From 06eba0151c9e575c99031c567c7ef7764a49a6f6 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 7 May 2024 03:50:17 -0500 Subject: [PATCH 01/22] chore(meshwide): Implement mesh wide map (#416) Implements mesh wide map. Fixes https://github.com/libremesh/lime-app/issues/394. It implements bunch of new features such: - [x] It show geolocated nodes on the map, using shared stated nodes package - [x] Show bat links, and wifi links between this nodes, using shared state bat links and wifi inks data types - [x] Monitor the state of the nodes and the links - [x] You can mark the actual state of the shared state data type as the reference state to monitor changes - [x] It inform you of errors on the shared state, such non located nodes, missing shared states packages or the reference state is not set - [x] You can switch between layers to see. --- jest.config.js | 3 + package-lock.json | 7978 +++++++++++++---- package.json | 2 + plugins/lime-plugin-locate/index.ts | 0 plugins/lime-plugin-locate/src/locateMenu.js | 6 +- plugins/lime-plugin-mesh-wide/index.ts | 10 + .../src/components/Components.tsx | 58 + .../components/FeatureDetail/LinkDetail.tsx | 262 + .../components/FeatureDetail/NodeDetail.tsx | 149 + .../FeatureDetail/SetReferenceStateBtn.tsx | 69 + .../FeatureDetail/ShowErrorsDetail.tsx | 102 + .../src/components/FeatureDetail/index.tsx | 81 + .../src/components/Map/FloatingAlert.tsx | 61 + .../src/components/Map/LinkLine.tsx | 77 + .../src/components/Map/NodeMarker.tsx | 65 + .../src/components/Map/style.less | 69 + .../components/configPage/ConfigSection.tsx | 107 + .../src/components/configPage/MeshStatus.tsx | 36 + .../src/components/configPage/OptionForm.tsx | 134 + .../src/components/configPage/modals.tsx | 109 + .../src/containers/Map.spec.tsx | 31 + .../src/containers/Map.tsx | 112 + .../src/containers/MapLayers/LinksLayers.tsx | 83 + .../src/containers/MapLayers/NodesLayer.tsx | 39 + .../SelectedFeatureBottomSheet.spec.tsx | 117 + .../containers/SelectedFeatureBottomSheet.tsx | 45 + .../src/hooks/useLocatedLinks.tsx | 189 + .../src/hooks/useMeshWideDataErrors.tsx | 83 + .../src/hooks/useNodes.tsx | 143 + .../src/hooks/useSingleNodeErrors.tsx | 20 + .../src/icons/SuccessIcon.tsx | 3 + .../src/icons/errorIcon.tsx | 11 + .../lime-plugin-mesh-wide/src/icons/power.tsx | 15 + .../src/icons/warningIcon.tsx | 16 + .../src/lib/links/PointToPointLink.ts | 134 + .../src/lib/links/getLinksCoordinates.spec.ts | 33 + .../src/lib/links/getLinksCoordinates.ts | 99 + .../src/lib/links/processLinkErrors.ts | 129 + .../src/lib/nodes/processErrors.ts | 32 + .../lime-plugin-mesh-wide/src/lib/utils.ts | 34 + .../lime-plugin-mesh-wide/src/meshWideApi.ts | 21 + .../src/meshWideMenu.tsx | 12 + .../src/meshWideMocks.tsx | 1150 +++ .../src/meshWidePage.tsx | 65 + .../src/meshWideQueries.tsx | 179 + .../src/meshWideQueriesKeys.tsx | 30 + .../src/meshWideTypes.tsx | 200 + .../src/screens/configPage.tsx | 44 + .../src/components/config/config.js | 33 - .../src/components/config/config.tsx | 48 + src/components/Modal/FullScreenModal.tsx | 43 + src/components/Modal/Modal.tsx | 204 + src/components/app.tsx | 14 +- src/components/bottom-sheet/BottomSheet.tsx | 299 + src/components/bottom-sheet/credits.md | 3 + src/components/bottom-sheet/index.ts | 1 + src/components/bottom-sheet/style.less | 92 + src/components/bottom-sheet/utils.ts | 44 + src/components/buttons/button.tsx | 87 + src/components/buttons/floatting-button.tsx | 24 + src/components/collapsible/index.js | 30 +- src/components/collapsible/style.less | 5 - src/components/divider/index.tsx | 10 + src/components/icons/SvgIcon.tsx | 42 + src/components/icons/bin.tsx | 17 + src/components/icons/edit.tsx | 17 + src/components/icons/teenny/chevrons.jsx | 31 + src/components/icons/teenny/pin.jsx | 22 + src/components/inputs/InputField.tsx | 31 + src/components/toast/index.tsx | 75 +- src/components/toast/style.less | 30 +- src/components/toast/toastProvider.tsx | 38 + src/config.ts | 2 + src/utils/constants.js | 2 + src/utils/useSharedData.ts | 17 + src/utils/utils.tsx | 3 + tailwind.config.js | 25 +- tsconfig.json | 3 +- 78 files changed, 11955 insertions(+), 1784 deletions(-) mode change 100755 => 100644 plugins/lime-plugin-locate/index.ts create mode 100644 plugins/lime-plugin-mesh-wide/index.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/components/Components.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/Map/style.less create mode 100644 plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/containers/Map.spec.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/containers/Map.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.spec.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/hooks/useNodes.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/icons/power.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/icons/warningIcon.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.spec.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/lib/utils.ts create mode 100644 plugins/lime-plugin-mesh-wide/src/meshWideApi.ts create mode 100755 plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx delete mode 100644 plugins/lime-plugin-node-admin/src/components/config/config.js create mode 100644 plugins/lime-plugin-node-admin/src/components/config/config.tsx create mode 100644 src/components/Modal/FullScreenModal.tsx create mode 100644 src/components/Modal/Modal.tsx create mode 100644 src/components/bottom-sheet/BottomSheet.tsx create mode 100644 src/components/bottom-sheet/credits.md create mode 100644 src/components/bottom-sheet/index.ts create mode 100644 src/components/bottom-sheet/style.less create mode 100644 src/components/bottom-sheet/utils.ts create mode 100644 src/components/buttons/button.tsx create mode 100644 src/components/buttons/floatting-button.tsx delete mode 100644 src/components/collapsible/style.less create mode 100644 src/components/divider/index.tsx create mode 100644 src/components/icons/SvgIcon.tsx create mode 100644 src/components/icons/bin.tsx create mode 100644 src/components/icons/edit.tsx create mode 100644 src/components/icons/teenny/chevrons.jsx create mode 100644 src/components/icons/teenny/pin.jsx create mode 100644 src/components/inputs/InputField.tsx create mode 100644 src/components/toast/toastProvider.tsx create mode 100644 src/utils/useSharedData.ts create mode 100644 src/utils/utils.tsx diff --git a/jest.config.js b/jest.config.js index 822a0cd07..8cfa47396 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,8 @@ /* eslint @typescript-eslint/no-var-requires: "off" */ const preactPreset = require("jest-preset-preact"); +const esModules = ["@react-leaflet", "react-leaflet"].join("|"); + /** @returns {Promise} */ module.exports = { preset: "jest-preset-preact", @@ -22,4 +24,5 @@ module.exports = { "^.+\\.[tj]sx?$": "babel-jest", }, clearMocks: true, + transformIgnorePatterns: [`/node_modules/(?!${esModules})`], }; diff --git a/package-lock.json b/package-lock.json index 060c516eb..dbe932a19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,10 +21,12 @@ "react-leaflet": "^4.2.1", "react-redux": "^8.0.4", "react-router-redux": "^4.0.8", + "react-spring": "^9.7.1", "react-use": "^17.4.0", "redux": "^4.2.0", "redux-observable": "^2.0.0", "simple-color-scale": "^1.0.1", + "tailwindcss": "^3.2.6", "timeago.js": "^4.0.2" }, "devDependencies": { @@ -91,7 +93,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -101,119 +102,45 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz", - "integrity": "sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz", - "integrity": "sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.0", - "@babel/helper-compilation-targets": "^7.19.1", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0", - "convert-source-map": "^1.7.0", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -223,11 +150,15 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -269,14 +200,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -284,26 +214,24 @@ } }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -313,7 +241,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, "dependencies": { "@babel/helper-explode-assignable-expression": "^7.18.6", "@babel/types": "^7.18.9" @@ -323,45 +250,55 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz", - "integrity": "sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==", - "dev": true, + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dependencies": { - "@babel/compat-data": "^7.19.1", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", + "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -370,11 +307,18 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "regexpu-core": "^5.1.0" @@ -390,7 +334,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.17.7", "@babel/helper-plugin-utils": "^7.16.7", @@ -407,7 +350,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -416,7 +358,6 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -425,7 +366,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, @@ -437,7 +377,6 @@ "version": "7.23.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, "dependencies": { "@babel/template": "^7.22.15", "@babel/types": "^7.23.0" @@ -450,7 +389,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -459,79 +397,72 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", - "dev": true, + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dependencies": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dev": true, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -541,40 +472,38 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", - "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", - "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "dependencies": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -584,7 +513,6 @@ "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -596,7 +524,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -605,7 +532,6 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -614,49 +540,45 @@ "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", - "dev": true, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -666,7 +588,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -678,7 +599,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -692,7 +612,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -700,14 +619,12 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -716,7 +633,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -725,7 +641,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -734,10 +649,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -749,7 +663,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -764,7 +677,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", @@ -781,7 +693,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz", "integrity": "sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-plugin-utils": "^7.19.0", @@ -799,7 +710,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -815,7 +725,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", @@ -851,7 +760,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -867,7 +775,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.23.3.tgz", "integrity": "sha512-Q23MpLZfSGZL1kU7fWqV262q65svLSCIP5kZ/JCW/rKTCm/FrLjpvEd2kfUYMVeHh4QhV/xzyoRAHWrAZJrE3Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-export-default-from": "^7.23.3" @@ -883,7 +790,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -899,7 +805,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -915,7 +820,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -931,7 +835,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -947,7 +850,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -960,16 +862,16 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", - "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", - "dev": true, + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", "dependencies": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" + "@babel/plugin-transform-parameters": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -982,7 +884,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -995,13 +896,13 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", - "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", - "dev": true, + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1015,7 +916,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1031,7 +931,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-create-class-features-plugin": "^7.18.6", @@ -1049,7 +948,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1065,7 +963,6 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1089,7 +986,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -1101,7 +997,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1131,7 +1026,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1143,7 +1037,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.23.3.tgz", "integrity": "sha512-KeENO5ck1IeZ/l2lFZNy+mpobV3D2Zy5C1YFnWm+YuY5mQiAWc4yAp13dqgguwsBsFVLh4LPCEqCa5qW13N+hw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1158,7 +1051,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -1170,7 +1062,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1185,7 +1076,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1212,7 +1102,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1224,7 +1113,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1239,7 +1127,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1251,7 +1138,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1263,7 +1149,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1275,7 +1160,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1287,7 +1171,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1299,7 +1182,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1311,7 +1193,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1326,7 +1207,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1341,7 +1221,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1356,7 +1235,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1368,14 +1246,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1388,7 +1265,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1403,7 +1279,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1418,7 +1293,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz", "integrity": "sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-compilation-targets": "^7.19.0", @@ -1441,7 +1315,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -1450,7 +1323,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1462,12 +1334,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.18.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", - "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", + "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1480,7 +1351,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1496,7 +1366,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1511,7 +1380,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1527,7 +1395,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-flow": "^7.23.3" @@ -1543,7 +1410,6 @@ "version": "7.18.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1558,7 +1424,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-function-name": "^7.18.9", @@ -1575,7 +1440,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1590,7 +1454,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1605,7 +1468,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", @@ -1622,7 +1484,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", @@ -1640,7 +1501,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz", "integrity": "sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==", - "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-module-transforms": "^7.19.0", @@ -1659,7 +1519,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1675,7 +1534,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0" @@ -1691,7 +1549,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1721,7 +1578,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-replace-supers": "^7.18.6" @@ -1734,12 +1590,45 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", + "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", + "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -1752,7 +1641,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1767,7 +1655,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1782,7 +1669,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz", "integrity": "sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-module-imports": "^7.18.6", @@ -1812,6 +1698,36 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", + "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz", + "integrity": "sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-pure-annotations": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", @@ -1832,7 +1748,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "regenerator-transform": "^0.15.0" @@ -1848,7 +1763,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1859,11 +1773,94 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", + "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-plugin-utils": "^7.24.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", + "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", + "peer": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", + "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.1", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", + "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "peer": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1878,7 +1875,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz", "integrity": "sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.19.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" @@ -1894,7 +1890,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -1909,7 +1904,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1924,7 +1918,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1939,7 +1932,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.1.tgz", "integrity": "sha512-+ILcOU+6mWLlvCwnL920m2Ow3wWx3Wo8n2t5aROQmV55GZt+hOiLvBaa3DNzRjSEHa1aauRs4/YLmkCfFkhhRQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0", @@ -1956,7 +1948,6 @@ "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.9" }, @@ -1971,7 +1962,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1987,7 +1977,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.1.tgz", "integrity": "sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.19.1", "@babel/helper-compilation-targets": "^7.19.1", @@ -2076,7 +2065,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -2085,7 +2073,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", @@ -2102,7 +2089,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", @@ -2138,7 +2124,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", @@ -2155,7 +2140,6 @@ "version": "7.23.7", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", - "dev": true, "dependencies": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", @@ -2174,7 +2158,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^2.0.0", @@ -2188,7 +2171,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "dependencies": { "locate-path": "^3.0.0" }, @@ -2200,7 +2182,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -2213,7 +2194,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -2226,7 +2206,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -2241,7 +2220,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "dependencies": { "p-limit": "^2.0.0" }, @@ -2253,7 +2231,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, "engines": { "node": ">=4" } @@ -2262,7 +2239,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "engines": { "node": ">=6" } @@ -2271,7 +2247,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "dependencies": { "find-up": "^3.0.0" }, @@ -2283,7 +2258,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "bin": { "semver": "bin/semver" } @@ -2300,33 +2274,31 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", - "dev": true, + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2338,16 +2310,14 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", - "dev": true, + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -2445,6 +2415,21 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "peer": true + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "peer": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", @@ -2497,6 +2482,15 @@ "node": ">=6.9.0" } }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2857,6 +2851,18 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/environment": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", @@ -3261,12 +3267,11 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3410,12 +3415,11 @@ } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -3430,7 +3434,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3443,16 +3446,14 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -3461,7 +3462,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -3471,7 +3471,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -3484,14 +3483,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", - "dev": true, + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -4172,6 +4169,999 @@ "react-dom": "^18.0.0" } }, + "node_modules/@react-native-community/cli": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.6.tgz", + "integrity": "sha512-647OSi6xBb8FbwFqX9zsJxOzu685AWtrOUWHfOkbKD+5LOpGORw+GQo0F9rWZnB68rLQyfKUZWJeaD00pGv5fw==", + "peer": true, + "dependencies": { + "@react-native-community/cli-clean": "12.3.6", + "@react-native-community/cli-config": "12.3.6", + "@react-native-community/cli-debugger-ui": "12.3.6", + "@react-native-community/cli-doctor": "12.3.6", + "@react-native-community/cli-hermes": "12.3.6", + "@react-native-community/cli-plugin-metro": "12.3.6", + "@react-native-community/cli-server-api": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-types": "12.3.6", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "deepmerge": "^4.3.0", + "execa": "^5.0.0", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.2", + "semver": "^7.5.2" + }, + "bin": { + "react-native": "build/bin.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native-community/cli-clean": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.6.tgz", + "integrity": "sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==", + "peer": true, + "dependencies": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "execa": "^5.0.0" + } + }, + "node_modules/@react-native-community/cli-config": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.6.tgz", + "integrity": "sha512-JGWSYQ9EAK6m2v0abXwFLEfsqJ1zkhzZ4CV261QZF9MoUNB6h57a274h1MLQR9mG6Tsh38wBUuNfEPUvS1vYew==", + "peer": true, + "dependencies": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "cosmiconfig": "^5.1.0", + "deepmerge": "^4.3.0", + "glob": "^7.1.3", + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "peer": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "peer": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "peer": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native-community/cli-config/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native-community/cli-debugger-ui": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.6.tgz", + "integrity": "sha512-SjUKKsx5FmcK9G6Pb6UBFT0s9JexVStK5WInmANw75Hm7YokVvHEgtprQDz2Uvy5znX5g2ujzrkIU//T15KQzA==", + "peer": true, + "dependencies": { + "serve-static": "^1.13.1" + } + }, + "node_modules/@react-native-community/cli-doctor": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.6.tgz", + "integrity": "sha512-fvBDv2lTthfw4WOQKkdTop2PlE9GtfrlNnpjB818MhcdEnPjfQw5YaTUcnNEGsvGomdCs1MVRMgYXXwPSN6OvQ==", + "peer": true, + "dependencies": { + "@react-native-community/cli-config": "12.3.6", + "@react-native-community/cli-platform-android": "12.3.6", + "@react-native-community/cli-platform-ios": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "deepmerge": "^4.3.0", + "envinfo": "^7.10.0", + "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "peer": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@react-native-community/cli-hermes": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.6.tgz", + "integrity": "sha512-sNGwfOCl8OAIjWCkwuLpP8NZbuO0dhDI/2W7NeOGDzIBsf4/c4MptTrULWtGIH9okVPLSPX0NnRyGQ+mSwWyuQ==", + "peer": true, + "dependencies": { + "@react-native-community/cli-platform-android": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "hermes-profile-transformer": "^0.0.6" + } + }, + "node_modules/@react-native-community/cli-platform-android": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.6.tgz", + "integrity": "sha512-DeDDAB8lHpuGIAPXeeD9Qu2+/wDTFPo99c8uSW49L0hkmZJixzvvvffbGQAYk32H0TmaI7rzvzH+qzu7z3891g==", + "peer": true, + "dependencies": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.2.4", + "glob": "^7.1.3", + "logkitty": "^0.7.1" + } + }, + "node_modules/@react-native-community/cli-platform-ios": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.6.tgz", + "integrity": "sha512-3eZ0jMCkKUO58wzPWlvAPRqezVKm9EPZyaPyHbRPWU8qw7JqkvnRlWIaYDGpjCJgVW4k2hKsEursLtYKb188tg==", + "peer": true, + "dependencies": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.0.12", + "glob": "^7.1.3", + "ora": "^5.4.1" + } + }, + "node_modules/@react-native-community/cli-plugin-metro": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.6.tgz", + "integrity": "sha512-3jxSBQt4fkS+KtHCPSyB5auIT+KKIrPCv9Dk14FbvOaEh9erUWEm/5PZWmtboW1z7CYeNbFMeXm9fM2xwtVOpg==", + "peer": true + }, + "node_modules/@react-native-community/cli-server-api": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.6.tgz", + "integrity": "sha512-80NIMzo8b2W+PL0Jd7NjiJW9mgaT8Y8wsIT/lh6mAvYH7mK0ecDJUYUTAAv79Tbo1iCGPAr3T295DlVtS8s4yQ==", + "peer": true, + "dependencies": { + "@react-native-community/cli-debugger-ui": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^7.5.1" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "peer": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@react-native-community/cli-tools": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.6.tgz", + "integrity": "sha512-FPEvZn19UTMMXUp/piwKZSh8cMEfO8G3KDtOwo53O347GTcwNrKjgZGtLSPELBX2gr+YlzEft3CoRv2Qmo83fQ==", + "peer": true, + "dependencies": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "node-fetch": "^2.6.0", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "peer": true, + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-types": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.6.tgz", + "integrity": "sha512-xPqTgcUtZowQ8WKOkI9TLGBwH2bGggOC4d2FFaIRST3gTcjrEeGRNeR5aXCzJFIgItIft8sd7p2oKEdy90+01Q==", + "peer": true, + "dependencies": { + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "peer": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/@react-native-community/cli/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", + "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", + "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", + "peer": true, + "dependencies": { + "@react-native/codegen": "0.73.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.73.21", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", + "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", + "peer": true, + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "@react-native/babel-plugin-codegen": "0.73.4", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/babel-preset/node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", + "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", + "peer": true, + "dependencies": { + "@babel/parser": "^7.20.0", + "flow-parser": "^0.206.0", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jscodeshift": "^0.14.0", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/codegen/node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "peer": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native/codegen/node_modules/flow-parser": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@react-native/codegen/node_modules/jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "peer": true, + "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/codegen/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@react-native/codegen/node_modules/recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "peer": true, + "dependencies": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@react-native/codegen/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.73.17", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.17.tgz", + "integrity": "sha512-F3PXZkcHg+1ARIr6FRQCQiB7ZAA+MQXGmq051metRscoLvgYJwj7dgC8pvgy0kexzUkHu5BNKrZeySzUft3xuQ==", + "peer": true, + "dependencies": { + "@react-native-community/cli-server-api": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "@react-native/dev-middleware": "0.73.8", + "@react-native/metro-babel-transformer": "0.73.15", + "chalk": "^4.0.0", + "execa": "^5.1.1", + "metro": "^0.80.3", + "metro-config": "^0.80.3", + "metro-core": "^0.80.3", + "node-fetch": "^2.2.0", + "readline": "^1.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", + "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.73.8", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", + "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", + "peer": true, + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.73.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^1.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "open": "^7.0.3", + "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", + "ws": "^6.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "peer": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", + "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", + "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.73.15", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", + "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", + "peer": true, + "dependencies": { + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.73.21", + "hermes-parser": "0.15.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", + "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "peer": true + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", + "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react-native": "*" + } + }, + "node_modules/@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "dependencies": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/konva": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/konva/-/konva-9.7.3.tgz", + "integrity": "sha512-R9sY6SiPGYqz1383P5qppg5z57YfChVknOC1UxxaGxpw+WiZa8fZ4zmZobslrw+os3/+HAXZv8O+EvU/nQpf7g==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "konva": ">=2.6", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-konva": "^16.8.0 || ^16.8.7-0 || ^16.9.0-0 || ^16.10.1-0 || ^16.12.0-0 || ^16.13.0-0 || ^17.0.0-0 || ^17.0.1-0 || ^17.0.2-0 || ^18.0.0-0" + } + }, + "node_modules/@react-spring/native": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/native/-/native-9.7.3.tgz", + "integrity": "sha512-4mpxX3FuEBCUT6ae2fjhxcJW6bhr2FBwFf274eXB7n+U30Gdg8Wo2qYwcUnmiAA0S3dvP8vLTazx3+CYWFShnA==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || >=17.0.0 || >=18.0.0", + "react-native": ">=0.58" + } + }, + "node_modules/@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "dependencies": { + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/three": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.7.3.tgz", + "integrity": "sha512-Q1p512CqUlmMK8UMBF/Rj79qndhOWq4XUTayxMP9S892jiXzWQuj+xC3Xvm59DP/D4JXusXpxxqfgoH+hmOktA==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "@react-three/fiber": ">=6.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "three": ">=0.126" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "node_modules/@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/zdog": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/zdog/-/zdog-9.7.3.tgz", + "integrity": "sha512-L+yK/1PvNi9n8cldiJ309k4LdxcPkeWE0W18l1zrP1IBIyd5NB5EPA8DMsGr9gtNnnIujtEzZk+4JIOjT8u/tw==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-zdog": ">=1.0", + "zdog": ">=1.0" + } + }, + "node_modules/@react-three/fiber": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.16.1.tgz", + "integrity": "sha512-Rgjn+xcR+6Do2Ic4b6RROIvCGs3RhoVJEamfmtMSfkgIRH3PeiPdqRxcfJlO9y6KDvYA5fIUGruz9h/sTeLlpw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.17.8", + "@types/react-reconciler": "^0.26.7", + "@types/webxr": "*", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "its-fine": "^1.0.6", + "react-reconciler": "^0.27.0", + "react-use-measure": "^2.1.1", + "scheduler": "^0.21.0", + "suspend-react": "^0.1.3", + "zustand": "^3.7.1" + }, + "peerDependencies": { + "expo": ">=43.0", + "expo-asset": ">=8.4", + "expo-file-system": ">=11.0", + "expo-gl": ">=11.0", + "react": ">=18.0", + "react-dom": ">=18.0", + "react-native": ">=0.64", + "three": ">=0.133" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-asset": { + "optional": true + }, + "expo-file-system": { + "optional": true + }, + "expo-gl": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@react-three/fiber/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/@react-three/fiber/node_modules/scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4245,11 +5235,31 @@ "rollup": "^1.20.0||^2.0.0" } }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "peer": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "peer": true + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "peer": true + }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@sindresorhus/is": { "version": "0.14.0", @@ -8144,14 +9154,12 @@ "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -8160,7 +9168,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } @@ -8237,8 +9244,7 @@ "node_modules/@types/node": { "version": "18.7.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.21.tgz", - "integrity": "sha512-rLFzK5bhM0YPyCoTC8bolBjMk7bwnZ8qeZUBslBfjZQou2ssJdWslx9CZ8DGM+Dx7QXQiiTVZ/6QO6kwtHkZCA==", - "dev": true + "integrity": "sha512-rLFzK5bhM0YPyCoTC8bolBjMk7bwnZ8qeZUBslBfjZQou2ssJdWslx9CZ8DGM+Dx7QXQiiTVZ/6QO6kwtHkZCA==" }, "node_modules/@types/node-fetch": { "version": "2.6.11", @@ -8336,6 +9342,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-reconciler": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz", + "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==", + "peer": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -8399,8 +9414,7 @@ "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, "node_modules/@types/tapable": { "version": "1.0.8", @@ -8483,6 +9497,12 @@ "node": ">= 8" } }, + "node_modules/@types/webxr": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.14.tgz", + "integrity": "sha512-UEMMm/Xn3DtEa+gpzUrOcDj+SJS1tk5YodjwOxcqStNhCfPcwgyC5Srg2ToVKyg2Fhq16Ffpb0UWUQHqoT9AMA==", + "peer": true + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -8496,7 +9516,6 @@ "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, "dependencies": { "@types/yargs-parser": "*" } @@ -8504,8 +9523,7 @@ "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.46.0", @@ -9336,11 +10354,22 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -9353,7 +10382,6 @@ "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -9574,6 +10602,12 @@ "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==", "dev": true }, + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "peer": true + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -9619,6 +10653,103 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "peer": true, + "dependencies": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-fragments/node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-fragments/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ansi-fragments/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "peer": true + }, + "node_modules/ansi-fragments/node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "peer": true + }, + "node_modules/ansi-fragments/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-fragments/node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-fragments/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "peer": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -9635,7 +10766,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -9644,7 +10774,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -9674,7 +10803,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -9689,6 +10817,12 @@ "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", "dev": true }, + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "peer": true + }, "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -9941,6 +11075,12 @@ "node": ">=8" } }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "peer": true + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -10056,8 +11196,7 @@ "node_modules/async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "node_modules/asynckit": { "version": "0.4.0", @@ -10235,7 +11374,6 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, "peerDependencies": { "@babel/core": "^7.0.0-0" } @@ -10424,7 +11562,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, "dependencies": { "object.assign": "^4.1.0" } @@ -10507,7 +11644,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.17.7", "@babel/helper-define-polyfill-provider": "^0.3.3", @@ -10521,7 +11657,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -10530,7 +11665,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.3.3", "core-js-compat": "^3.25.1" @@ -10543,7 +11677,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.3.3" }, @@ -10557,6 +11690,15 @@ "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", "dev": true }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, "node_modules/babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -10702,8 +11844,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base": { "version": "0.11.2", @@ -10739,7 +11880,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -10855,7 +11995,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -11020,7 +12159,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11030,7 +12168,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -11150,7 +12287,6 @@ "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -11182,7 +12318,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, "dependencies": { "node-int64": "^0.4.0" } @@ -11191,7 +12326,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -11223,8 +12357,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-xor": { "version": "1.0.3", @@ -11263,7 +12396,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -11372,7 +12504,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -11397,7 +12528,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "dev": true, "dependencies": { "callsites": "^2.0.0" }, @@ -11409,7 +12539,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", - "dev": true, "engines": { "node": ">=4" } @@ -11418,7 +12547,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "dev": true, "dependencies": { "caller-callsite": "^2.0.0" }, @@ -11449,7 +12577,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, "engines": { "node": ">=6" } @@ -11503,7 +12630,6 @@ "version": "1.0.30001588", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz", "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -11560,7 +12686,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -11665,6 +12790,24 @@ "node": ">=10" } }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "peer": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -11674,6 +12817,20 @@ "node": ">=6.0" } }, + "node_modules/chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", + "peer": true, + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, "node_modules/ci-env": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/ci-env/-/ci-env-1.17.0.tgz", @@ -11683,8 +12840,7 @@ "node_modules/ci-info": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", - "dev": true + "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==" }, "node_modules/cipher-base": { "version": "1.0.4", @@ -11837,7 +12993,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "dependencies": { "restore-cursor": "^3.1.0" }, @@ -11849,7 +13004,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", - "dev": true, "engines": { "node": ">=6" }, @@ -12014,7 +13168,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, "engines": { "node": ">=0.8" } @@ -12023,7 +13176,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -12037,7 +13189,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -12195,7 +13346,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -12206,8 +13356,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-string": { "version": "1.9.1", @@ -12286,11 +13435,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "peer": true + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/common-tags": { "version": "1.8.2", @@ -12304,8 +13458,7 @@ "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, "node_modules/compare-func": { "version": "2.0.0", @@ -12327,7 +13480,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -12339,7 +13491,6 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -12398,7 +13549,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -12406,8 +13556,7 @@ "node_modules/compression/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/compressorjs": { "version": "1.1.1", @@ -12421,8 +13570,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -12480,6 +13628,21 @@ "node": ">=8" } }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -12489,6 +13652,60 @@ "node": ">=0.8" } }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "node_modules/connect/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -13508,12 +14725,11 @@ "hasInstallScript": true }, "node_modules/core-js-compat": { - "version": "3.25.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.3.tgz", - "integrity": "sha512-xVtYpJQ5grszDHEUU9O7XbjjcZ0ccX3LgQsyqSvTnjX97ZqEgn9F5srmrwwwMtbKzDllyFPL+O+2OFMl1lU4TQ==", - "dev": true, + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", + "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", "dependencies": { - "browserslist": "^4.21.4" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -13983,7 +15199,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -14612,11 +15827,22 @@ "node": "*" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "peer": true + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "peer": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -14633,7 +15859,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -14712,10 +15937,9 @@ } }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "engines": { "node": ">=0.10.0" } @@ -14754,7 +15978,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", - "dev": true, "dependencies": { "clone": "^1.0.2" } @@ -14769,7 +15992,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -14795,7 +16017,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -14845,15 +16066,34 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "peer": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } }, + "node_modules/deprecated-react-native-prop-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", + "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", + "peer": true, + "dependencies": { + "@react-native/normalize-colors": "^0.73.0", + "invariant": "^2.2.4", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -14868,7 +16108,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -15335,8 +16574,7 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { "version": "3.1.8", @@ -15366,8 +16604,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.677", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.677.tgz", - "integrity": "sha512-erDa3CaDzwJOpyvfKhOiJjBVNnMM0qxHq47RheVVwsSQrgBA9ZSGV9kdaOfZDPXcHzhG7lBxhj6A7KvfLJBd6Q==", - "dev": true + "integrity": "sha512-erDa3CaDzwJOpyvfKhOiJjBVNnMM0qxHq47RheVVwsSQrgBA9ZSGV9kdaOfZDPXcHzhG7lBxhj6A7KvfLJBd6Q==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -15411,8 +16648,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/emojis-list": { "version": "3.0.0", @@ -15427,7 +16663,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -15502,10 +16737,9 @@ } }, "node_modules/envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true, + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==", "bin": { "envinfo": "dist/cli.js" }, @@ -15529,7 +16763,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -15542,6 +16775,19 @@ "stackframe": "^1.3.4" } }, + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "peer": true, + "dependencies": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/es-abstract": { "version": "1.22.4", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", @@ -15607,7 +16853,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -15619,7 +16864,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -15709,7 +16953,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -15726,14 +16969,12 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -16233,11 +17474,19 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, "engines": { "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -16273,7 +17522,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -16755,6 +18003,28 @@ "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" }, + "node_modules/fast-xml-parser": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz", + "integrity": "sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "peer": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastest-stable-stringify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", @@ -16785,7 +18055,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, "dependencies": { "bser": "2.1.1" } @@ -17068,7 +18337,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -17130,7 +18398,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -17161,6 +18428,12 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "peer": true + }, "node_modules/flow-parser": { "version": "0.229.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.229.0.tgz", @@ -17412,7 +18685,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -17455,7 +18727,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -17522,14 +18793,12 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -17543,7 +18812,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17605,7 +18873,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -17614,7 +18881,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -17623,7 +18889,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -17709,7 +18974,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -18214,7 +19478,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -18351,7 +19614,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -18396,8 +19658,7 @@ "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -18489,7 +19750,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -18529,7 +19789,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -18562,7 +19821,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -18574,7 +19832,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -18586,7 +19843,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -18735,7 +19991,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -18861,6 +20116,42 @@ "he": "bin/he" } }, + "node_modules/hermes-estree": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", + "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", + "peer": true + }, + "node_modules/hermes-parser": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", + "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", + "peer": true, + "dependencies": { + "hermes-estree": "0.15.0" + } + }, + "node_modules/hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", + "peer": true, + "dependencies": { + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-profile-transformer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "peer": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -19189,7 +20480,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -19321,7 +20611,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "engines": { "node": ">=10.17.0" } @@ -19495,7 +20784,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -19578,7 +20866,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, "engines": { "node": ">=0.8.19" } @@ -19608,7 +20895,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -19807,8 +21093,7 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "node_modules/is-bigint": { "version": "1.0.4", @@ -19915,7 +21200,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -19978,7 +21262,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -19987,7 +21270,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, "bin": { "is-docker": "cli.js" }, @@ -20058,7 +21340,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -20120,7 +21401,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, "engines": { "node": ">=8" } @@ -20168,7 +21448,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -20286,7 +21565,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -20367,7 +21645,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, "engines": { "node": ">=10" }, @@ -20432,7 +21709,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -20454,8 +21730,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isobject": { "version": "3.0.1", @@ -20578,6 +21853,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/its-fine": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.1.3.tgz", + "integrity": "sha512-mncCA+yb6tuh5zK26cHqKlsSyxm4zdm4YgJpxycyx6p9fgxgK5PLu3iDVpKhzTn57Yrv3jk/r0aK0RFTT1OjFw==", + "peer": true, + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, + "node_modules/its-fine/node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "peer": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/jake": { "version": "10.8.5", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", @@ -21744,10 +23040,9 @@ } }, "node_modules/jest-get-type": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", - "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -22097,18 +23392,17 @@ } }, "node_modules/jest-message-util": { - "version": "29.2.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.1.tgz", - "integrity": "sha512-Dx5nEjw9V8C1/Yj10S/8ivA8F439VS8vTq1L7hEgwHFn9ovSKNpYW/kwNh7UglaEgXO42XxzKJB+2x0nSglFVw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.2.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.2.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -22839,12 +24133,11 @@ "dev": true }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -23060,6 +24353,19 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joi": { + "version": "17.12.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", + "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "peer": true, + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-cookie": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", @@ -23103,6 +24409,18 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "node_modules/jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "peer": true + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "peer": true + }, "node_modules/jscodeshift": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", @@ -23362,7 +24680,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -23379,8 +24696,7 @@ "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -23416,7 +24732,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -23428,7 +24743,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -23517,7 +24831,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -23526,7 +24839,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, "engines": { "node": ">=6" } @@ -23540,6 +24852,26 @@ "node": ">= 8" } }, + "node_modules/konva": { + "version": "9.3.6", + "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.6.tgz", + "integrity": "sha512-dqR8EbcM0hjuilZCBP6xauQ5V3kH3m9kBcsDkqPypQuRgsXbcXUrxqYxhNbdvKZpYNW8Amq94jAD/C0NY3qfBQ==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "peer": true + }, "node_modules/last-call-webpack-plugin": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", @@ -23709,7 +25041,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, "engines": { "node": ">=6" } @@ -23727,6 +25058,31 @@ "node": ">= 0.8.0" } }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "peer": true, + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, "node_modules/lilconfig": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", @@ -24030,7 +25386,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -24049,8 +25404,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.get": { "version": "4.4.2", @@ -24088,6 +25442,12 @@ "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", "dev": true }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "peer": true + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -24098,7 +25458,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -24142,6 +25501,138 @@ "node": ">=8" } }, + "node_modules/logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "peer": true, + "dependencies": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "bin": { + "logkitty": "bin/logkitty.js" + } + }, + "node_modules/logkitty/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/logkitty/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logkitty/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "peer": true + }, + "node_modules/logkitty/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "peer": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "peer": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -24172,7 +25663,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -24238,7 +25728,6 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, "dependencies": { "tmpl": "1.0.5" } @@ -24289,6 +25778,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "peer": true + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -24388,6 +25883,12 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "peer": true + }, "node_modules/memoizerific": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", @@ -24484,8 +25985,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -24511,6 +26011,602 @@ "node": ">= 0.6" } }, + "node_modules/metro": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.8.tgz", + "integrity": "sha512-in7S0W11mg+RNmcXw+2d9S3zBGmCARDxIwoXJAmLUQOQoYsRP3cpGzyJtc7WOw8+FXfpgXvceD0u+PZIHXEL7g==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.20.1", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.80.8", + "metro-cache": "0.80.8", + "metro-cache-key": "0.80.8", + "metro-config": "0.80.8", + "metro-core": "0.80.8", + "metro-file-map": "0.80.8", + "metro-resolver": "0.80.8", + "metro-runtime": "0.80.8", + "metro-source-map": "0.80.8", + "metro-symbolicate": "0.80.8", + "metro-transform-plugins": "0.80.8", + "metro-transform-worker": "0.80.8", + "mime-types": "^2.1.27", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "rimraf": "^3.0.2", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.1", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.8.tgz", + "integrity": "sha512-TTzNwRZb2xxyv4J/+yqgtDAP2qVqH3sahsnFu6Xv4SkLqzrivtlnyUbaeTdJ9JjtADJUEjCbgbFgUVafrXdR9Q==", + "peer": true, + "dependencies": { + "@babel/core": "^7.20.0", + "hermes-parser": "0.20.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "peer": true + }, + "node_modules/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "peer": true, + "dependencies": { + "hermes-estree": "0.20.1" + } + }, + "node_modules/metro-cache": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.8.tgz", + "integrity": "sha512-5svz+89wSyLo7BxdiPDlwDTgcB9kwhNMfNhiBZPNQQs1vLFXxOkILwQiV5F2EwYT9DEr6OPZ0hnJkZfRQ8lDYQ==", + "peer": true, + "dependencies": { + "metro-core": "0.80.8", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-cache-key": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.8.tgz", + "integrity": "sha512-qWKzxrLsRQK5m3oH8ePecqCc+7PEhR03cJE6Z6AxAj0idi99dHOSitTmY0dclXVB9vP2tQIAE8uTd8xkYGk8fA==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.8.tgz", + "integrity": "sha512-VGQJpfJawtwRzGzGXVUoohpIkB0iPom4DmSbAppKfumdhtLA8uVeEPp2GM61kL9hRvdbMhdWA7T+hZFDlo4mJA==", + "peer": true, + "dependencies": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "jest-validate": "^29.6.3", + "metro": "0.80.8", + "metro-cache": "0.80.8", + "metro-core": "0.80.8", + "metro-runtime": "0.80.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/metro-config/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/metro-config/node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "peer": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "peer": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/metro-config/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "peer": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-config/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/metro-core": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.8.tgz", + "integrity": "sha512-g6lud55TXeISRTleW6SHuPFZHtYrpwNqbyFIVd9j9Ofrb5IReiHp9Zl8xkAfZQp8v6ZVgyXD7c130QTsCz+vBw==", + "peer": true, + "dependencies": { + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.80.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-file-map": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.8.tgz", + "integrity": "sha512-eQXMFM9ogTfDs2POq7DT2dnG7rayZcoEgRbHPXvhUWkVwiKkro2ngcBE++ck/7A36Cj5Ljo79SOkYwHaWUDYDw==", + "peer": true, + "dependencies": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/metro-file-map/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro-file-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-file-map/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "node_modules/metro-file-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.8.tgz", + "integrity": "sha512-y8sUFjVvdeUIINDuW1sejnIjkZfEF+7SmQo0EIpYbWmwh+kq/WMj74yVaBWuqNjirmUp1YNfi3alT67wlbBWBQ==", + "peer": true, + "dependencies": { + "terser": "^5.15.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-resolver": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.8.tgz", + "integrity": "sha512-JdtoJkP27GGoZ2HJlEsxs+zO7jnDUCRrmwXJozTlIuzLHMRrxgIRRby9fTCbMhaxq+iA9c+wzm3iFb4NhPmLbQ==", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-runtime": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.8.tgz", + "integrity": "sha512-2oScjfv6Yb79PelU1+p8SVrCMW9ZjgEiipxq7jMRn8mbbtWzyv3g8Mkwr+KwOoDFI/61hYPUbY8cUnu278+x1g==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.8.tgz", + "integrity": "sha512-+OVISBkPNxjD4eEKhblRpBf463nTMk3KMEeYS8Z4xM/z3qujGJGSsWUGRtH27+c6zElaSGtZFiDMshEb8mMKQg==", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "invariant": "^2.2.4", + "metro-symbolicate": "0.80.8", + "nullthrows": "^1.1.1", + "ob1": "0.80.8", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.8.tgz", + "integrity": "sha512-nwhYySk79jQhwjL9QmOUo4wS+/0Au9joEryDWw7uj4kz2yvw1uBjwmlql3BprQCBzRdB3fcqOP8kO8Es+vE31g==", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "metro-source-map": "0.80.8", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.8.tgz", + "integrity": "sha512-sSu8VPL9Od7w98MftCOkQ1UDeySWbsIAS5I54rW22BVpPnI3fQ42srvqMLaJUQPjLehUanq8St6OMBCBgH/UWw==", + "peer": true, + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.8.tgz", + "integrity": "sha512-+4FG3TQk3BTbNqGkFb2uCaxYTfsbuFOCKMMURbwu0ehCP8ZJuTUramkaNZoATS49NSAkRgUltgmBa4YaKZ5mqw==", + "peer": true, + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "metro": "0.80.8", + "metro-babel-transformer": "0.80.8", + "metro-cache": "0.80.8", + "metro-cache-key": "0.80.8", + "metro-minify-terser": "0.80.8", + "metro-source-map": "0.80.8", + "metro-transform-plugins": "0.80.8", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "peer": true + }, + "node_modules/metro/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/metro/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro/node_modules/hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "peer": true + }, + "node_modules/metro/node_modules/hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "peer": true, + "dependencies": { + "hermes-estree": "0.20.1" + } + }, + "node_modules/metro/node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "peer": true, + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/metro/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro/node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "peer": true + }, + "node_modules/metro/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/metro/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/metro/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/microevent.ts": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", @@ -24521,7 +26617,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -24553,7 +26648,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, "bin": { "mime": "cli.js" }, @@ -24565,7 +26659,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -24574,7 +26667,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -24586,7 +26678,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -24673,7 +26764,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -24817,7 +26907,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -24893,8 +26982,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -25034,7 +27122,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -25042,8 +27129,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/nested-error-stacks": { "version": "2.1.1", @@ -25066,11 +27152,25 @@ "lower-case": "^1.1.1" } }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "peer": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "peer": true + }, "node_modules/node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, "dependencies": { "minimatch": "^3.0.2" }, @@ -25082,7 +27182,6 @@ "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -25101,20 +27200,17 @@ "node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -25141,8 +27237,7 @@ "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-libs-browser": { "version": "2.2.1", @@ -25219,8 +27314,20 @@ "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "peer": true, + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -25247,7 +27354,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -25274,7 +27380,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "dependencies": { "path-key": "^3.0.0" }, @@ -25306,6 +27411,12 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "peer": true + }, "node_modules/num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -25327,11 +27438,19 @@ "node": "*" } }, + "node_modules/ob1": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.8.tgz", + "integrity": "sha512-QHJQk/lXMmAW8I7AIM3in1MSlwe1umR72Chhi8B7Xnq6mzjhBKkA6Fy/zAhQnGkA4S912EPCEvTij5yh+EQTAA==", + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -25443,7 +27562,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -25464,7 +27582,6 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -25580,7 +27697,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -25592,7 +27708,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -25601,7 +27716,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -25610,7 +27724,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -26221,7 +28334,6 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -26344,7 +28456,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -26359,7 +28470,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -26414,7 +28524,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -26579,7 +28688,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -26638,7 +28746,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "engines": { "node": ">=8" } @@ -26647,7 +28754,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -26656,7 +28762,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -26664,8 +28769,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "0.1.7", @@ -26713,14 +28817,12 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -26774,7 +28876,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, "engines": { "node": ">= 6" } @@ -28830,12 +30931,11 @@ } }, "node_modules/pretty-format": { - "version": "29.2.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.1.tgz", - "integrity": "sha512-Y41Sa4aLCtKAXvwuIpTvcFBkyeYp2gdFWzXGA+ZNES3VwURIB165XO/z7CjETwzCCS53MjW/rLMyyqEnTtaOfA==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -28847,7 +30947,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "engines": { "node": ">=10" }, @@ -28921,6 +31020,15 @@ "node": ">=8" } }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -28976,7 +31084,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -28989,7 +31096,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -28999,8 +31105,7 @@ "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/property-information": { "version": "5.6.0", @@ -29231,6 +31336,15 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "peer": true, + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -29292,7 +31406,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -29407,6 +31520,37 @@ "node": ">=0.10.0" } }, + "node_modules/react-devtools-core": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "peer": true, + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -29440,6 +31584,62 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "node_modules/react-konva": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-18.2.10.tgz", + "integrity": "sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "peer": true, + "dependencies": { + "@types/react-reconciler": "^0.28.2", + "its-fine": "^1.1.1", + "react-reconciler": "~0.29.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "konva": "^8.0.1 || ^7.2.5 || ^9.0.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/react-konva/node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "peer": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/react-konva/node_modules/react-reconciler": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz", + "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-leaflet": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", @@ -29453,6 +31653,284 @@ "react-dom": "^18.0.0" } }, + "node_modules/react-native": { + "version": "0.73.6", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.6.tgz", + "integrity": "sha512-oqmZe8D2/VolIzSPZw+oUd6j/bEmeRHwsLn1xLA5wllEYsZ5zNuMsDus235ONOnCRwexqof/J3aztyQswSmiaA==", + "peer": true, + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "12.3.6", + "@react-native-community/cli-platform-android": "12.3.6", + "@react-native-community/cli-platform-ios": "12.3.6", + "@react-native/assets-registry": "0.73.1", + "@react-native/codegen": "0.73.3", + "@react-native/community-cli-plugin": "0.73.17", + "@react-native/gradle-plugin": "0.73.4", + "@react-native/js-polyfills": "0.73.1", + "@react-native/normalize-colors": "0.73.2", + "@react-native/virtualized-lists": "0.73.4", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "deprecated-react-native-prop-types": "^5.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^4.27.7", + "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "18.2.0" + } + }, + "node_modules/react-native/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "peer": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "peer": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/react-native/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/react-native/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-native/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-native/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/react-native/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "peer": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/react-native/node_modules/pretty-format/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/react-native/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, + "node_modules/react-native/node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-native/node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-native/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-native/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-reconciler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", + "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.21.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/react-reconciler/node_modules/scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/react-redux": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.4.tgz", @@ -29505,6 +31983,36 @@ "resolved": "https://registry.npmjs.org/react-router-redux/-/react-router-redux-4.0.8.tgz", "integrity": "sha512-lzlK+S6jZnn17BZbzBe6F8ok3YAhGAUlyWgRu3cz5mT199gKxfem5lNu3qcgzRiVhNEOFVG0/pdT+1t4aWhoQw==" }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "peer": true, + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-spring": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.7.3.tgz", + "integrity": "sha512-oTxDpFV5gzq7jQX6+bU0SVq+vX8VnuuT5c8Zwn6CpDErOPvCmV+DRkPiEBtaL3Ozgzwiy5yFx83N0h303j/r3A==", + "dependencies": { + "@react-spring/core": "~9.7.3", + "@react-spring/konva": "~9.7.3", + "@react-spring/native": "~9.7.3", + "@react-spring/three": "~9.7.3", + "@react-spring/web": "~9.7.3", + "@react-spring/zdog": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -29539,6 +32047,30 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-use-measure": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz", + "integrity": "sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==", + "peer": true, + "dependencies": { + "debounce": "^1.2.1" + }, + "peerDependencies": { + "react": ">=16.13", + "react-dom": ">=16.13" + } + }, + "node_modules/react-zdog": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/react-zdog/-/react-zdog-1.2.2.tgz", + "integrity": "sha512-Ix7ALha91aOEwiHuxumCeYbARS5XNpc/w0v145oGkM6poF/CvhKJwzLhM5sEZbtrghMA+psAhOJkCTzJoseicA==", + "peer": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "resize-observer-polyfill": "^1.5.1" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -29654,7 +32186,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -29676,6 +32207,12 @@ "node": ">=8.10.0" } }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "peer": true + }, "node_modules/recast": { "version": "0.14.7", "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz", @@ -29743,14 +32280,12 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "node_modules/regenerate-unicode-properties": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -29767,7 +32302,6 @@ "version": "0.15.0", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -29819,7 +32353,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz", "integrity": "sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==", - "dev": true, "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", @@ -29859,14 +32392,12 @@ "node_modules/regjsgen": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true + "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==" }, "node_modules/regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -29878,7 +32409,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" } @@ -30234,7 +32764,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -30248,6 +32777,12 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "peer": true + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -30263,7 +32798,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -30335,7 +32869,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -30394,7 +32927,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -30979,7 +33511,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -31015,7 +33546,6 @@ "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -31039,7 +33569,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "dependencies": { "ms": "2.0.0" } @@ -31047,14 +33576,21 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/serialize-javascript": { "version": "5.0.1", @@ -31175,7 +33711,6 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -31189,14 +33724,12 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/set-function-length": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, "dependencies": { "define-data-property": "^1.1.2", "es-errors": "^1.3.0", @@ -31289,8 +33822,7 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/sha.js": { "version": "2.4.11", @@ -31309,7 +33841,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "dependencies": { "kind-of": "^6.0.2" }, @@ -31321,7 +33852,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -31333,11 +33863,19 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", @@ -31381,8 +33919,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-color-scale": { "version": "1.0.1", @@ -31421,8 +33958,7 @@ "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "node_modules/size-plugin": { "version": "3.0.0", @@ -31530,7 +34066,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "engines": { "node": ">=8" } @@ -31852,7 +34387,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -31986,8 +34520,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/sshpk": { "version": "1.17.0", @@ -32054,7 +34587,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -32066,7 +34598,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, "engines": { "node": ">=8" } @@ -32103,6 +34634,27 @@ "stacktrace-gps": "^3.0.4" } }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "peer": true, + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/standard-version": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", @@ -32312,7 +34864,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -32452,7 +35003,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -32461,7 +35011,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -32503,7 +35052,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -32645,7 +35193,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -32684,7 +35231,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "engines": { "node": ">=6" } @@ -32734,6 +35280,12 @@ "node": ">=0.8.0" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, "node_modules/style-loader": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", @@ -32837,11 +35389,16 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.2.tgz", "integrity": "sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA==" }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "peer": true + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -32866,7 +35423,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -32874,6 +35430,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/suspend-react": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", + "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", + "peer": true, + "peerDependencies": { + "react": ">=17.0" + } + }, "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -33218,7 +35783,6 @@ "version": "0.8.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "dev": true, "dependencies": { "rimraf": "~2.6.2" }, @@ -33230,7 +35794,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true, "engines": { "node": ">=8" } @@ -33239,7 +35802,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -33297,7 +35859,6 @@ "version": "5.15.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", - "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -33399,6 +35960,12 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/three": { + "version": "0.163.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.163.0.tgz", + "integrity": "sha512-HlMgCb2TF/dTLRtknBnjUTsR8FsDqBY43itYop2+Zg822I+Kd0Ua2vs8CvfBVefXkBdNDrLMoRTGCIIpfCuDew==", + "peer": true + }, "node_modules/throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -33494,8 +36061,7 @@ "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, "node_modules/to-arraybuffer": { "version": "1.0.1", @@ -33507,7 +36073,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -33564,7 +36129,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -33581,7 +36145,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, "engines": { "node": ">=0.6" } @@ -33800,7 +36363,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, "engines": { "node": ">=4" } @@ -34005,7 +36567,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, "engines": { "node": ">=4" } @@ -34014,7 +36575,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -34027,7 +36587,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true, "engines": { "node": ">=4" } @@ -34036,7 +36595,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, "engines": { "node": ">=4" } @@ -34260,7 +36818,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -34269,7 +36826,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -34355,7 +36911,6 @@ "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -34590,7 +37145,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -34660,7 +37214,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -34752,6 +37305,12 @@ "node": ">=4" } }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "peer": true + }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -34789,7 +37348,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, "dependencies": { "makeerror": "1.0.12" } @@ -35125,7 +37683,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, "dependencies": { "defaults": "^1.0.3" } @@ -36099,6 +38656,12 @@ "node": ">=0.10.0" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "peer": true + }, "node_modules/whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", @@ -36120,7 +38683,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -36147,6 +38709,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "peer": true + }, "node_modules/which-typed-array": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", @@ -36551,7 +39119,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -36567,8 +39134,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -36586,7 +39152,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "dev": true, "dependencies": { "async-limiter": "~1.0.0" } @@ -36646,7 +39211,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -36654,8 +39218,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -36716,7 +39279,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, "engines": { "node": ">=10" }, @@ -36724,6 +39286,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zdog": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/zdog/-/zdog-1.1.3.tgz", + "integrity": "sha512-raRj6r0gPzopFm5XWBJZr/NuV4EEnT4iE+U3dp5FV5pCb588Gmm3zLIp/j9yqqcMiHH8VNQlerLTgOqL7krh6w==", + "peer": true + }, + "node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "peer": true, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, "node_modules/zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", @@ -36746,114 +39331,56 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz", - "integrity": "sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==", - "dev": true + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==" }, "@babel/core": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz", - "integrity": "sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.0", - "@babel/helper-compilation-targets": "^7.19.1", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.1", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0", - "convert-source-map": "^1.7.0", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -36883,89 +39410,104 @@ } }, "@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "requires": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } } } }, "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, "requires": { "@babel/helper-explode-assignable-expression": "^7.18.6", "@babel/types": "^7.18.9" } }, "@babel/helper-compilation-targets": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz", - "integrity": "sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==", - "dev": true, + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "requires": { - "@babel/compat-data": "^7.19.1", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } }, "@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", + "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } } }, "@babel/helper-create-regexp-features-plugin": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "regexpu-core": "^5.1.0" @@ -36975,7 +39517,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.17.7", "@babel/helper-plugin-utils": "^7.16.7", @@ -36988,22 +39529,19 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, "@babel/helper-environment-visitor": { "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" }, "@babel/helper-explode-assignable-expression": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, "requires": { "@babel/types": "^7.18.6" } @@ -37012,7 +39550,6 @@ "version": "7.23.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, "requires": { "@babel/template": "^7.22.15", "@babel/types": "^7.23.0" @@ -37022,108 +39559,91 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, "requires": { "@babel/types": "^7.22.5" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", - "dev": true, + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "requires": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.23.0" } }, "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.0" } }, "@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" } }, "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==" }, "@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dev": true, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" } }, "@babel/helper-replace-supers": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", - "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5" } }, "@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", - "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", - "dev": true, + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "requires": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.22.5" } }, "@babel/helper-split-export-declaration": { "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, "requires": { "@babel/types": "^7.22.5" } @@ -37131,60 +39651,53 @@ "@babel/helper-string-parser": { "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" }, "@babel/helper-validator-identifier": { "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" }, "@babel/helper-validator-option": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" }, "@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", - "dev": true, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "requires": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" } }, "@babel/helpers": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" } }, "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "requires": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -37193,7 +39706,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -37204,7 +39716,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -37212,26 +39723,22 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -37239,16 +39746,14 @@ } }, "@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37257,7 +39762,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", @@ -37268,7 +39772,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz", "integrity": "sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q==", - "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-plugin-utils": "^7.19.0", @@ -37280,7 +39783,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -37290,7 +39792,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", - "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", @@ -37314,7 +39815,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -37324,7 +39824,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.23.3.tgz", "integrity": "sha512-Q23MpLZfSGZL1kU7fWqV262q65svLSCIP5kZ/JCW/rKTCm/FrLjpvEd2kfUYMVeHh4QhV/xzyoRAHWrAZJrE3Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-export-default-from": "^7.23.3" @@ -37334,7 +39833,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -37344,7 +39842,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -37354,7 +39851,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -37364,7 +39860,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -37374,43 +39869,39 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", - "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", - "dev": true, + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", "requires": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" + "@babel/plugin-transform-parameters": "^7.20.7" } }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", - "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", - "dev": true, + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, @@ -37418,7 +39909,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -37428,7 +39918,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-create-class-features-plugin": "^7.18.6", @@ -37440,7 +39929,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -37450,7 +39938,6 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37468,7 +39955,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.12.13" } @@ -37477,7 +39963,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } @@ -37495,7 +39980,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37504,7 +39988,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.23.3.tgz", "integrity": "sha512-KeENO5ck1IeZ/l2lFZNy+mpobV3D2Zy5C1YFnWm+YuY5mQiAWc4yAp13dqgguwsBsFVLh4LPCEqCa5qW13N+hw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5" } @@ -37513,7 +39996,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3" } @@ -37522,7 +40004,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz", "integrity": "sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5" } @@ -37531,7 +40012,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37549,7 +40029,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37558,7 +40037,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37567,7 +40045,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } @@ -37576,7 +40053,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37585,7 +40061,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" } @@ -37594,7 +40069,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37603,7 +40077,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37612,7 +40085,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -37621,7 +40093,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } @@ -37630,7 +40101,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } @@ -37639,7 +40109,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37648,27 +40117,24 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-remap-async-to-generator": "^7.22.20" } }, "@babel/plugin-transform-block-scoped-functions": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37677,7 +40143,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -37686,7 +40151,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz", "integrity": "sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-compilation-targets": "^7.19.0", @@ -37702,8 +40166,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" } } }, @@ -37711,25 +40174,22 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-destructuring": { - "version": "7.18.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", - "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", + "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", "requires": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.24.0" } }, "@babel/plugin-transform-dotall-regex": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -37739,7 +40199,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -37748,7 +40207,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, "requires": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -37758,7 +40216,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz", "integrity": "sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-flow": "^7.23.3" @@ -37768,7 +40225,6 @@ "version": "7.18.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37777,7 +40233,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-function-name": "^7.18.9", @@ -37788,7 +40243,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -37797,7 +40251,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37806,7 +40259,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", - "dev": true, "requires": { "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", @@ -37817,7 +40269,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", - "dev": true, "requires": { "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6", @@ -37829,7 +40280,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz", "integrity": "sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==", - "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-module-transforms": "^7.19.0", @@ -37842,7 +40292,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, "requires": { "@babel/helper-module-transforms": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -37852,7 +40301,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", - "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0" @@ -37862,7 +40310,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37880,26 +40327,45 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-replace-supers": "^7.18.6" } }, "@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", + "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", + "peer": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", + "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "peer": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-transform-property-literals": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37908,7 +40374,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37917,7 +40382,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz", "integrity": "sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-module-imports": "^7.18.6", @@ -37935,6 +40399,24 @@ "@babel/plugin-transform-react-jsx": "^7.18.6" } }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", + "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz", + "integrity": "sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==", + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, "@babel/plugin-transform-react-pure-annotations": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", @@ -37949,7 +40431,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "regenerator-transform": "^0.15.0" @@ -37959,16 +40440,79 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } }, + "@babel/plugin-transform-runtime": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", + "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", + "peer": true, + "requires": { + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-plugin-utils": "^7.24.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", + "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", + "peer": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", + "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "peer": true, + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.1", + "semver": "^6.3.1" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "peer": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", + "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "peer": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.1" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "peer": true + } + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37977,7 +40521,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz", "integrity": "sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.19.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" @@ -37987,7 +40530,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6" } @@ -37996,7 +40538,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -38005,7 +40546,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -38014,7 +40554,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.1.tgz", "integrity": "sha512-+ILcOU+6mWLlvCwnL920m2Ow3wWx3Wo8n2t5aROQmV55GZt+hOiLvBaa3DNzRjSEHa1aauRs4/YLmkCfFkhhRQ==", - "dev": true, "requires": { "@babel/helper-create-class-features-plugin": "^7.19.0", "@babel/helper-plugin-utils": "^7.19.0", @@ -38025,7 +40564,6 @@ "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.9" } @@ -38034,7 +40572,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -38044,7 +40581,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.1.tgz", "integrity": "sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA==", - "dev": true, "requires": { "@babel/compat-data": "^7.19.1", "@babel/helper-compilation-targets": "^7.19.1", @@ -38126,8 +40662,7 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -38135,7 +40670,6 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.23.3.tgz", "integrity": "sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", @@ -38146,7 +40680,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", @@ -38173,7 +40706,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.18.6", "@babel/helper-validator-option": "^7.18.6", @@ -38184,7 +40716,6 @@ "version": "7.23.7", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", - "dev": true, "requires": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", @@ -38197,7 +40728,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, "requires": { "commondir": "^1.0.1", "make-dir": "^2.0.0", @@ -38208,7 +40738,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -38217,7 +40746,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -38227,7 +40755,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "requires": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -38237,7 +40764,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -38246,7 +40772,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -38254,20 +40779,17 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "requires": { "find-up": "^3.0.0" } @@ -38275,8 +40797,7 @@ "semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" } } }, @@ -38289,30 +40810,28 @@ } }, "@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", - "dev": true, + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "requires": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" } }, "@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", - "dev": true, + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -38320,16 +40839,14 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" } } }, "@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", - "dev": true, + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "requires": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -38400,6 +40917,21 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "peer": true + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "peer": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@humanwhocodes/config-array": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", @@ -38435,6 +40967,12 @@ "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", "dev": true }, + "@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "peer": true + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -38724,6 +41262,15 @@ } } }, + "@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "peer": true, + "requires": { + "@jest/types": "^29.6.3" + } + }, "@jest/environment": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", @@ -39056,12 +41603,11 @@ } }, "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "requires": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { @@ -39185,12 +41731,11 @@ } }, "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -39202,7 +41747,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -39211,20 +41755,17 @@ "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, "@jridgewell/source-map": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -39234,7 +41775,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -39246,14 +41786,12 @@ "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", - "dev": true, + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -39542,252 +42080,1027 @@ "ramda": "^0.27.1" } }, - "@lingui/react": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/react/-/react-3.14.0.tgz", - "integrity": "sha512-ow9Mtru7f0T2S9AwnPWRejppcucCW0LmoDR3P4wqHjL+eH5f8a6nxd2doxGieC91/2i4qqW88y4K/zXJxwRSQw==", - "dev": true, + "@lingui/react": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@lingui/react/-/react-3.14.0.tgz", + "integrity": "sha512-ow9Mtru7f0T2S9AwnPWRejppcucCW0LmoDR3P4wqHjL+eH5f8a6nxd2doxGieC91/2i4qqW88y4K/zXJxwRSQw==", + "dev": true, + "peer": true, + "requires": { + "@babel/runtime": "^7.11.2", + "@lingui/core": "^3.14.0" + } + }, + "@mdn/browser-compat-data": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.11.tgz", + "integrity": "sha512-4o1ZaGmvqoDx3QLyEAcZvGDKmdVXLB0aiANuPDumgue/7iH67KUBsKejLX7wrdxEdyNYfXUKtjFQYhGwVUBXGw==", + "dev": true + }, + "@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "dev": true, + "requires": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true + } + } + }, + "@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", + "dev": true + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "dependencies": { + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "dev": true + } + } + }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", + "dev": true + }, + "@preact/async-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@preact/async-loader/-/async-loader-3.0.2.tgz", + "integrity": "sha512-nYIdlAGbZ0+0/u5VJxQdLDgNFgEJmNLzctuqnCBZxW/EpLPMg8lcsnRsoXVl+O28ZZYhVhos3XiWM3KtuN0C3Q==", + "dev": true, + "requires": { + "kleur": "^4.1.4", + "loader-utils": "^2.0.0" + }, + "dependencies": { + "kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true + } + } + }, + "@prefresh/babel-plugin": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@prefresh/babel-plugin/-/babel-plugin-0.4.3.tgz", + "integrity": "sha512-fYAWbU1WDSLn108kKY4eDaaeUcnszFqXjgaGKYXNZ5NLulpRTpsrY+Sbfo9q8LDpWrBpqIgzjrwNnvglWI1xNQ==", + "dev": true + }, + "@prefresh/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@prefresh/core/-/core-1.4.1.tgz", + "integrity": "sha512-og1vaBj3LMJagVncNrDb37Gqc0cWaUcDbpVt5hZtsN4i2Iwzd/5hyTsDHvlMirhSym3wL9ihU0Xa2VhSaOue7g==", + "dev": true, + "requires": {} + }, + "@prefresh/utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@prefresh/utils/-/utils-1.1.3.tgz", + "integrity": "sha512-Mb9abhJTOV4yCfkXrMrcgFiFT7MfNOw8sDa+XyZBdq/Ai2p4Zyxqsb3EgHLOEdHpMj6J9aiZ54W8H6FTam1u+A==", + "dev": true + }, + "@prefresh/webpack": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@prefresh/webpack/-/webpack-3.3.4.tgz", + "integrity": "sha512-RiXS/hvXDup5cQw/267kxkKie81kxaAB7SFbkr8ppshobDEzwgUN1tbGbHNx6Uari0Ql2XByC6HIgQGpaq2Q7w==", + "dev": true, + "requires": { + "@prefresh/core": "^1.3.3", + "@prefresh/utils": "^1.1.2" + } + }, + "@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "requires": {} + }, + "@react-native-community/cli": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.6.tgz", + "integrity": "sha512-647OSi6xBb8FbwFqX9zsJxOzu685AWtrOUWHfOkbKD+5LOpGORw+GQo0F9rWZnB68rLQyfKUZWJeaD00pGv5fw==", + "peer": true, + "requires": { + "@react-native-community/cli-clean": "12.3.6", + "@react-native-community/cli-config": "12.3.6", + "@react-native-community/cli-debugger-ui": "12.3.6", + "@react-native-community/cli-doctor": "12.3.6", + "@react-native-community/cli-hermes": "12.3.6", + "@react-native-community/cli-plugin-metro": "12.3.6", + "@react-native-community/cli-server-api": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-types": "12.3.6", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "deepmerge": "^4.3.0", + "execa": "^5.0.0", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.2", + "semver": "^7.5.2" + }, + "dependencies": { + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "peer": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "peer": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "peer": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "peer": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "peer": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "@react-native-community/cli-clean": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.6.tgz", + "integrity": "sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==", + "peer": true, + "requires": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "execa": "^5.0.0" + } + }, + "@react-native-community/cli-config": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.6.tgz", + "integrity": "sha512-JGWSYQ9EAK6m2v0abXwFLEfsqJ1zkhzZ4CV261QZF9MoUNB6h57a274h1MLQR9mG6Tsh38wBUuNfEPUvS1vYew==", + "peer": true, + "requires": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "cosmiconfig": "^5.1.0", + "deepmerge": "^4.3.0", + "glob": "^7.1.3", + "joi": "^17.2.1" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "peer": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "peer": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "peer": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "peer": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "peer": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "peer": true + } + } + }, + "@react-native-community/cli-debugger-ui": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.6.tgz", + "integrity": "sha512-SjUKKsx5FmcK9G6Pb6UBFT0s9JexVStK5WInmANw75Hm7YokVvHEgtprQDz2Uvy5znX5g2ujzrkIU//T15KQzA==", + "peer": true, + "requires": { + "serve-static": "^1.13.1" + } + }, + "@react-native-community/cli-doctor": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.6.tgz", + "integrity": "sha512-fvBDv2lTthfw4WOQKkdTop2PlE9GtfrlNnpjB818MhcdEnPjfQw5YaTUcnNEGsvGomdCs1MVRMgYXXwPSN6OvQ==", + "peer": true, + "requires": { + "@react-native-community/cli-config": "12.3.6", + "@react-native-community/cli-platform-android": "12.3.6", + "@react-native-community/cli-platform-ios": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "deepmerge": "^4.3.0", + "envinfo": "^7.10.0", + "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "peer": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "peer": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "peer": true + } + } + }, + "@react-native-community/cli-hermes": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.6.tgz", + "integrity": "sha512-sNGwfOCl8OAIjWCkwuLpP8NZbuO0dhDI/2W7NeOGDzIBsf4/c4MptTrULWtGIH9okVPLSPX0NnRyGQ+mSwWyuQ==", + "peer": true, + "requires": { + "@react-native-community/cli-platform-android": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "hermes-profile-transformer": "^0.0.6" + } + }, + "@react-native-community/cli-platform-android": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.6.tgz", + "integrity": "sha512-DeDDAB8lHpuGIAPXeeD9Qu2+/wDTFPo99c8uSW49L0hkmZJixzvvvffbGQAYk32H0TmaI7rzvzH+qzu7z3891g==", + "peer": true, + "requires": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.2.4", + "glob": "^7.1.3", + "logkitty": "^0.7.1" + } + }, + "@react-native-community/cli-platform-ios": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.6.tgz", + "integrity": "sha512-3eZ0jMCkKUO58wzPWlvAPRqezVKm9EPZyaPyHbRPWU8qw7JqkvnRlWIaYDGpjCJgVW4k2hKsEursLtYKb188tg==", + "peer": true, + "requires": { + "@react-native-community/cli-tools": "12.3.6", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.0.12", + "glob": "^7.1.3", + "ora": "^5.4.1" + } + }, + "@react-native-community/cli-plugin-metro": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.6.tgz", + "integrity": "sha512-3jxSBQt4fkS+KtHCPSyB5auIT+KKIrPCv9Dk14FbvOaEh9erUWEm/5PZWmtboW1z7CYeNbFMeXm9fM2xwtVOpg==", + "peer": true + }, + "@react-native-community/cli-server-api": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.6.tgz", + "integrity": "sha512-80NIMzo8b2W+PL0Jd7NjiJW9mgaT8Y8wsIT/lh6mAvYH7mK0ecDJUYUTAAv79Tbo1iCGPAr3T295DlVtS8s4yQ==", + "peer": true, + "requires": { + "@react-native-community/cli-debugger-ui": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^7.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "peer": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "peer": true, + "requires": {} + } + } + }, + "@react-native-community/cli-tools": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.6.tgz", + "integrity": "sha512-FPEvZn19UTMMXUp/piwKZSh8cMEfO8G3KDtOwo53O347GTcwNrKjgZGtLSPELBX2gr+YlzEft3CoRv2Qmo83fQ==", + "peer": true, + "requires": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "node-fetch": "^2.6.0", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "peer": true + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "peer": true + }, + "open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "peer": true, + "requires": { + "is-wsl": "^1.1.0" + } + } + } + }, + "@react-native-community/cli-types": { + "version": "12.3.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.6.tgz", + "integrity": "sha512-xPqTgcUtZowQ8WKOkI9TLGBwH2bGggOC4d2FFaIRST3gTcjrEeGRNeR5aXCzJFIgItIft8sd7p2oKEdy90+01Q==", + "peer": true, + "requires": { + "joi": "^17.2.1" + } + }, + "@react-native/assets-registry": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", + "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", + "peer": true + }, + "@react-native/babel-plugin-codegen": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", + "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", "peer": true, "requires": { - "@babel/runtime": "^7.11.2", - "@lingui/core": "^3.14.0" + "@react-native/codegen": "0.73.3" } }, - "@mdn/browser-compat-data": { - "version": "5.5.11", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.11.tgz", - "integrity": "sha512-4o1ZaGmvqoDx3QLyEAcZvGDKmdVXLB0aiANuPDumgue/7iH67KUBsKejLX7wrdxEdyNYfXUKtjFQYhGwVUBXGw==", - "dev": true + "@react-native/babel-preset": { + "version": "0.73.21", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", + "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", + "peer": true, + "requires": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "@react-native/babel-plugin-codegen": "0.73.4", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "dependencies": { + "react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "peer": true + } + } }, - "@mdx-js/mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", - "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", - "dev": true, + "@react-native/codegen": { + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", + "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", + "peer": true, "requires": { - "@babel/core": "7.12.9", - "@babel/plugin-syntax-jsx": "7.12.1", - "@babel/plugin-syntax-object-rest-spread": "7.8.3", - "@mdx-js/util": "1.6.22", - "babel-plugin-apply-mdx-type-prop": "1.6.22", - "babel-plugin-extract-import-names": "1.6.22", - "camelcase-css": "2.0.1", - "detab": "2.0.4", - "hast-util-raw": "6.0.1", - "lodash.uniq": "4.5.0", - "mdast-util-to-hast": "10.0.1", - "remark-footnotes": "2.0.0", - "remark-mdx": "1.6.22", - "remark-parse": "8.0.3", - "remark-squeeze-paragraphs": "4.0.0", - "style-to-object": "0.3.0", - "unified": "9.2.0", - "unist-builder": "2.0.3", - "unist-util-visit": "2.0.3" + "@babel/parser": "^7.20.0", + "flow-parser": "^0.206.0", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jscodeshift": "^0.14.0", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1" }, "dependencies": { - "@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", - "dev": true, + "ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "peer": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "tslib": "^2.0.1" } }, - "@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", - "dev": true, + "flow-parser": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", + "peer": true + }, + "jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "peer": true, + "requires": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "peer": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "minimist": "^1.2.6" } }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true + "recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "peer": true, + "requires": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "peer": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } } } }, - "@mdx-js/util": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", - "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", - "dev": true - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, + "@react-native/community-cli-plugin": { + "version": "0.73.17", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.17.tgz", + "integrity": "sha512-F3PXZkcHg+1ARIr6FRQCQiB7ZAA+MQXGmq051metRscoLvgYJwj7dgC8pvgy0kexzUkHu5BNKrZeySzUft3xuQ==", + "peer": true, "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - }, - "dependencies": { - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", - "dev": true - } - } + "@react-native-community/cli-server-api": "12.3.6", + "@react-native-community/cli-tools": "12.3.6", + "@react-native/dev-middleware": "0.73.8", + "@react-native/metro-babel-transformer": "0.73.15", + "chalk": "^4.0.0", + "execa": "^5.1.1", + "metro": "^0.80.3", + "metro-config": "^0.80.3", + "metro-core": "^0.80.3", + "node-fetch": "^2.2.0", + "readline": "^1.3.0" + } + }, + "@react-native/debugger-frontend": { + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", + "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", + "peer": true }, - "@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, + "@react-native/dev-middleware": { + "version": "0.73.8", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", + "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", + "peer": true, "requires": { - "eslint-scope": "5.1.1" + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.73.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^1.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "open": "^7.0.3", + "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", + "ws": "^6.2.2" }, "dependencies": { - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "ms": "2.0.0" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "peer": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } } } }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, + "@react-native/gradle-plugin": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", + "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==", + "peer": true + }, + "@react-native/js-polyfills": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", + "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", + "peer": true + }, + "@react-native/metro-babel-transformer": { + "version": "0.73.15", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", + "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", + "peer": true, "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.73.21", + "hermes-parser": "0.15.0", + "nullthrows": "^1.1.1" } }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "@react-native/normalize-colors": { + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", + "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "peer": true }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, + "@react-native/virtualized-lists": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", + "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", + "peer": true, "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" } }, - "@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "dev": true, + "@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" } }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, + "@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" } }, - "@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true + "@react-spring/konva": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/konva/-/konva-9.7.3.tgz", + "integrity": "sha512-R9sY6SiPGYqz1383P5qppg5z57YfChVknOC1UxxaGxpw+WiZa8fZ4zmZobslrw+os3/+HAXZv8O+EvU/nQpf7g==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } }, - "@preact/async-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@preact/async-loader/-/async-loader-3.0.2.tgz", - "integrity": "sha512-nYIdlAGbZ0+0/u5VJxQdLDgNFgEJmNLzctuqnCBZxW/EpLPMg8lcsnRsoXVl+O28ZZYhVhos3XiWM3KtuN0C3Q==", - "dev": true, + "@react-spring/native": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/native/-/native-9.7.3.tgz", + "integrity": "sha512-4mpxX3FuEBCUT6ae2fjhxcJW6bhr2FBwFf274eXB7n+U30Gdg8Wo2qYwcUnmiAA0S3dvP8vLTazx3+CYWFShnA==", "requires": { - "kleur": "^4.1.4", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true - } + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" } }, - "@prefresh/babel-plugin": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@prefresh/babel-plugin/-/babel-plugin-0.4.3.tgz", - "integrity": "sha512-fYAWbU1WDSLn108kKY4eDaaeUcnszFqXjgaGKYXNZ5NLulpRTpsrY+Sbfo9q8LDpWrBpqIgzjrwNnvglWI1xNQ==", - "dev": true + "@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "requires": { + "@react-spring/types": "~9.7.3" + } }, - "@prefresh/core": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@prefresh/core/-/core-1.4.1.tgz", - "integrity": "sha512-og1vaBj3LMJagVncNrDb37Gqc0cWaUcDbpVt5hZtsN4i2Iwzd/5hyTsDHvlMirhSym3wL9ihU0Xa2VhSaOue7g==", - "dev": true, - "requires": {} + "@react-spring/three": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.7.3.tgz", + "integrity": "sha512-Q1p512CqUlmMK8UMBF/Rj79qndhOWq4XUTayxMP9S892jiXzWQuj+xC3Xvm59DP/D4JXusXpxxqfgoH+hmOktA==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } }, - "@prefresh/utils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@prefresh/utils/-/utils-1.1.3.tgz", - "integrity": "sha512-Mb9abhJTOV4yCfkXrMrcgFiFT7MfNOw8sDa+XyZBdq/Ai2p4Zyxqsb3EgHLOEdHpMj6J9aiZ54W8H6FTam1u+A==", - "dev": true + "@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" }, - "@prefresh/webpack": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@prefresh/webpack/-/webpack-3.3.4.tgz", - "integrity": "sha512-RiXS/hvXDup5cQw/267kxkKie81kxaAB7SFbkr8ppshobDEzwgUN1tbGbHNx6Uari0Ql2XByC6HIgQGpaq2Q7w==", - "dev": true, + "@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", "requires": { - "@prefresh/core": "^1.3.3", - "@prefresh/utils": "^1.1.2" + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" } }, - "@react-leaflet/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", - "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", - "requires": {} + "@react-spring/zdog": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/zdog/-/zdog-9.7.3.tgz", + "integrity": "sha512-L+yK/1PvNi9n8cldiJ309k4LdxcPkeWE0W18l1zrP1IBIyd5NB5EPA8DMsGr9gtNnnIujtEzZk+4JIOjT8u/tw==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-three/fiber": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.16.1.tgz", + "integrity": "sha512-Rgjn+xcR+6Do2Ic4b6RROIvCGs3RhoVJEamfmtMSfkgIRH3PeiPdqRxcfJlO9y6KDvYA5fIUGruz9h/sTeLlpw==", + "peer": true, + "requires": { + "@babel/runtime": "^7.17.8", + "@types/react-reconciler": "^0.26.7", + "@types/webxr": "*", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "its-fine": "^1.0.6", + "react-reconciler": "^0.27.0", + "react-use-measure": "^2.1.1", + "scheduler": "^0.21.0", + "suspend-react": "^0.1.3", + "zustand": "^3.7.1" + }, + "dependencies": { + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "peer": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + } + } }, "@rollup/plugin-babel": { "version": "5.3.1", @@ -39834,11 +43147,31 @@ "picomatch": "^2.2.2" } }, + "@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "peer": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "peer": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "peer": true + }, "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "@sindresorhus/is": { "version": "0.14.0", @@ -42668,14 +46001,12 @@ "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" }, "@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } @@ -42684,7 +46015,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, "requires": { "@types/istanbul-lib-report": "*" } @@ -42761,8 +46091,7 @@ "@types/node": { "version": "18.7.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.21.tgz", - "integrity": "sha512-rLFzK5bhM0YPyCoTC8bolBjMk7bwnZ8qeZUBslBfjZQou2ssJdWslx9CZ8DGM+Dx7QXQiiTVZ/6QO6kwtHkZCA==", - "dev": true + "integrity": "sha512-rLFzK5bhM0YPyCoTC8bolBjMk7bwnZ8qeZUBslBfjZQou2ssJdWslx9CZ8DGM+Dx7QXQiiTVZ/6QO6kwtHkZCA==" }, "@types/node-fetch": { "version": "2.6.11", @@ -42859,6 +46188,15 @@ "csstype": "^3.0.2" } }, + "@types/react-reconciler": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz", + "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==", + "peer": true, + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -42922,8 +46260,7 @@ "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, "@types/tapable": { "version": "1.0.8", @@ -43005,6 +46342,12 @@ } } }, + "@types/webxr": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.14.tgz", + "integrity": "sha512-UEMMm/Xn3DtEa+gpzUrOcDj+SJS1tk5YodjwOxcqStNhCfPcwgyC5Srg2ToVKyg2Fhq16Ffpb0UWUQHqoT9AMA==", + "peer": true + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -43018,7 +46361,6 @@ "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, "requires": { "@types/yargs-parser": "*" } @@ -43026,8 +46368,7 @@ "@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "@typescript-eslint/eslint-plugin": { "version": "5.46.0", @@ -43636,11 +46977,19 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "peer": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, "requires": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -43649,8 +46998,7 @@ "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" }, "acorn-globals": { "version": "4.3.4", @@ -43822,6 +47170,12 @@ "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==", "dev": true }, + "anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "peer": true + }, "ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -43854,6 +47208,87 @@ } } }, + "ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "peer": true, + "requires": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "peer": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "peer": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "peer": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "peer": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "peer": true + }, + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "peer": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "peer": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "peer": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "peer": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -43863,14 +47298,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -43888,7 +47321,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -43900,6 +47332,12 @@ "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", "dev": true }, + "appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "peer": true + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -44083,6 +47521,12 @@ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "peer": true + }, "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -44190,8 +47634,7 @@ "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "asynckit": { "version": "0.4.0", @@ -44316,7 +47759,6 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, "requires": {} }, "babel-jest": { @@ -44464,7 +47906,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, "requires": { "object.assign": "^4.1.0" } @@ -44535,7 +47976,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, "requires": { "@babel/compat-data": "^7.17.7", "@babel/helper-define-polyfill-provider": "^0.3.3", @@ -44545,8 +47985,7 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -44554,7 +47993,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, "requires": { "@babel/helper-define-polyfill-provider": "^0.3.3", "core-js-compat": "^3.25.1" @@ -44564,7 +48002,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, "requires": { "@babel/helper-define-polyfill-provider": "^0.3.3" } @@ -44575,6 +48012,15 @@ "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", "dev": true }, + "babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "peer": true, + "requires": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, "babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", @@ -44704,8 +48150,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base": { "version": "0.11.2", @@ -44736,8 +48181,7 @@ "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "batch": { "version": "0.6.1", @@ -44819,7 +48263,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -44960,7 +48403,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -44970,7 +48412,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -45072,7 +48513,6 @@ "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -45084,7 +48524,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, "requires": { "node-int64": "^0.4.0" } @@ -45093,7 +48532,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -45108,8 +48546,7 @@ "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "buffer-xor": { "version": "1.0.3", @@ -45141,8 +48578,7 @@ "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" }, "cacache": { "version": "15.3.0", @@ -45229,7 +48665,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, "requires": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -45248,7 +48683,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "dev": true, "requires": { "callsites": "^2.0.0" }, @@ -45256,8 +48690,7 @@ "callsites": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", - "dev": true + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==" } } }, @@ -45265,7 +48698,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "dev": true, "requires": { "caller-callsite": "^2.0.0" } @@ -45289,8 +48721,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-css": { "version": "2.0.1", @@ -45333,8 +48764,7 @@ "caniuse-lite": { "version": "1.0.30001588", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz", - "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==", - "dev": true + "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==" }, "capture-exit": { "version": "2.0.0", @@ -45367,7 +48797,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -45436,12 +48865,38 @@ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true }, + "chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "peer": true, + "requires": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + } + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true }, + "chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", + "peer": true, + "requires": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, "ci-env": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/ci-env/-/ci-env-1.17.0.tgz", @@ -45451,8 +48906,7 @@ "ci-info": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", - "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", - "dev": true + "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==" }, "cipher-base": { "version": "1.0.4", @@ -45575,7 +49029,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "requires": { "restore-cursor": "^3.1.0" } @@ -45583,8 +49036,7 @@ "cli-spinners": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", - "dev": true + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==" }, "cli-table": { "version": "0.3.6", @@ -45691,14 +49143,12 @@ "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "requires": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -45709,7 +49159,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -45853,7 +49302,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -45861,8 +49309,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "color-string": { "version": "1.9.1", @@ -45913,11 +49360,16 @@ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", "dev": true }, + "command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "peer": true + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "common-tags": { "version": "1.8.2", @@ -45928,8 +49380,7 @@ "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, "compare-func": { "version": "2.0.0", @@ -45951,7 +49402,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, "requires": { "mime-db": ">= 1.43.0 < 2" } @@ -45960,7 +49410,6 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, "requires": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -45975,7 +49424,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -45983,8 +49431,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -46026,8 +49473,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -46081,6 +49527,65 @@ "xdg-basedir": "^4.0.0" } }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "peer": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "peer": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "peer": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "peer": true + } + } + }, "connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -46857,12 +50362,11 @@ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-compat": { - "version": "3.25.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.3.tgz", - "integrity": "sha512-xVtYpJQ5grszDHEUU9O7XbjjcZ0ccX3LgQsyqSvTnjX97ZqEgn9F5srmrwwwMtbKzDllyFPL+O+2OFMl1lU4TQ==", - "dev": true, + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", + "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", "requires": { - "browserslist": "^4.21.4" + "browserslist": "^4.23.0" } }, "core-util-is": { @@ -47256,7 +50760,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -47750,11 +51253,22 @@ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "peer": true + }, + "debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "peer": true + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -47762,8 +51276,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" }, "decamelize-keys": { "version": "1.1.1", @@ -47824,10 +51337,9 @@ } }, "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, "default-browser-id": { "version": "1.0.4", @@ -47854,7 +51366,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", - "dev": true, "requires": { "clone": "^1.0.2" } @@ -47869,7 +51380,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "requires": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -47886,7 +51396,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "requires": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -47921,11 +51430,27 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "peer": true + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "deprecated-react-native-prop-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", + "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", + "peer": true, + "requires": { + "@react-native/normalize-colors": "^0.73.0", + "invariant": "^2.2.4", + "prop-types": "^15.8.1" + } }, "des.js": { "version": "1.0.1", @@ -47940,8 +51465,7 @@ "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "detab": { "version": "2.0.4", @@ -48325,8 +51849,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "ejs": { "version": "3.1.8", @@ -48350,8 +51873,7 @@ "electron-to-chromium": { "version": "1.4.677", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.677.tgz", - "integrity": "sha512-erDa3CaDzwJOpyvfKhOiJjBVNnMM0qxHq47RheVVwsSQrgBA9ZSGV9kdaOfZDPXcHzhG7lBxhj6A7KvfLJBd6Q==", - "dev": true + "integrity": "sha512-erDa3CaDzwJOpyvfKhOiJjBVNnMM0qxHq47RheVVwsSQrgBA9ZSGV9kdaOfZDPXcHzhG7lBxhj6A7KvfLJBd6Q==" }, "elliptic": { "version": "6.5.4", @@ -48391,8 +51913,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "emojis-list": { "version": "3.0.0", @@ -48403,8 +51924,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "end-of-stream": { "version": "1.4.4", @@ -48469,10 +51989,9 @@ "dev": true }, "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==" }, "errno": { "version": "0.1.8", @@ -48487,7 +52006,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -48500,6 +52018,16 @@ "stackframe": "^1.3.4" } }, + "errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "peer": true, + "requires": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + } + }, "es-abstract": { "version": "1.22.4", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", @@ -48559,7 +52087,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, "requires": { "get-intrinsic": "^1.2.4" } @@ -48567,8 +52094,7 @@ "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, "es-get-iterator": { "version": "1.1.3", @@ -48641,8 +52167,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-goat": { "version": "2.1.1", @@ -48653,14 +52178,12 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "escodegen": { "version": "1.14.3", @@ -48996,8 +52519,13 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "peer": true }, "eventemitter3": { "version": "4.0.7", @@ -49031,7 +52559,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "requires": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -49428,6 +52955,15 @@ "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" }, + "fast-xml-parser": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz", + "integrity": "sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==", + "peer": true, + "requires": { + "strnum": "^1.0.5" + } + }, "fastest-stable-stringify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", @@ -49455,7 +52991,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, "requires": { "bser": "2.1.1" } @@ -49675,7 +53210,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -49727,7 +53261,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -49749,6 +53282,12 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "peer": true + }, "flow-parser": { "version": "0.229.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.229.0.tgz", @@ -49928,8 +53467,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "from2": { "version": "2.3.0", @@ -49971,7 +53509,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -50034,21 +53571,18 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "optional": true }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "function.prototype.name": { "version": "1.1.6", @@ -50094,20 +53628,17 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, "requires": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -50167,8 +53698,7 @@ "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" }, "get-symbol-description": { "version": "1.0.2", @@ -50542,7 +54072,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -50639,7 +54168,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "requires": { "get-intrinsic": "^1.1.3" } @@ -50677,8 +54205,7 @@ "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "grapheme-splitter": { "version": "1.0.4", @@ -50746,7 +54273,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -50775,8 +54301,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-glob": { "version": "1.0.0", @@ -50802,7 +54327,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "requires": { "es-define-property": "^1.0.0" } @@ -50810,14 +54334,12 @@ "has-proto": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.2", @@ -50925,7 +54447,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, "requires": { "function-bind": "^1.1.2" } @@ -51023,6 +54544,38 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hermes-estree": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", + "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", + "peer": true + }, + "hermes-parser": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", + "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", + "peer": true, + "requires": { + "hermes-estree": "0.15.0" + } + }, + "hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", + "peer": true, + "requires": { + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "peer": true + } + } + }, "hex-color-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", @@ -51312,7 +54865,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, "requires": { "depd": "2.0.0", "inherits": "2.0.4", @@ -51411,8 +54963,7 @@ "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" }, "husky": { "version": "8.0.1", @@ -51543,8 +55094,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "iferr": { "version": "0.1.5", @@ -51588,8 +55138,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" }, "indent-string": { "version": "4.0.0", @@ -51613,7 +55162,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -51773,8 +55321,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "is-bigint": { "version": "1.0.4", @@ -51856,7 +55403,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -51899,14 +55445,12 @@ "is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", - "dev": true + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==" }, "is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" }, "is-dom": { "version": "1.1.0", @@ -51954,8 +55498,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-function": { "version": "1.0.2", @@ -51997,8 +55540,7 @@ "is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" }, "is-map": { "version": "2.0.2", @@ -52027,8 +55569,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { "version": "1.0.7", @@ -52109,8 +55650,7 @@ "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, "is-string": { "version": "1.0.7", @@ -52163,8 +55703,7 @@ "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" }, "is-weakref": { "version": "1.0.2", @@ -52209,7 +55748,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "requires": { "is-docker": "^2.0.0" } @@ -52228,8 +55766,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "isobject": { "version": "3.0.1", @@ -52327,6 +55864,26 @@ "iterate-iterator": "^1.0.1" } }, + "its-fine": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.1.3.tgz", + "integrity": "sha512-mncCA+yb6tuh5zK26cHqKlsSyxm4zdm4YgJpxycyx6p9fgxgK5PLu3iDVpKhzTn57Yrv3jk/r0aK0RFTT1OjFw==", + "peer": true, + "requires": { + "@types/react-reconciler": "^0.28.0" + }, + "dependencies": { + "@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "peer": true, + "requires": { + "@types/react": "*" + } + } + } + }, "jake": { "version": "10.8.5", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", @@ -53241,10 +56798,9 @@ } }, "jest-get-type": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.0.0.tgz", - "integrity": "sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==", - "dev": true + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==" }, "jest-haste-map": { "version": "27.5.1", @@ -53526,18 +57082,17 @@ } }, "jest-message-util": { - "version": "29.2.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.1.tgz", - "integrity": "sha512-Dx5nEjw9V8C1/Yj10S/8ivA8F439VS8vTq1L7hEgwHFn9ovSKNpYW/kwNh7UglaEgXO42XxzKJB+2x0nSglFVw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.2.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.2.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } @@ -54141,12 +57696,11 @@ } }, "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -54317,6 +57871,19 @@ } } }, + "joi": { + "version": "17.12.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", + "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "peer": true, + "requires": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-cookie": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", @@ -54354,6 +57921,18 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "peer": true + }, + "jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "peer": true + }, "jscodeshift": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", @@ -54574,8 +58153,7 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-buffer": { "version": "3.0.0", @@ -54586,8 +58164,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -54622,14 +58199,12 @@ "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "requires": { "graceful-fs": "^4.1.6" } @@ -54696,14 +58271,12 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" }, "klona": { "version": "2.0.5", @@ -54711,6 +58284,12 @@ "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", "dev": true }, + "konva": { + "version": "9.3.6", + "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.6.tgz", + "integrity": "sha512-dqR8EbcM0hjuilZCBP6xauQ5V3kH3m9kBcsDkqPypQuRgsXbcXUrxqYxhNbdvKZpYNW8Amq94jAD/C0NY3qfBQ==", + "peer": true + }, "last-call-webpack-plugin": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", @@ -54834,8 +58413,7 @@ "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, "levn": { "version": "0.4.1", @@ -54847,6 +58425,33 @@ "type-check": "~0.4.0" } }, + "lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "peer": true, + "requires": { + "debug": "^2.6.9", + "marky": "^1.2.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + } + } + }, "lilconfig": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", @@ -55055,7 +58660,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "requires": { "p-locate": "^5.0.0" } @@ -55068,8 +58672,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "lodash.get": { "version": "4.4.2", @@ -55107,6 +58710,12 @@ "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", "dev": true }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "peer": true + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -55117,7 +58726,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, "requires": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -55148,6 +58756,113 @@ } } }, + "logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "peer": true, + "requires": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "dependencies": { + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "peer": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "peer": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "peer": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "peer": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "peer": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "peer": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "peer": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "peer": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "peer": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -55172,7 +58887,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -55225,7 +58939,6 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, "requires": { "tmpl": "1.0.5" } @@ -55263,6 +58976,12 @@ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", "dev": true }, + "marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "peer": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -55340,6 +59059,12 @@ "fs-monkey": "^1.0.3" } }, + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "peer": true + }, "memoizerific": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", @@ -55428,8 +59153,7 @@ "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "merge2": { "version": "1.4.1", @@ -55449,6 +59173,484 @@ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true }, + "metro": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.8.tgz", + "integrity": "sha512-in7S0W11mg+RNmcXw+2d9S3zBGmCARDxIwoXJAmLUQOQoYsRP3cpGzyJtc7WOw8+FXfpgXvceD0u+PZIHXEL7g==", + "peer": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.20.1", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.80.8", + "metro-cache": "0.80.8", + "metro-cache-key": "0.80.8", + "metro-config": "0.80.8", + "metro-core": "0.80.8", + "metro-file-map": "0.80.8", + "metro-resolver": "0.80.8", + "metro-runtime": "0.80.8", + "metro-source-map": "0.80.8", + "metro-symbolicate": "0.80.8", + "metro-transform-plugins": "0.80.8", + "metro-transform-worker": "0.80.8", + "mime-types": "^2.1.27", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "rimraf": "^3.0.2", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.1", + "yargs": "^17.6.2" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "peer": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "peer": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "requires": { + "ms": "2.0.0" + } + }, + "hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "peer": true + }, + "hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "peer": true, + "requires": { + "hermes-estree": "0.20.1" + } + }, + "image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "peer": true, + "requires": { + "queue": "6.0.2" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "peer": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "peer": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "peer": true + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "peer": true, + "requires": {} + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "peer": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "peer": true + } + } + }, + "metro-babel-transformer": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.8.tgz", + "integrity": "sha512-TTzNwRZb2xxyv4J/+yqgtDAP2qVqH3sahsnFu6Xv4SkLqzrivtlnyUbaeTdJ9JjtADJUEjCbgbFgUVafrXdR9Q==", + "peer": true, + "requires": { + "@babel/core": "^7.20.0", + "hermes-parser": "0.20.1", + "nullthrows": "^1.1.1" + }, + "dependencies": { + "hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "peer": true + }, + "hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "peer": true, + "requires": { + "hermes-estree": "0.20.1" + } + } + } + }, + "metro-cache": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.8.tgz", + "integrity": "sha512-5svz+89wSyLo7BxdiPDlwDTgcB9kwhNMfNhiBZPNQQs1vLFXxOkILwQiV5F2EwYT9DEr6OPZ0hnJkZfRQ8lDYQ==", + "peer": true, + "requires": { + "metro-core": "0.80.8", + "rimraf": "^3.0.2" + } + }, + "metro-cache-key": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.8.tgz", + "integrity": "sha512-qWKzxrLsRQK5m3oH8ePecqCc+7PEhR03cJE6Z6AxAj0idi99dHOSitTmY0dclXVB9vP2tQIAE8uTd8xkYGk8fA==", + "peer": true + }, + "metro-config": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.8.tgz", + "integrity": "sha512-VGQJpfJawtwRzGzGXVUoohpIkB0iPom4DmSbAppKfumdhtLA8uVeEPp2GM61kL9hRvdbMhdWA7T+hZFDlo4mJA==", + "peer": true, + "requires": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "jest-validate": "^29.6.3", + "metro": "0.80.8", + "metro-cache": "0.80.8", + "metro-core": "0.80.8", + "metro-runtime": "0.80.8" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "peer": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "peer": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "peer": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "peer": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "peer": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "peer": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "peer": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "peer": true + } + } + }, + "metro-core": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.8.tgz", + "integrity": "sha512-g6lud55TXeISRTleW6SHuPFZHtYrpwNqbyFIVd9j9Ofrb5IReiHp9Zl8xkAfZQp8v6ZVgyXD7c130QTsCz+vBw==", + "peer": true, + "requires": { + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.80.8" + } + }, + "metro-file-map": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.8.tgz", + "integrity": "sha512-eQXMFM9ogTfDs2POq7DT2dnG7rayZcoEgRbHPXvhUWkVwiKkro2ngcBE++ck/7A36Cj5Ljo79SOkYwHaWUDYDw==", + "peer": true, + "requires": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "peer": true, + "requires": { + "ms": "2.0.0" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "peer": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "peer": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "metro-minify-terser": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.8.tgz", + "integrity": "sha512-y8sUFjVvdeUIINDuW1sejnIjkZfEF+7SmQo0EIpYbWmwh+kq/WMj74yVaBWuqNjirmUp1YNfi3alT67wlbBWBQ==", + "peer": true, + "requires": { + "terser": "^5.15.0" + } + }, + "metro-resolver": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.8.tgz", + "integrity": "sha512-JdtoJkP27GGoZ2HJlEsxs+zO7jnDUCRrmwXJozTlIuzLHMRrxgIRRby9fTCbMhaxq+iA9c+wzm3iFb4NhPmLbQ==", + "peer": true + }, + "metro-runtime": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.8.tgz", + "integrity": "sha512-2oScjfv6Yb79PelU1+p8SVrCMW9ZjgEiipxq7jMRn8mbbtWzyv3g8Mkwr+KwOoDFI/61hYPUbY8cUnu278+x1g==", + "peer": true, + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "metro-source-map": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.8.tgz", + "integrity": "sha512-+OVISBkPNxjD4eEKhblRpBf463nTMk3KMEeYS8Z4xM/z3qujGJGSsWUGRtH27+c6zElaSGtZFiDMshEb8mMKQg==", + "peer": true, + "requires": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "invariant": "^2.2.4", + "metro-symbolicate": "0.80.8", + "nullthrows": "^1.1.1", + "ob1": "0.80.8", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "peer": true + } + } + }, + "metro-symbolicate": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.8.tgz", + "integrity": "sha512-nwhYySk79jQhwjL9QmOUo4wS+/0Au9joEryDWw7uj4kz2yvw1uBjwmlql3BprQCBzRdB3fcqOP8kO8Es+vE31g==", + "peer": true, + "requires": { + "invariant": "^2.2.4", + "metro-source-map": "0.80.8", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "peer": true + } + } + }, + "metro-transform-plugins": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.8.tgz", + "integrity": "sha512-sSu8VPL9Od7w98MftCOkQ1UDeySWbsIAS5I54rW22BVpPnI3fQ42srvqMLaJUQPjLehUanq8St6OMBCBgH/UWw==", + "peer": true, + "requires": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "nullthrows": "^1.1.1" + } + }, + "metro-transform-worker": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.8.tgz", + "integrity": "sha512-+4FG3TQk3BTbNqGkFb2uCaxYTfsbuFOCKMMURbwu0ehCP8ZJuTUramkaNZoATS49NSAkRgUltgmBa4YaKZ5mqw==", + "peer": true, + "requires": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "metro": "0.80.8", + "metro-babel-transformer": "0.80.8", + "metro-cache": "0.80.8", + "metro-cache-key": "0.80.8", + "metro-minify-terser": "0.80.8", + "metro-source-map": "0.80.8", + "metro-transform-plugins": "0.80.8", + "nullthrows": "^1.1.1" + } + }, "microevent.ts": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", @@ -55459,7 +59661,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -55486,20 +59687,17 @@ "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -55507,8 +59705,7 @@ "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "mimic-response": { "version": "1.0.1", @@ -55571,7 +59768,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -55683,8 +59879,7 @@ "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "modify-values": { "version": "1.0.1", @@ -55741,8 +59936,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "7.2.5", @@ -55855,14 +60049,12 @@ "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "nested-error-stacks": { "version": "2.1.1", @@ -55885,11 +60077,22 @@ "lower-case": "^1.1.1" } }, + "nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "peer": true + }, + "node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "peer": true + }, "node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, "requires": { "minimatch": "^3.0.2" } @@ -55898,7 +60101,6 @@ "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, "requires": { "whatwg-url": "^5.0.0" }, @@ -55906,20 +60108,17 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -55945,8 +60144,7 @@ "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node-libs-browser": { "version": "2.2.1", @@ -56025,8 +60223,13 @@ "node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "peer": true }, "normalize-package-data": { "version": "2.5.0", @@ -56051,8 +60254,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-range": { "version": "0.1.2", @@ -56070,7 +60272,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "requires": { "path-key": "^3.0.0" } @@ -56096,6 +60297,12 @@ "boolbase": "^1.0.0" } }, + "nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "peer": true + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -56114,11 +60321,16 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "ob1": { + "version": "0.80.8", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.8.tgz", + "integrity": "sha512-QHJQk/lXMmAW8I7AIM3in1MSlwe1umR72Chhi8B7Xnq6mzjhBKkA6Fy/zAhQnGkA4S912EPCEvTij5yh+EQTAA==", + "peer": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-copy": { "version": "0.1.0", @@ -56203,8 +60415,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -56219,7 +60430,6 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, "requires": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -56302,7 +60512,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -56310,14 +60519,12 @@ "on-headers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "requires": { "wrappy": "1" } @@ -56326,7 +60533,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "requires": { "mimic-fn": "^2.1.0" } @@ -56722,7 +60928,6 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, "requires": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -56813,7 +61018,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "requires": { "yocto-queue": "^0.1.0" } @@ -56822,7 +61026,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "requires": { "p-limit": "^3.0.2" } @@ -56858,8 +61061,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "package-json": { "version": "6.5.0", @@ -57002,8 +61204,7 @@ "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "pascal-case": { "version": "3.1.2", @@ -57057,26 +61258,22 @@ "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { "version": "0.1.7", @@ -57118,14 +61315,12 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pidtree": { "version": "0.6.0", @@ -57157,8 +61352,7 @@ "pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" }, "pkg-dir": { "version": "4.2.0", @@ -58728,12 +62922,11 @@ } }, "pretty-format": { - "version": "29.2.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.1.tgz", - "integrity": "sha512-Y41Sa4aLCtKAXvwuIpTvcFBkyeYp2gdFWzXGA+ZNES3VwURIB165XO/z7CjETwzCCS53MjW/rLMyyqEnTtaOfA==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "requires": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -58741,8 +62934,7 @@ "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" } } }, @@ -58796,6 +62988,15 @@ } } }, + "promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "peer": true, + "requires": { + "asap": "~2.0.6" + } + }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -58839,7 +63040,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -58849,7 +63049,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -58859,8 +63058,7 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" } } }, @@ -59059,6 +63257,15 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "peer": true, + "requires": { + "inherits": "~2.0.3" + } + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -59099,8 +63306,7 @@ "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { "version": "2.5.1", @@ -59183,6 +63389,25 @@ "loose-envify": "^1.1.0" } }, + "react-devtools-core": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "peer": true, + "requires": { + "shell-quote": "^1.6.1", + "ws": "^7" + }, + "dependencies": { + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "peer": true, + "requires": {} + } + } + }, "react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -59204,6 +63429,39 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "react-konva": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-18.2.10.tgz", + "integrity": "sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==", + "peer": true, + "requires": { + "@types/react-reconciler": "^0.28.2", + "its-fine": "^1.1.1", + "react-reconciler": "~0.29.0", + "scheduler": "^0.23.0" + }, + "dependencies": { + "@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "peer": true, + "requires": { + "@types/react": "*" + } + }, + "react-reconciler": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz", + "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + } + } + }, "react-leaflet": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", @@ -59212,6 +63470,242 @@ "@react-leaflet/core": "^2.1.0" } }, + "react-native": { + "version": "0.73.6", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.6.tgz", + "integrity": "sha512-oqmZe8D2/VolIzSPZw+oUd6j/bEmeRHwsLn1xLA5wllEYsZ5zNuMsDus235ONOnCRwexqof/J3aztyQswSmiaA==", + "peer": true, + "requires": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "12.3.6", + "@react-native-community/cli-platform-android": "12.3.6", + "@react-native-community/cli-platform-ios": "12.3.6", + "@react-native/assets-registry": "0.73.1", + "@react-native/codegen": "0.73.3", + "@react-native/community-cli-plugin": "0.73.17", + "@react-native/gradle-plugin": "0.73.4", + "@react-native/js-polyfills": "0.73.1", + "@react-native/normalize-colors": "0.73.2", + "@react-native/virtualized-lists": "0.73.4", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "deprecated-react-native-prop-types": "^5.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^4.27.7", + "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "dependencies": { + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "peer": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "peer": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "peer": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "peer": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "peer": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "peer": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "peer": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "peer": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "peer": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, + "react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "peer": true + }, + "scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "peer": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "peer": true + } + } + }, + "react-reconciler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", + "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.21.0" + }, + "dependencies": { + "scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + } + } + }, "react-redux": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.4.tgz", @@ -59236,6 +63730,29 @@ "resolved": "https://registry.npmjs.org/react-router-redux/-/react-router-redux-4.0.8.tgz", "integrity": "sha512-lzlK+S6jZnn17BZbzBe6F8ok3YAhGAUlyWgRu3cz5mT199gKxfem5lNu3qcgzRiVhNEOFVG0/pdT+1t4aWhoQw==" }, + "react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "peer": true, + "requires": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + } + }, + "react-spring": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.7.3.tgz", + "integrity": "sha512-oTxDpFV5gzq7jQX6+bU0SVq+vX8VnuuT5c8Zwn6CpDErOPvCmV+DRkPiEBtaL3Ozgzwiy5yFx83N0h303j/r3A==", + "requires": { + "@react-spring/core": "~9.7.3", + "@react-spring/konva": "~9.7.3", + "@react-spring/native": "~9.7.3", + "@react-spring/three": "~9.7.3", + "@react-spring/web": "~9.7.3", + "@react-spring/zdog": "~9.7.3" + } + }, "react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -59263,6 +63780,26 @@ "tslib": "^2.1.0" } }, + "react-use-measure": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz", + "integrity": "sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==", + "peer": true, + "requires": { + "debounce": "^1.2.1" + } + }, + "react-zdog": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/react-zdog/-/react-zdog-1.2.2.tgz", + "integrity": "sha512-Ix7ALha91aOEwiHuxumCeYbARS5XNpc/w0v145oGkM6poF/CvhKJwzLhM5sEZbtrghMA+psAhOJkCTzJoseicA==", + "peer": true, + "requires": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "resize-observer-polyfill": "^1.5.1" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -59352,7 +63889,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -59368,6 +63904,12 @@ "picomatch": "^2.2.1" } }, + "readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "peer": true + }, "recast": { "version": "0.14.7", "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz", @@ -59425,14 +63967,12 @@ "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, "requires": { "regenerate": "^1.4.2" } @@ -59446,7 +63986,6 @@ "version": "0.15.0", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", - "dev": true, "requires": { "@babel/runtime": "^7.8.4" } @@ -59483,7 +64022,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz", "integrity": "sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==", - "dev": true, "requires": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", @@ -59514,14 +64052,12 @@ "regjsgen": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true + "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==" }, "regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, "requires": { "jsesc": "~0.5.0" }, @@ -59529,8 +64065,7 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" } } }, @@ -59805,8 +64340,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "require-from-string": { "version": "2.0.2", @@ -59814,6 +64348,12 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "peer": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -59829,7 +64369,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -59884,7 +64423,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "requires": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -59930,7 +64468,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -60388,7 +64925,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -60414,7 +64950,6 @@ "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "2.0.0", @@ -60435,7 +64970,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" }, @@ -60443,19 +64977,23 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, + "serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "peer": true + }, "serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -60564,7 +65102,6 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -60575,14 +65112,12 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "set-function-length": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, "requires": { "define-data-property": "^1.1.2", "es-errors": "^1.3.0", @@ -60656,8 +65191,7 @@ "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "sha.js": { "version": "2.4.11", @@ -60673,7 +65207,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "requires": { "kind-of": "^6.0.2" } @@ -60682,7 +65215,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -60690,8 +65222,13 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "peer": true }, "shelljs": { "version": "0.8.5", @@ -60726,8 +65263,7 @@ "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-color-scale": { "version": "1.0.1", @@ -60765,8 +65301,7 @@ "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "size-plugin": { "version": "3.0.0", @@ -60851,8 +65386,7 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "slice-ansi": { "version": "4.0.0", @@ -61107,7 +65641,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -61224,8 +65757,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "sshpk": { "version": "1.17.0", @@ -61277,7 +65809,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, "requires": { "escape-string-regexp": "^2.0.0" }, @@ -61285,8 +65816,7 @@ "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" } } }, @@ -61321,6 +65851,23 @@ "stacktrace-gps": "^3.0.4" } }, + "stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "peer": true, + "requires": { + "type-fest": "^0.7.1" + }, + "dependencies": { + "type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "peer": true + } + } + }, "standard-version": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", @@ -61488,8 +66035,7 @@ "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "stealthy-require": { "version": "1.1.1", @@ -61616,7 +66162,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" }, @@ -61624,8 +66169,7 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, @@ -61649,7 +66193,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -61756,7 +66299,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -61782,8 +66324,7 @@ "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" }, "strip-indent": { "version": "3.0.0", @@ -61817,6 +66358,12 @@ } } }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, "style-loader": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", @@ -61894,11 +66441,16 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.2.tgz", "integrity": "sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA==" }, + "sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "peer": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -61916,8 +66468,14 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "suspend-react": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", + "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", + "peer": true, + "requires": {} }, "svgo": { "version": "1.3.2", @@ -62209,7 +66767,6 @@ "version": "0.8.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "dev": true, "requires": { "rimraf": "~2.6.2" }, @@ -62218,7 +66775,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -62228,8 +66784,7 @@ "temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" }, "tempy": { "version": "0.6.0", @@ -62265,7 +66820,6 @@ "version": "5.15.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", - "dev": true, "requires": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -62337,6 +66891,12 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "three": { + "version": "0.163.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.163.0.tgz", + "integrity": "sha512-HlMgCb2TF/dTLRtknBnjUTsR8FsDqBY43itYop2+Zg822I+Kd0Ua2vs8CvfBVefXkBdNDrLMoRTGCIIpfCuDew==", + "peer": true + }, "throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", @@ -62425,8 +66985,7 @@ "tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, "to-arraybuffer": { "version": "1.0.1", @@ -62437,8 +66996,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, "to-object-path": { "version": "0.3.0", @@ -62482,7 +67040,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -62495,8 +67052,7 @@ "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "toposort": { "version": "1.0.7", @@ -62656,8 +67212,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { "version": "0.20.2", @@ -62807,14 +67362,12 @@ "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" }, "unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "requires": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -62823,14 +67376,12 @@ "unicode-match-property-value-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" }, "unicode-property-aliases-ecmascript": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" }, "unified": { "version": "9.2.0", @@ -62988,14 +67539,12 @@ "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "unquote": { "version": "1.1.1", @@ -63063,7 +67612,6 @@ "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -63240,8 +67788,7 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "3.4.0", @@ -63296,8 +67843,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "vendors": { "version": "1.0.4", @@ -63352,6 +67898,12 @@ "unist-util-stringify-position": "^2.0.0" } }, + "vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "peer": true + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -63386,7 +67938,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, "requires": { "makeerror": "1.0.12" } @@ -63679,7 +68230,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, "requires": { "defaults": "^1.0.3" } @@ -64418,6 +68968,12 @@ } } }, + "whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "peer": true + }, "whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", @@ -64439,7 +68995,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -64457,6 +69012,12 @@ "is-symbol": "^1.0.3" } }, + "which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "peer": true + }, "which-typed-array": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", @@ -64811,7 +69372,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -64821,8 +69381,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "write-file-atomic": { "version": "3.0.3", @@ -64840,7 +69399,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "dev": true, "requires": { "async-limiter": "~1.0.0" } @@ -64890,14 +69448,12 @@ "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { "version": "1.10.2", @@ -64945,8 +69501,20 @@ "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "zdog": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/zdog/-/zdog-1.1.3.tgz", + "integrity": "sha512-raRj6r0gPzopFm5XWBJZr/NuV4EEnT4iE+U3dp5FV5pCb588Gmm3zLIp/j9yqqcMiHH8VNQlerLTgOqL7krh6w==", + "peer": true + }, + "zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "peer": true, + "requires": {} }, "zwitch": { "version": "1.0.5", diff --git a/package.json b/package.json index 749e20c93..da10654c9 100644 --- a/package.json +++ b/package.json @@ -94,10 +94,12 @@ "react-leaflet": "^4.2.1", "react-redux": "^8.0.4", "react-router-redux": "^4.0.8", + "react-spring": "^9.7.1", "react-use": "^17.4.0", "redux": "^4.2.0", "redux-observable": "^2.0.0", "simple-color-scale": "^1.0.1", + "tailwindcss": "^3.2.6", "timeago.js": "^4.0.2" }, "husky": { diff --git a/plugins/lime-plugin-locate/index.ts b/plugins/lime-plugin-locate/index.ts old mode 100755 new mode 100644 diff --git a/plugins/lime-plugin-locate/src/locateMenu.js b/plugins/lime-plugin-locate/src/locateMenu.js index b98303c13..1a389c660 100755 --- a/plugins/lime-plugin-locate/src/locateMenu.js +++ b/plugins/lime-plugin-locate/src/locateMenu.js @@ -1,12 +1,12 @@ import { Trans } from "@lingui/macro"; -import { MapIcon } from "components/icons/teenny/map"; +import { PinIcon } from "components/icons/teenny/pin"; export const LocateMenu = () => ( - + - Map + Locate ); diff --git a/plugins/lime-plugin-mesh-wide/index.ts b/plugins/lime-plugin-mesh-wide/index.ts new file mode 100644 index 000000000..3ea2bc26a --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/index.ts @@ -0,0 +1,10 @@ +import { MeshWideMenu } from "./src/meshWideMenu"; +import MeshWidePage from "./src/meshWidePage"; +import MeshWideConfigPage from "./src/screens/configPage"; + +export default { + name: "MeshWide", + page: MeshWidePage, + menu: MeshWideMenu, + additionalRoutes: [["/meshwide/config", MeshWideConfigPage]], +} as LimePlugin; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Components.tsx b/plugins/lime-plugin-mesh-wide/src/components/Components.tsx new file mode 100644 index 000000000..7305e4563 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/Components.tsx @@ -0,0 +1,58 @@ +import { VNode } from "preact"; + +import { Button } from "components/buttons/button"; +import { BinIcon } from "components/icons/bin"; +import { EditIcon } from "components/icons/edit"; + +import SuccessIcon from "plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon"; +import ErrorIcon from "plugins/lime-plugin-mesh-wide/src/icons/errorIcon"; + +interface IStatusMessage { + isError: boolean; + children: VNode | string; +} + +export const StatusAndButton = ({ + isError, + children, + btn, + onClick, +}: { btn?: VNode | string; onClick?: () => void } & IStatusMessage) => { + const containerClasses = + "flex flex-col items-center justify-center text-center bg-white py-5 gap-3"; + + return ( +
+ {children} + {btn && } +
+ ); +}; + +export const StatusMessage = ({ + isError, + children, + classes, +}: { + classes?: string; +} & IStatusMessage) => ( +
+ {isError ? : } + {children} +
+); + +export const EditOrDelete = ({ + onEdit, + onDelete, +}: { + onEdit: (e) => void; + onDelete: (e) => void; +}) => ( +
+ + +
+); diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx new file mode 100644 index 000000000..f9c15ef42 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -0,0 +1,262 @@ +import { Trans } from "@lingui/macro"; +import { useState } from "preact/hooks"; + +import Tabs from "components/tabs"; + +import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; +import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; +import { + getQueryByLinkType, + usePointToPointErrors, +} from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; +import ErrorIcon from "plugins/lime-plugin-mesh-wide/src/icons/errorIcon"; +import { MacToMacLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { readableBytes } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; +import { + BaseMacToMacLink, + BatmanLinkErrorCodes, + IBatManLinkData, + ILinkMtoMErrors, + IWifiLinkData, + LinkMapFeature, + WifiLinkErrorCodes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { isEmpty } from "utils/utils"; + +import { Row, TitleAndText } from "./index"; + +const BatmanDetail = ({ + name, + errorsArray, + node, +}: { + name: string; + errorsArray: BatmanLinkErrorCodes[] | undefined; + node: IBatManLinkData; +}) => { + return ( + <> + +
+ {name}{" "} + {errorsArray?.length > 0 && } +
+
+ + Iface}> + {node?.iface} + + Last seen}> + <>{node?.last_seen_msecs} ms + + + + ); +}; + +const WifiDetail = ({ + name, + errorsArray, + node, +}: { + name: string; + errorsArray: WifiLinkErrorCodes[]; + node: IWifiLinkData; +}) => { + return ( +
+ +
+ {name}{" "} + {errorsArray?.length > 0 && } +
+
+ + Signal} + error={ + errorsArray?.includes( + WifiLinkErrorCodes.SIGNAL_LOSS + ) ? ( + + The signal is X below the reference state + + ) : null + } + > + {node?.signal?.toString() ?? "0"} + + Chains} + error={ + errorsArray?.includes(WifiLinkErrorCodes.CHAIN_LOSS) ? ( + + The difference between chains is too big + + ) : null + } + > + {node?.chains?.toString() ?? "0/0"} + + + + TxRate}> + {`${readableBytes(node.tx_rate)}`} + + RxRate}> + {`${readableBytes(node.rx_rate)}`} + + +
+ ); +}; + +const SelectedLink = ({ + linkDetail, + errors, +}: { + linkDetail: BaseMacToMacLink; + errors: ILinkMtoMErrors | undefined; +}) => { + if (linkDetail === undefined || (errors && !errors?.linkUp)) + return ( +
+ This link seems down +
+ ); + + const names = linkDetail?.names; + const linkType = linkDetail.type; + + return ( + <> + + {names && ( +
+ + Link from {names[0]} to{" "} + {names[1]} + +
+ )} +
+ {names.map((name, i) => { + const node = linkDetail.linkByName(name); + const errorsArray = errors?.linkErrors[name] ?? []; + return linkType === "wifi_links_info" ? ( + + ) : ( + + ); + })} + + ); +}; + +const LinkFeatureDetail = ({ actual, reference }: LinkMapFeature) => { + const linkToShow = reference ?? actual; + const [selectedLink, setSelectedLink] = useState(0); + const { errors } = usePointToPointErrors({ + id: linkToShow.id, + type: linkToShow.type, + }); + const linkType = linkToShow.type; + + const tabs = linkToShow.links.map( + (link: MacToMacLink, i) => { + return { + key: i, + repr: ( +
+ + Link {i + 1}{" "} + {errors && + errors?.macToMacErrors[link.id]?.hasErrors ? ( + + ) : null} + +
+ ), + }; + } + ); + + return ( +
+ {tabs?.length > 1 && ( + + )} + {selectedLink !== null && ( + + )} +
+ ); +}; + +export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { + const isNewNode = !reference; + + const { errors } = usePointToPointErrors({ + id: reference.id, + type: reference.type, + }); + + // Check if there are errors of global reference state to shown + const { reference: fetchDataReference } = getQueryByLinkType( + reference.type + ); + const { data: referenceData, isError: isReferenceError } = + fetchDataReference({}); + let referenceError = false; + if (!referenceData || isEmpty(referenceData) || isReferenceError) { + referenceError = true; + } + + // Mutation to update the reference state + const { mutate, btnText } = useSetReferenceState(reference.type); + + let errorMessage = Same status as in the reference state; + if (referenceError) { + errorMessage = Reference is not set or has errors; + } else if (errors?.hasErrors) { + errorMessage = This link has errors; + } else if (isNewNode) { + errorMessage = ( + This Link is not registered on the reference state + ); + } + + const hasError = errors?.hasErrors || referenceError || isNewNode; + + return ( + + {errorMessage} + + ); +}; + +export default LinkFeatureDetail; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx new file mode 100644 index 000000000..25ab29ec3 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -0,0 +1,149 @@ +import { Trans } from "@lingui/macro"; + +import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; +import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; +import { + Row, + TitleAndText, +} from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; +import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors"; +import { getArrayDifference } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; +import { useMeshWideNodesReference } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { + NodeErrorCodes, + NodeMapFeature, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { isEmpty } from "utils/utils"; + +const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => { + // If node no reference is set, is a new node + const nodeToShow = reference ?? actual; + + const uptime = nodeToShow.uptime; + const firmware = nodeToShow.firmware_version; + const ipv6 = nodeToShow.ipv6; + const ipv4 = nodeToShow.ipv4; + const device = nodeToShow.device; + const { errors, isDown } = useSingleNodeErrors({ + actual, + reference, + }); + + if (isDown) { + return This node seems down; + } + const macs = actual.macs; + + return ( +
+ +
{name}
+ {/*todo(kon): implement safe_reboot*/} + {/**/} +
+ + {!isDown ? ( + Uptime}> + {uptime.toString()} + + ) : ( + Uptime}> + The node is down + + )} + Firmware version}> + {firmware} + + + + IPv4}>{ipv4} + IPv6}>{ipv6} + + + Device}> + {device} + + + + Macs}> +
+ {macs.map((mac, k) => ( +
{mac}
+ ))} +
+
+ {errors.includes(NodeErrorCodes.MACS_MISSMATCH) && ( + Macs not found} + error={ + This macs are not on the actual state + } + > + <> + {getArrayDifference(reference.macs, macs).map( + (mac, k) => ( +
{mac}
+ ) + )} + +
+ )} +
+
+ ); +}; + +export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { + const { + hasErrors: hasNodeErrors, + isDown, + isNewNode, + } = useSingleNodeErrors({ + actual, + reference, + }); + + // Check if there are errors of global reference state to shown + const { data: meshWideNodesReference, isError: isReferenceError } = + useMeshWideNodesReference({}); + + // Mutation to update the reference state + const { mutate, btnText } = useSetReferenceState("node_info"); + + let referenceError = false; + if ( + !meshWideNodesReference || + isEmpty(meshWideNodesReference) || + isReferenceError + ) { + referenceError = true; + } + + let errorMessage = Same status as in the reference state; + if (referenceError) { + errorMessage = Reference is not set or has errors; + } else if (isDown) { + errorMessage = In the reference state this node is on; + } else if (isNewNode) { + errorMessage = ( + This node is not registered on the reference state + ); + } + + const hasErrors = hasNodeErrors || referenceError || isNewNode; + + return ( + + {errorMessage} + + ); +}; + +export default NodeDetails; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx new file mode 100644 index 000000000..fda447598 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx @@ -0,0 +1,69 @@ +import { Trans } from "@lingui/macro"; +import { useCallback } from "react"; + +import { useToast } from "components/toast/toastProvider"; + +import { useSetReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; +import { + useSetBatmanLinksInfoReferenceState, + useSetNodeInfoReferenceState, + useSetWifiLinksInfoReferenceState, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { DataTypes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +const toastDuration = 5000; + +export const useSetReferenceState = (dataType: T) => { + const { toggleModal, confirmModal, isModalOpen } = + useSetReferenceStateModal(); + const { showToast } = useToast(); + + const mutationOpts = { + onSuccess: () => { + showToast({ + text: New reference state set!, + duration: toastDuration, + }); + }, + onError: () => { + showToast({ + text: Error setting new reference state!, + duration: toastDuration, + }); + }, + onSettled: () => { + if (isModalOpen) toggleModal(); + }, + }; + + const { mutateAsync: nodesMutation } = + useSetNodeInfoReferenceState(mutationOpts); + const { mutateAsync: wifiMutation } = + useSetWifiLinksInfoReferenceState(mutationOpts); + const { mutateAsync: batmanMutation } = + useSetBatmanLinksInfoReferenceState(mutationOpts); + + const btnText = Set {dataType} reference state; + + const mutate = useCallback(async () => { + switch (dataType) { + case "node_info": + await confirmModal(dataType, async () => { + await nodesMutation(); + }); + break; + case "wifi_links_info": + confirmModal(dataType, async () => { + await wifiMutation(); + }); + break; + case "bat_links_info": + confirmModal(dataType, async () => { + await batmanMutation(); + }); + break; + } + }, [batmanMutation, confirmModal, dataType, nodesMutation, wifiMutation]); + + return { mutate, btnText }; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx new file mode 100644 index 000000000..50e727333 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx @@ -0,0 +1,102 @@ +import { Trans } from "@lingui/macro"; + +import { Button } from "components/buttons/button"; + +import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; +import { Row } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; +import { + DataTypes, + ErrorsDetails, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +const SetDataTypeBtn = ({ dataType }: { dataType: T }) => { + const { mutate, btnText } = useSetReferenceState(dataType); + return ( +
+
{dataType}
+ +
+ ); +}; + +export const ShowErrorsDetail = ({ errors }: { errors: ErrorsDetails }) => { + return ( +
+ {errors.invalidNodes.size > 0 && ( +
+ +
+ Invalid Nodes +
+
+ + + The following nodes are not located or have not + reference state. Please, set their location to see + them on the map: + + + {[...errors.invalidNodes].map((name, k) => ( +
{name}
+ ))} +
+ )} + {errors.dataNotSetErrors.length > 0 && ( +
+ +
+ Reference State is not set +
+
+ + + The following shared states packages have not data + set + + +
+ {[...errors.dataNotSetErrors].map((data, k) => { + let dataType = data.queryKey[2]["data_type"]; + if (!dataType) { + dataType = JSON.stringify( + data.queryKey, + null, + 2 + ); + return ( +
+ {dataType}: {data?.error?.toString()} +
+ ); + } + return ( + + ); + })} +
+
+ )} + {errors.meshWideDataErrors.length > 0 && ( +
+ +
+ Shared state error +
+
+ + + The following shared states packages have errors. + Are they installed or properly initialized? + + + {[...errors.meshWideDataErrors].map((data, k) => ( +
+ {JSON.stringify(data.queryKey, null, 2)}:{" "} + {data?.error?.toString()} +
+ ))} +
+ )} +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index.tsx new file mode 100644 index 000000000..5171e52ed --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index.tsx @@ -0,0 +1,81 @@ +import { VNode } from "preact"; + +import LinkFeatureDetail, { + LinkReferenceStatus, +} from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail"; +import NodeDetails, { + NodeReferenceStatus, +} from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail"; +import { ShowErrorsDetail } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail"; +import { + LinkMapFeature, + NodeMapFeature, + SelectedMapFeature, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const TitleAndText = ({ + title, + children, + error, +}: { + title: VNode | string; + children: VNode | string; + error?: VNode | string; +}) => { + return ( +
+
{title}
+
{children}
+ {error &&
{error}
} +
+ ); +}; + +export const Row = ({ children }: { children: any }) => { + return ( +
+ {children} +
+ ); +}; + +export const FeatureDetail = ({ + selectedFeature, +}: { + selectedFeature: SelectedMapFeature; +}) => { + if (!selectedFeature) return; + switch (selectedFeature.type) { + case "link": + return ; + case "node": + return ; + case "errorsDetails": + return ; + } +}; + +export const FeatureReferenceStatus = ({ + selectedFeature, +}: { + selectedFeature: SelectedMapFeature; +}) => { + if (!selectedFeature) return; + const type = selectedFeature.type; + + if (type === "link") { + return ( + + ); + } else if (type === "node") { + return ( + + ); + } +}; + +export default FeatureDetail; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx new file mode 100644 index 000000000..30600437b --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx @@ -0,0 +1,61 @@ +import { useCallback } from "react"; + +import { useMeshWideDataErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors"; +import { useNodes } from "plugins/lime-plugin-mesh-wide/src/hooks/useNodes"; +import { WarningIcon } from "plugins/lime-plugin-mesh-wide/src/icons/warningIcon"; +import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { InvalidNodes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const FloatingAlert = () => { + const { setData: setSelectedFeature, data: selectedMapFeature } = + useSelectedMapFeature(); + + const { + hasInvalidNodes, + invalidNodes: { invalidNodesReference, invalidNodesActual }, + } = useNodes(); + const { meshWideDataErrors, dataNotSetErrors } = useMeshWideDataErrors(); + + const hasErrors = + hasInvalidNodes || meshWideDataErrors.length || dataNotSetErrors.length; + + const callback = useCallback(() => { + if (selectedMapFeature && selectedMapFeature.id === "errorsDetails") { + setSelectedFeature(null); + return; + } + const invalidNodes: InvalidNodes = new Set([ + ...Object.keys(invalidNodesReference ?? []), + ...Object.keys(invalidNodesActual ?? []), + ]); + + setSelectedFeature({ + id: "errorsDetails", + type: "errorsDetails", + feature: { + invalidNodes, + meshWideDataErrors, + dataNotSetErrors, + }, + }); + }, [ + dataNotSetErrors, + invalidNodesActual, + invalidNodesReference, + meshWideDataErrors, + selectedMapFeature, + setSelectedFeature, + ]); + + return hasErrors ? ( +
+
+ +
+
+ ) : null; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx new file mode 100644 index 000000000..2a3d50f59 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx @@ -0,0 +1,77 @@ +import L from "leaflet"; +import { Polyline } from "react-leaflet"; + +import { useLocatedLinks } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; +import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; + +interface ILinkLineProps { + referenceLink?: PontToPointLink; + actualLink: PontToPointLink | undefined; +} + +export const LinkLine = ({ referenceLink, actualLink }: ILinkLineProps) => { + const { data: selectedMapFeature, setData: setSelectedMapFeature } = + useSelectedMapFeature(); + + const linkToShow = referenceLink ?? actualLink; + let isNewNode = false; + if (!referenceLink) { + isNewNode = true; + } + + const type = linkToShow.type; + const isSelected = selectedMapFeature?.id === linkToShow.id; + + const { linksErrors } = useLocatedLinks({ type }); + + let hasError = false; + let linkUp = true; + + if (!isNewNode && linksErrors && linksErrors[referenceLink.id]) { + hasError = linksErrors[referenceLink.id].hasErrors; + linkUp = linksErrors[referenceLink.id].linkUp; + } + + const _setSelectedFeature = () => { + setSelectedMapFeature({ + id: linkToShow.id, + feature: { reference: linkToShow, actual: actualLink }, + type: "link", + }); + }; + + const getPathOpts = (isSelected) => { + return { + color: hasError ? "#eb7575" : "#76bd7d", + weight: isSelected ? 7 : 5, + opacity: isSelected ? 1 : 0.8, + dashArray: isNewNode || !linkUp ? "7 10" : null, // Show dash array also when is a new node + }; + }; + + const coordinates = linkToShow.coordinates.map((c) => [c.lat, c.long]); + + return ( + { + L.DomEvent.stopPropagation(e); + _setSelectedFeature(); + }, + mouseover: (e) => { + const l = e.target; + l.setStyle(getPathOpts(true)); + }, + mouseout: (event) => { + const l = event.target; + l.setStyle(getPathOpts(isSelected)); + }, + }} + /> + ); +}; + +export default LinkLine; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx new file mode 100644 index 000000000..cf72d4423 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx @@ -0,0 +1,65 @@ +import L from "leaflet"; +import { Marker, Tooltip } from "react-leaflet"; + +import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors"; +import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { + INodeInfo, + NodeMapFeature, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import style from "./style.less"; + +const NodeMarker = ({ + name, + actual, + reference, +}: { + name: string; + reference?: INodeInfo | undefined; + actual: INodeInfo; +}) => { + const { data: selectedMapFeature, setData: setSelectedMapFeature } = + useSelectedMapFeature(); + + const { hasErrors, isDown, isNewNode } = useSingleNodeErrors({ + actual, + reference, + }); + + const markerClasses = `${ + selectedMapFeature?.id === name && style.selectedMarker + } + ${hasErrors ? style.errorMarker : style.syncedMarker} + ${isDown && style.notUpMarker} + ${isNewNode && style.newNodeMarker}`; + + // If node no reference is set, is a new node + const nodeToShow = reference ?? actual; + + return ( + `, + })} + eventHandlers={{ + click: (e) => { + L.DomEvent.stopPropagation(e); + setSelectedMapFeature({ + id: name, + feature: { actual, reference, name } as NodeMapFeature, + type: "node", + }); + }, + }} + > + {name} + + ); +}; + +export default NodeMarker; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/style.less b/plugins/lime-plugin-mesh-wide/src/components/Map/style.less new file mode 100644 index 000000000..23662c5aa --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/style.less @@ -0,0 +1,69 @@ +@good: #76bd7d; +@warning: #eaab7e; +@bad: #eb7575; + +//Delete a leaflet strange div +.leaflet-div-custom-icon { + background: none !important; + border: none !important; +} + +// Default Marker shape +.defaultMarker { + position: absolute; + left: -1.4rem; + top: -1.5rem; + border-radius: 50% 50% 50% 0; + width: 3rem; + height: 3rem; + transform: rotate(-45deg); +} +.defaultMarker::after { + position: absolute; + content: ""; + width: 8px; + height: 8px; + border-radius: 50%; + top: 55%; + left: 56%; + margin-left: -6px; + margin-top: -5px; + background-color: #fff; +} + +// Marker status colors +.syncedMarker { + background-color: @good; +} +.errorMarker { + background-color: @bad; +} +.notUpMarker { + opacity: 0.8; + background-size: 10px 10px; + background-image: repeating-linear-gradient( + 45deg, + #fff 0, + #fff 1px, + @bad 0, + @bad 50% + ); +} + +.newNodeMarker { + opacity: 0.8; + background-size: 10px 10px; + background-image: repeating-linear-gradient( + 45deg, + #fff 0, + #fff 1px, + @good 0, + @good 50% + ); +} + +// Selected marker feature +.selectedMarker, +.defaultMarker:hover { + border: 2px solid black; +} diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx new file mode 100644 index 000000000..666090429 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx @@ -0,0 +1,107 @@ +import { Trans } from "@lingui/macro"; + +import { Button } from "components/buttons/button"; +import { Collapsible } from "components/collapsible"; +import { useToast } from "components/toast/toastProvider"; + +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; +import { OptionContainer } from "plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm"; +import { + useAddNewSectionModal, + useDeletePropModal, + useEditPropModal, +} from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; +import { IMeshWideSection } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const ConfigSection = ({ dropdown }: { dropdown: IMeshWideSection }) => { + return ( + } + > + {Object.entries(dropdown.options).map(([key, value]) => ( + + ))} + + ); +}; + +export const SectionEditOrDelete = ({ name }) => { + const { toggleModal: toggleDeleteModal, actionModal: deletePropModal } = + useDeletePropModal(); + const { toggleModal: toggleEditModal, actionModal: editPropertyModal } = + useEditPropModal(); + + const { showToast } = useToast(); + + return ( + { + e.stopPropagation(); + editPropertyModal(name, () => { + console.log("edit stuff"); + toggleEditModal(); + showToast({ + text: ( + + Edited {name} - {new Date().toDateString()} + + ), + duration: 5000, + onAction: () => { + console.log("Undo action"); + }, + }); + }); + }} + onDelete={(e) => { + e.stopPropagation(); + deletePropModal(name, () => { + console.log("delete stuff"); + toggleDeleteModal(); + showToast({ + text: ( + + Deleted {name} - {new Date().toDateString()} + + ), + duration: 5000, + onAction: () => { + console.log("Undo action"); + }, + }); + }); + }} + /> + ); +}; + +export const AddNewSectionBtn = () => { + const { toggleModal: toggleNewSectionModal, actionModal: addSectionModal } = + useAddNewSectionModal(); + + const { showToast } = useToast(); + return ( + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx new file mode 100644 index 000000000..8f90a14fd --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx @@ -0,0 +1,36 @@ +import { Trans } from "@lingui/macro"; + +import { useToast } from "components/toast/toastProvider"; + +import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; + +export const MeshStatus = () => { + const { showToast } = useToast(); + return ( + { + showToast({ + text: ( + <> + + Updating shared state{" "} + {new Date().toDateString()} + + + ), + duration: 5000, + }); + }} + > +
+ 10 of 12 node are ready to update +
+ + Last update: 30 second ago + +
+
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx new file mode 100644 index 000000000..af75fbcdb --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx @@ -0,0 +1,134 @@ +import { Trans } from "@lingui/macro"; +import { useState } from "preact/hooks"; +import { SubmitHandler, useForm } from "react-hook-form"; + +import { Button } from "components/buttons/button"; +import Divider from "components/divider"; +import InputField from "components/inputs/InputField"; +import { useToast } from "components/toast/toastProvider"; + +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; +import { + useDeletePropModal, + useEditPropModal, +} from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; + +const EditOptionForm = ({ + keyString, + value, + onSubmit, +}: { + keyString: string; + value: string; + onSubmit?: (data) => void; +}) => { + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + defaultValues: { key: keyString, value }, + }); + + const _onSubmit: SubmitHandler = (data) => { + onSubmit(data); + }; + + return ( +
+ Key} + register={register} + /> + Value} + register={register} + /> + + + ); +}; + +export const OptionContainer = ({ + keyString, + value, +}: { + keyString: string; + value: string; +}) => { + const [isEditing, setIsEditing] = useState(false); + + const toggleIsEditing = () => setIsEditing(!isEditing); + + const { toggleModal: toggleDeleteModal, actionModal: deletePropModal } = + useDeletePropModal(); + const { toggleModal: toggleEditModal, actionModal: editPropertyModal } = + useEditPropModal(); + const { showToast } = useToast(); + + return ( +
+
+ +
+
+ {!isEditing ? ( + <> +
+
{keyString}
+ { + e.stopPropagation(); + deletePropModal(keyString, () => { + console.log("delete stuff"); + toggleDeleteModal(); + showToast({ + text: ( + + Deleted {keyString} + + ), + duration: 5000, + onAction: () => { + console.log("Undo action"); + }, + }); + }); + }} + /> +
+
{value}
+ + ) : ( + { + editPropertyModal(keyString, () => { + console.log("edited stuff"); + toggleEditModal(); + toggleIsEditing(); + showToast({ + text: Edited {keyString}, + duration: 5000, + }); + }); + }} + /> + )} +
+
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx new file mode 100644 index 000000000..e0f2f40bb --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx @@ -0,0 +1,109 @@ +import { Trans } from "@lingui/macro"; +import { ComponentChildren } from "preact"; +import { useCallback } from "preact/compat"; +import { useForm } from "react-hook-form"; + +import { ModalActions, useModal } from "components/Modal/Modal"; +import InputField from "components/inputs/InputField"; + +import { DataTypes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +const useActionModal = ( + title: ComponentChildren, + btnText: ComponentChildren, + actionName: ModalActions +) => { + const { toggleModal, setModalState } = useModal(); + + const actionModal = useCallback( + (prop: string, actionCb: () => void) => { + setModalState({ + content: ( +
+ + Are you sure you want to {title} the{" "} + {prop} property? + +
+ ), + title, + [`${actionName}Cb`]: actionCb, + [`${actionName}BtnText`]: btnText, + }); + toggleModal(); + }, + [setModalState, toggleModal] + ); + return { actionModal, toggleModal }; +}; + +export const useDeletePropModal = () => + useActionModal( + Delete property, + Delete, + "delete" + ); + +export const useEditPropModal = () => + useActionModal( + Edit property, + Edit, + "success" + ); + +export const useAddNewSectionModal = () => { + const { toggleModal, setModalState } = useModal(); + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + defaultValues: { name: "" }, + }); + + const actionModal = useCallback( + (actionCb: (data) => void) => { + setModalState({ + content: ( +
+ Name} + register={register} + /> +
+ ), + title: Add new section, + successCb: handleSubmit(actionCb), + successBtnText: Add, + }); + toggleModal(); + }, + [setModalState, toggleModal] + ); + return { actionModal, toggleModal }; +}; + +export const useSetReferenceStateModal = () => { + const { toggleModal, setModalState, isModalOpen } = useModal(); + + const confirmModal = useCallback( + (dataType: DataTypes, cb: () => Promise) => { + setModalState({ + title: Set reference state for {dataType}, + content: ( + + Are you sure you want to set this reference state for{" "} + {dataType} + + ), + successCb: cb, + successBtnText: Continue, + }); + toggleModal(); + }, + [setModalState, toggleModal] + ); + return { confirmModal, toggleModal, isModalOpen }; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.spec.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.spec.tsx new file mode 100644 index 000000000..abba9ca14 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.spec.tsx @@ -0,0 +1,31 @@ +import "@testing-library/jest-dom"; +import "@testing-library/jest-dom/extend-expect"; +import { screen } from "@testing-library/preact"; + +import { MeshWideMap } from "plugins/lime-plugin-mesh-wide/src/containers/Map"; +import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; +import { nodesReferenceState } from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; + +import { render } from "utils/test_utils"; + +jest.mock("plugins/lime-plugin-mesh-wide/src/meshWideApi.ts"); +jest.mock("leaflet"); + +const mockedDoSharedStateApiCall = jest.mocked(doSharedStateApiCall); + +describe("Map component", () => { + it("should show nodes alert when a node has not configured properly the coordinates", async () => { + nodesReferenceState["primero"].coordinates = { + long: "FIXME", + lat: "FIXME", + }; + // mockedDoSharedStateApiCall.mockResolvedValue(nodesReferenceState); + mockedDoSharedStateApiCall.mockResolvedValue(nodesReferenceState); + render( + + ); + expect( + await screen.findByTestId("has-invalid-nodes") + ).toBeInTheDocument(); + }); +}); diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx new file mode 100644 index 000000000..d261ed688 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx @@ -0,0 +1,112 @@ +import { t } from "@lingui/macro"; +import L from "leaflet"; +import { useEffect, useRef } from "preact/hooks"; +import { + LayerGroup, + LayersControl, + MapContainer, + TileLayer, +} from "react-leaflet"; + +import { + useLoadLeaflet, + useLocation, +} from "plugins/lime-plugin-locate/src/locateQueries"; +import { FloatingAlert } from "plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert"; +import { + BatmanLinksLayer, + WifiLinksLayer, +} from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers"; +import NodesLayer from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer"; +import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; + +const openStreetMapTileString = "https://{s}.tile.osm.org/{z}/{x}/{y}.png"; +const openStreetMapAttribution = + '© OpenStreetMap contributors'; + +interface ILayersChecked { + nodes?: boolean; + wifiLinks?: boolean; + batmanLinks?: boolean; +} + +export const MeshWideMap = ({ + nodes = true, + wifiLinks = true, + batmanLinks = false, +}: ILayersChecked) => { + const { data: selectedMapFeature, setData: setSelectedMapFeature } = + useSelectedMapFeature(); + + const { isLoading: assetsLoading, data: leafletData } = useLoadLeaflet({ + refetchOnWindowFocus: false, + }); + + const { data: nodeLocation, isLoading: isLoadingLocation } = useLocation({ + enabled: !!leafletData, + }); + + const mapRef = useRef(); + const loading = assetsLoading || isLoadingLocation; + + useEffect(() => { + if (mapRef) { + mapRef.current.on("click", () => { + if (selectedMapFeature !== null) { + setSelectedMapFeature(null); + } + }); + } + }, [mapRef, selectedMapFeature, setSelectedMapFeature]); + + // Set map position when map is available or location gets updated + useEffect(() => { + const mapInstance = mapRef.current; + if ( + !loading && + mapInstance && + nodeLocation && + nodeLocation.location && + (nodeLocation.location.lat !== "FIXME" || + nodeLocation.location.lon !== "FIXME") + ) { + mapInstance.setView( + [+nodeLocation.location.lat, +nodeLocation.location.lon], + 13 + ); + } + }, [loading, nodeLocation]); + + return ( + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx b/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx new file mode 100644 index 000000000..35f426b4e --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx @@ -0,0 +1,83 @@ +import LinkLine from "plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine"; +import { useLocatedLinks } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; +import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { LocatedLinkData } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +interface ILinksLayerProps { + links: LocatedLinkData; + linksReference: LocatedLinkData; + newLinks: LocatedLinkData; + linksLoaded: boolean; +} + +const LinksLayer = ({ + links, + linksReference, + linksLoaded, + newLinks, +}: ILinksLayerProps) => { + return ( + <> + {linksLoaded && + Object.entries(linksReference).map((referenceLink, i) => { + let actualLink: PontToPointLink; + if (links) { + actualLink = Object.values(links).find( + (value) => value.id === referenceLink[0] + ); + } + return ( + + ); + })} + {newLinks && + Object.entries(newLinks).map(([k, v], i) => { + return ; + })} + + ); +}; + +export const WifiLinksLayer = () => { + const { + locatedNewLinks: newLinks, + locatedLinks, + locatedLinksReference, + linksLoaded, + } = useLocatedLinks({ type: "wifi_links_info" }); + + return ( +
+ +
+ ); +}; + +export const BatmanLinksLayer = () => { + const { + locatedNewLinks: newLinks, + locatedLinks, + locatedLinksReference, + linksLoaded, + } = useLocatedLinks({ type: "bat_links_info" }); + + return ( +
+ +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer.tsx b/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer.tsx new file mode 100644 index 000000000..5be48d8c3 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer.tsx @@ -0,0 +1,39 @@ +import NodeMarker from "plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker"; +import { useNodes } from "plugins/lime-plugin-mesh-wide/src/hooks/useNodes"; +import { INodeInfo } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +const NodesLayer = () => { + const { + locatedNodes: { + locatedNodesReference: referenceNodes, + locatedNodesActual: meshWideNodesActual, + locatedNewNodes, + }, + } = useNodes(); + + return ( + <> + {referenceNodes && + Object.entries(referenceNodes).map(([k, v], i) => { + let actualNode: INodeInfo; + if (meshWideNodesActual) { + actualNode = meshWideNodesActual[k]; + } + return ( + + ); + })} + {locatedNewNodes && + Object.entries(locatedNewNodes).map(([k, v], i) => { + return ; + })} + + ); +}; + +export default NodesLayer; diff --git a/plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.spec.tsx b/plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.spec.tsx new file mode 100644 index 000000000..adb0123c5 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.spec.tsx @@ -0,0 +1,117 @@ +import "@testing-library/jest-dom"; +import { screen } from "@testing-library/preact"; + +import { SelectedFeatureBottomSheet } from "plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet"; +import { + nodes, + nodesReferenceState, +} from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; +import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { + INodeInfo, + NodeMapFeature, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { render } from "utils/test_utils"; + +jest.mock("plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx"); +const mockedSelectedMapFeature = jest.mocked(useSelectedMapFeature); + +function pxToNumber(pxString: string): number { + const numericString = pxString.replace("px", ""); + return parseInt(numericString, 10); +} + +describe("Feature bottom sheet", () => { + // beforeEach(() => {}); + beforeAll(() => { + Object.defineProperty(window, "matchMedia", { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, // or true if you want it to match + media: query, + onchange: null, + addListener: jest.fn(), // deprecated in favor of `addEventListener` + removeListener: jest.fn(), // deprecated in favor of `removeEventListener` + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); + }); + + it("should not open BottomSheet when selectedMapFeature is null", () => { + // Mock the return value for the hook + mockedSelectedMapFeature.mockReturnValue({ + data: null, + setData: () => {}, + }); + + render(); + + expect( + pxToNumber(screen.queryByTestId("bottom-sheet-body").style.height) + ).toBeLessThan(0); + }); + + it("should open BottomSheet with invalid nodes feature", () => { + const invalid = "invalid_node"; + mockedSelectedMapFeature.mockReturnValue({ + data: { + type: "errorsDetails", + feature: { + invalidNodes: new Set([invalid]), + meshWideDataErrors: [], + dataNotSetErrors: [], + }, + id: "errorsDetails", + }, + setData: () => {}, + }); + + render(); + expect( + pxToNumber(screen.queryByTestId("bottom-sheet-body").style.height) + ).toBeGreaterThan(0); + expect(screen.getByText(invalid)).toBeInTheDocument(); + expect(screen.getByText("Invalid Nodes")).toBeInTheDocument(); + }); + + it("should open BottomSheet with node feature", () => { + const name = "LiMe-da4eaa"; + const actual: INodeInfo = nodes()[name]; + const reference: INodeInfo = nodesReferenceState[name]; + // Mock the return value for the hook + mockedSelectedMapFeature.mockReturnValue({ + data: { + type: "node", + feature: { actual, reference, name } as NodeMapFeature, + id: "node", + }, + setData: () => {}, + }); + + render(); + + expect(screen.getByText(name)).toBeInTheDocument(); + }); + + it.skip("should open BottomSheet with link feature", () => { + // todo: fix this test. The feature change with new objects. + // const name = "LiMe-da4eaa"; + // const actual = links("wifi_links_info")[name]; + // const reference = linksReferenceState[name]; + // mockedSelectedMapFeature.mockReturnValue({ + // data: { + // type: "link", + // feature: { PontToPointLink(actual), reference } as LinkMapFeature, + // id: "node", + // }, + // setData: () => {}, + // }); + // + // render(); + // + // expect(screen.getByText(name)).toBeInTheDocument(); + }); +}); diff --git a/plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.tsx b/plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.tsx new file mode 100644 index 000000000..b894bea23 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet.tsx @@ -0,0 +1,45 @@ +import { useEffect, useState } from "preact/hooks"; + +import { BottomSheet } from "components/bottom-sheet"; + +import { + FeatureDetail, + FeatureReferenceStatus, +} from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail"; +import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; + +export const SelectedFeatureBottomSheet = () => { + const [isOpen, setIsOpen] = useState(false); + + const { data: selectedMapFeature } = useSelectedMapFeature(); + + useEffect(() => { + if (selectedMapFeature == null) { + setIsOpen(false); + } else { + setIsOpen(true); + } + }, [selectedMapFeature]); + + return ( +
+ { + setIsOpen(false); + }} + initialDrawerDistanceTop={600} + footer={ + + } + > +
+ +
+
+
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx new file mode 100644 index 000000000..d0168821d --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx @@ -0,0 +1,189 @@ +import { UseQueryResult } from "@tanstack/react-query"; +import { createContext } from "preact"; +import { useMemo } from "preact/compat"; +import { useContext } from "preact/hooks"; + +import { useNodes } from "plugins/lime-plugin-mesh-wide/src/hooks/useNodes"; +import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { mergeLinksAndCoordinates } from "plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates"; +import { compareLinks } from "plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors"; +import { + useMeshWideBatman, + useMeshWideBatmanReference, + useMeshWideLinks, + useMeshWideLinksReference, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { + ILinkErrors, + ILinkPtoPErrors, + ILinks, + LinkType, + LocatedLinkData, + PointToPointLinkId, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { isEmpty } from "utils/utils"; + +interface getQueryByLinkTypeReturnType { + state: (params) => UseQueryResult>; + reference: (params) => UseQueryResult>; +} +/** + * Util function that returns the correct query based on the link type + * @param type + */ +export const getQueryByLinkType = ( + type: T +): getQueryByLinkTypeReturnType => { + if (type === "bat_links_info") { + return { + state: useMeshWideBatman, + reference: useMeshWideBatmanReference, + } as getQueryByLinkTypeReturnType; + } + return { + state: useMeshWideLinks, + reference: useMeshWideLinksReference, + } as getQueryByLinkTypeReturnType; +}; + +interface IUselocatedLinks { + locatedLinksReference: LocatedLinkData; + linksErrors: ILinkErrors | undefined; + locatedLinks: LocatedLinkData; + linksLoaded: boolean; + locatedNewLinks: LocatedLinkData; +} + +/** + * Util hook to get located links and compare them with the reference links + * @param type + */ +const useCalculateLocatedLinks = ({ + type, +}: { + type: LinkType; +}): IUselocatedLinks => { + const { state: fetchData, reference: fetchDataReference } = + getQueryByLinkType(type); + + const { data: linksReference } = fetchDataReference({}); + const { data: links } = fetchData({}); + const { + locatedNodes: { allLocatedNodes: meshWideNodes }, + } = useNodes(); + + const locatedLinksReference: LocatedLinkData = useMemo(() => { + if (meshWideNodes && linksReference) { + return mergeLinksAndCoordinates( + meshWideNodes, + linksReference, + type + ); + } + }, [meshWideNodes, linksReference, type]); + + const locatedLinks: LocatedLinkData = useMemo(() => { + if (links && meshWideNodes) { + return mergeLinksAndCoordinates(meshWideNodes, links, type); + } + }, [links, meshWideNodes, type]); + + const linksLoaded = !!locatedLinksReference && !!locatedLinks; + + const linksErrors: ILinkErrors = useMemo(() => { + // If there are no links reference just drop no errors (because there are no links to compare with) + if (locatedLinksReference && !isEmpty(locatedLinksReference)) { + const errors: ILinkErrors = {}; + Object.entries(locatedLinksReference).forEach( + ([k, referenceLink]) => { + let actualLink: PontToPointLink; + if (locatedLinks) { + actualLink = Object.values(locatedLinks).find( + (value) => value.id === referenceLink.id + ); + } + errors[referenceLink.id] = compareLinks({ + referenceLink, + actualLink, + }); + } + ); + return errors; + } + }, [locatedLinksReference, locatedLinks]); + + // This links are valid and not exists on the reference state + let locatedNewLinks: LocatedLinkData = {}; + if (locatedLinks) { + locatedNewLinks = Object.keys(locatedLinks).reduce((obj, key) => { + if (!locatedLinksReference || !locatedLinksReference[key]) { + obj[key] = locatedLinks[key]; + } + return obj; + }, {} as LocatedLinkData); + } + + return { + locatedLinks, + locatedLinksReference, + linksLoaded, + linksErrors, + locatedNewLinks, + } as IUselocatedLinks; +}; + +export const usePointToPointErrors = ({ + id, + type, +}: { + id: PointToPointLinkId; + type: LinkType; +}): { errors: ILinkPtoPErrors | undefined } => { + const { linksErrors } = useLocatedLinks({ type }); + return { errors: linksErrors && linksErrors[id] }; +}; + +// Define separate contexts for each type of link +const BatmanLinksContext = createContext(null); +const MeshWideLinksContext = createContext(null); + +// Export a hook that return the proper context based on the type of link +export const useLocatedLinks = ({ type }: { type: LinkType }) => { + let requestedContext = MeshWideLinksContext; + if (type === "bat_links_info") { + requestedContext = BatmanLinksContext; + } + + const context = useContext(requestedContext); + if (context === null) { + throw new Error( + `useLocatedLinks must be used within a provider for ${requestedContext} links` + ); + } + return context; +}; + +export const BatmanLinksProvider = ({ children }) => { + const batmanLinksData = useCalculateLocatedLinks({ + type: "bat_links_info", + }); + + return ( + + {children} + + ); +}; + +export const MeshWideLinksProvider = ({ children }) => { + const meshWideLinksData = useCalculateLocatedLinks({ + type: "wifi_links_info", + }); + + return ( + + {children} + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx new file mode 100644 index 000000000..da9e137ae --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx @@ -0,0 +1,83 @@ +import { QueryKey } from "@tanstack/react-query"; + +import { + useMeshWideBatman, + useMeshWideBatmanReference, + useMeshWideLinks, + useMeshWideLinksReference, + useMeshWideNodes, + useMeshWideNodesReference, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; +import { MeshWideDataError } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { isEmpty } from "utils/utils"; + +/** + * Hook used to show to the interface if any of shared state module has an error. + * + * The errors can happen when the module is not on the device. I tried a different approach on + * https://github.com/selankon/lime-app/blob/ee610c1af81df393de81121887cd56588497317e/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx#L12-L33 + * But I like this more for performance reasons. The other approach used a timer and I think is not the best. + * + * On this way, it just listens query cache and updated when anything falls. + * + * Is there a better way to do this? + */ +export const useMeshWideDataErrors = () => { + const meshWideDataErrors: MeshWideDataError[] = []; + const dataNotSetErrors: MeshWideDataError[] = []; + + const addError = (queryKey: QueryKey, error?: unknown, data?: object) => { + if (data && isEmpty(data)) { + dataNotSetErrors.push({ queryKey, error }); + } + if (error) { + meshWideDataErrors.push({ queryKey, error }); + } + }; + + const { data: linksReferenceData, error: linksReferenceError } = + useMeshWideLinksReference({}); + addError( + getFromSharedStateKeys.getFromSharedStateMultiWriter("wifi_links_info"), + linksReferenceError, + linksReferenceData + ); + + const { error: linksError } = useMeshWideLinks({}); + addError( + getFromSharedStateKeys.getFromSharedStateAsync("wifi_links_info"), + linksError + ); + + const { data: batmanReferenceData, error: batmanReferenceError } = + useMeshWideBatmanReference({}); + addError( + getFromSharedStateKeys.getFromSharedStateMultiWriter("bat_links_info"), + batmanReferenceError, + batmanReferenceData + ); + + const { error: batmanError } = useMeshWideBatman({}); + addError( + getFromSharedStateKeys.getFromSharedStateAsync("bat_links_info"), + batmanError + ); + + const { data: nodesReferenceData, error: nodesReferenceError } = + useMeshWideNodesReference({}); + addError( + getFromSharedStateKeys.getFromSharedStateMultiWriter("node_info"), + nodesReferenceError, + nodesReferenceData + ); + + const { error: nodesError } = useMeshWideNodes({}); + addError( + getFromSharedStateKeys.getFromSharedStateAsync("node_info"), + nodesError + ); + + return { meshWideDataErrors, dataNotSetErrors }; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useNodes.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useNodes.tsx new file mode 100644 index 000000000..d1f0f8d4f --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useNodes.tsx @@ -0,0 +1,143 @@ +import { ComponentChildren, createContext } from "preact"; +import { useMemo } from "preact/compat"; +import { useContext } from "preact/hooks"; + +import { isValidCoordinate } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; +import { + useMeshWideNodes, + useMeshWideNodesReference, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { INodes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +interface NodesContextType { + hasInvalidNodes: boolean; + allNodes: { + meshWideNodesReference: INodes; + meshWideNodesActual: INodes; + }; + invalidNodes: { + invalidNodesReference: INodes; + invalidNodesActual: INodes; + }; + locatedNodes: { + locatedNodesReference: INodes; + locatedNodesActual: INodes; + allLocatedNodes: INodes; + locatedNewNodes: INodes; + }; +} + +const NodesContext = createContext(null); + +export const NodesProvider = ({ + children, +}: { + children: ComponentChildren; +}) => { + const { data: meshWideNodesReference } = useMeshWideNodesReference({}); + const { data: meshWideNodesActual } = useMeshWideNodes({}); + + const splitNodesByValidity = ( + nodeList: INodes + ): { validNodes: INodes; invalidNodes: INodes } => { + const validNodes: INodes = {}; + const invalidNodes: INodes = {}; + + Object.entries(nodeList).forEach(([key, nodeInfo]) => { + try { + if ( + isValidCoordinate( + nodeInfo.coordinates.lat, + nodeInfo.coordinates.long + ) + ) { + validNodes[key] = nodeInfo; + } else { + invalidNodes[key] = nodeInfo; + } + } catch (e) { + invalidNodes[key] = nodeInfo; + } + }); + + return { validNodes, invalidNodes }; + }; + + const { + validNodes: locatedNodesReference, + invalidNodes: invalidNodesReference, + }: { validNodes: INodes; invalidNodes: INodes } | undefined = + useMemo(() => { + if (meshWideNodesReference) + return splitNodesByValidity(meshWideNodesReference); + return { validNodes: undefined, invalidNodes: undefined }; + }, [meshWideNodesReference]); + + const { + validNodes: locatedNodesActual, + invalidNodes: invalidNodesActual, + }: { validNodes: INodes; invalidNodes: INodes } | undefined = + useMemo(() => { + if (meshWideNodesActual) + return splitNodesByValidity(meshWideNodesActual); + return { validNodes: undefined, invalidNodes: undefined }; + }, [meshWideNodesActual]); + + const hasInvalidNodes = + (invalidNodesReference && + Object.keys(invalidNodesReference).length > 0) || + (invalidNodesActual && Object.keys(invalidNodesActual).length > 0); + + // This nodes are valid and not exists on the reference state + let locatedNewNodes: INodes = {}; + if (locatedNodesActual) { + locatedNewNodes = Object.keys(locatedNodesActual).reduce((obj, key) => { + if (!meshWideNodesReference || !meshWideNodesReference[key]) { + obj[key] = locatedNodesActual[key]; + } + return obj; + }, {} as INodes); + } + + // Used to have on an a single list all the located nodes + // This is used to have an easier way to draw links between nodes + // that are not active, or not on reference or new + const allLocatedNodes = { + ...locatedNodesReference, + ...locatedNodesActual, + ...locatedNewNodes, + }; + + return ( + + {children} + + ); +}; + +export const useNodes = () => { + const context = useContext(NodesContext); + if (context === null) { + throw new Error("useNodesContext must be used within a NodesProvider"); + } + return context; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors.tsx new file mode 100644 index 000000000..6b9b8df6b --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors.tsx @@ -0,0 +1,20 @@ +import { processNodeErrors } from "plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors"; +import { + INodeInfo, + NodeErrorCodes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const useSingleNodeErrors = ({ + actual, + reference, +}: { + actual: INodeInfo; + reference: INodeInfo; +}) => { + const isNewNode = !reference; + const errors = processNodeErrors(reference, actual); + const isDown = errors.includes(NodeErrorCodes.NODE_DOWN); + const hasErrors = errors.length > 0; + + return { errors, hasErrors, isDown, isNewNode }; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx b/plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx new file mode 100644 index 000000000..0c606d9a2 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx @@ -0,0 +1,3 @@ +const SuccessIcon = () => ; + +export default SuccessIcon; diff --git a/plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx b/plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx new file mode 100644 index 000000000..1417d3775 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx @@ -0,0 +1,11 @@ +const ErrorIcon = () => ( + + ! + +); + +export default ErrorIcon; diff --git a/plugins/lime-plugin-mesh-wide/src/icons/power.tsx b/plugins/lime-plugin-mesh-wide/src/icons/power.tsx new file mode 100644 index 000000000..72d70e36d --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/icons/power.tsx @@ -0,0 +1,15 @@ +export const PowerIcon = () => ( + + + +); diff --git a/plugins/lime-plugin-mesh-wide/src/icons/warningIcon.tsx b/plugins/lime-plugin-mesh-wide/src/icons/warningIcon.tsx new file mode 100644 index 000000000..db17d5232 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/icons/warningIcon.tsx @@ -0,0 +1,16 @@ +export const WarningIcon = () => { + return ( + + + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts new file mode 100644 index 000000000..508e79728 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts @@ -0,0 +1,134 @@ +import { + BaseMacToMacLink, + Coordinates, + ILocatedLink, + LinkDataTypes, + LinkType, + MacToMacLinkId, + PointToPointLinkId, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +/** + * This class should store a group of links between the same geo coordinates. + * + * Could store two links between same geo but with different macs + */ +export class PontToPointLink { + private _links: BaseMacToMacLink[] = []; + public readonly id: PointToPointLinkId; + public readonly coordinates: Coordinates[] = []; + + constructor(coord1: Coordinates, coord2: Coordinates) { + this.id = PontToPointLink.generateId(coord1, coord2); + this.coordinates.push(coord1, coord2); + } + + addLink(link: typeof this._links[number]) { + this.links.push(link); + } + + /** + * For a given two macs check if any of the links on the _links array contain a node with this macs. (which should + * mean that the link is already added on the array). + * @param mac1 + * @param mac2 + */ + linkExists(mac1: string, mac2: string) { + for (const link of this._links) { + // Just needed to check the first node of the link object becouse the other will have the same macs but reversed + const node = link.data[Object.keys(link.data)[0]]; + if ( + node && + (node.dst_mac.toLowerCase() === mac1.toLowerCase() || + node.src_mac.toLowerCase() === mac1.toLowerCase()) && + (node.dst_mac.toLowerCase() === mac2.toLowerCase() || + node.src_mac.toLowerCase() === mac2.toLowerCase()) + ) { + return true; + } + } + return false; + } + + get names(): string[] { + return [ + ...this._links.reduce((acc, link) => { + Object.keys(link).forEach((key) => acc.add(key)); + return acc; + }, new Set()), + ] as string[]; + } + + get links() { + return this._links; + } + + /** + * Generate a deterministic unique id based on the coordinates of a node. + * @param coord1 + * @param coord2 + */ + static generateId(coord1: Coordinates, coord2: Coordinates): string { + const _prepareCoord = (coord: string) => + parseFloat(coord.replace("-", "").replace(".", "")); + + const allCoordinates = [ + _prepareCoord(coord1.long), + _prepareCoord(coord1.lat), + _prepareCoord(coord2.long), + _prepareCoord(coord2.lat), + ]; + + return allCoordinates.sort((a, b) => a - b).toString(); + } + + get type(): LinkType { + return this._links[0].type; + } +} + +/** + * Store link info between two macs + */ +export class MacToMacLink { + private _data: ILocatedLink; + private _id: MacToMacLinkId; + public type: T; + + constructor(data: ILocatedLink, type: T) { + this._data = data; + this._id = MacToMacLink.generateId(data); + this.type = type; + } + + /** + * Deterministically generation of a unique id using the macs of this link. Concatenate the sorted macs that + * are involved on this link + * @param data + */ + static generateId(data: ILocatedLink): MacToMacLinkId { + return [ + ...Object.entries(data).map(([k, v]) => { + return v.src_mac?.toLowerCase().replace(/:/g, ""); + }), + ] + .sort() + .join(""); + } + + get id() { + return this._id; + } + + get data() { + return this._data; + } + + get names(): string[] { + return [...Object.keys(this._data)]; + } + + linkByName(name: string): LinkDataTypes[T] { + return this._data[name]; + } +} diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.spec.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.spec.ts new file mode 100644 index 000000000..fad847d38 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.spec.ts @@ -0,0 +1,33 @@ +import "@testing-library/jest-dom/extend-expect"; + +import { mergeLinksAndCoordinates } from "plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates"; +import { + linksReferenceState, + nodesReferenceState, +} from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; + +describe("tests for the algorithm that merge point and links data types", () => { + beforeEach(() => {}); + + it("assert that merged nodes have the correct coordinates", async () => { + const locatedLinksReference = mergeLinksAndCoordinates( + nodesReferenceState, + linksReferenceState, + "wifi_links_info" + ); + // Iterate between merged link objects + Object.entries(locatedLinksReference).map(([k, merged], i) => { + expect(merged.coordinates.length).toBe(2); // Merged objects haw to be exactly two geo points + for (const link of merged.links) { + Object.entries(link.data).map(([name, linkData], i) => { + const node = nodesReferenceState[name]; + expect(linkData.coordinates).toBe(node.coordinates); + }); + } + }); + }); + + // Implement this tests + it.skip("no duplicated links", async () => {}); + it.skip("check that a link between two points can have different links with different macs", async () => {}); +}); diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts new file mode 100644 index 000000000..57f76ec89 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts @@ -0,0 +1,99 @@ +import { + MacToMacLink, + PontToPointLink, +} from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { + ILinks, + ILocatedLink, + INodes, + LinkDataTypes, + LinkType, + LocatedLinkData, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { isEmpty } from "utils/utils"; + +export const mergeLinksAndCoordinates = ( + nodes: INodes, + links: ILinks, + type: T +): LocatedLinkData => { + if (!nodes || isEmpty(nodes) || !links || isEmpty(links)) return {}; + + const result: LocatedLinkData = {}; + + // for every node check all links + for (const linkNodeName in links) { + if (isEmpty(links[linkNodeName])) continue; + for (const linkData of Object.values(links[linkNodeName])) { + if (!linkData.dst_mac) continue; + // Get the nodeName of the destination node + const dstNodeName = Object.keys(nodes).find((pid) => { + return nodes[pid].macs.find( + (mac) => + mac.toLowerCase() === linkData.dst_mac.toLowerCase() + ); + }); + + // Is possible that the destination node is not on the list of links, + // just ignore it + if (!dstNodeName) continue; + + if ( + dstNodeName && + dstNodeName !== linkNodeName && + nodes[linkNodeName] // If is the link for a non geolocated node + ) { + // Generate a unique id of the point to point link based on the coordinates + const linkKey = PontToPointLink.generateId( + nodes[linkNodeName].coordinates, + nodes[dstNodeName!].coordinates + ); + + // If this point to point link no exists, instantiate it + if (!result[linkKey]) { + result[linkKey] = new PontToPointLink( + nodes[linkNodeName].coordinates, + nodes[dstNodeName!].coordinates + ); + } + // Else if the link is not already added don't do it. + else if ( + result[linkKey].linkExists( + linkData.src_mac, + linkData.dst_mac + ) || + !links[dstNodeName] + ) { + continue; + } + + // Get the destination link info + const destPointData = ( + links[dstNodeName] as Array + ).find( + (data: LinkDataTypes[T]) => + data.dst_mac.toLowerCase() === + linkData.src_mac.toLowerCase() && + data.src_mac.toLowerCase() === + linkData.dst_mac.toLowerCase() + ); + + const entry = { + [linkNodeName]: { + ...linkData, + coordinates: nodes[linkNodeName].coordinates, + }, + [dstNodeName]: { + ...destPointData, + coordinates: nodes[dstNodeName].coordinates, + }, + } as ILocatedLink; + + result[linkKey].addLink(new MacToMacLink(entry, type)); + } + } + } + + return result; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts new file mode 100644 index 000000000..655f8e6e1 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts @@ -0,0 +1,129 @@ +import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { + BatmanLinkErrorCodes, + IBatManLinkData, + ILinkPtoPErrors, + IWifiLinkData, + WifiLinkErrorCodes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { DEFAULT_COMMUNITY_SETTINGS } from "utils/constants"; + +/** + * It compares two links and return an array of error codes. + * @param reference + * @param actual + */ +const compareWifiData = (reference: IWifiLinkData, actual: IWifiLinkData) => { + // todo(kon): use community settings and not limeapp defaults + // const { data: communitySettings } = useCommunitySettings(); + + const errors: WifiLinkErrorCodes[] = []; + if ( + actual === undefined || + actual.signal === undefined || + actual.signal === 0 + ) { + return [WifiLinkErrorCodes.LINK_DOWN]; + } + + if ( + reference.signal - actual.signal > + DEFAULT_COMMUNITY_SETTINGS.mw_link_signal_threshold + ) { + errors.push(WifiLinkErrorCodes.SIGNAL_LOSS); + } + if ( + Math.abs(actual.chains[0] - actual.chains[1]) > + DEFAULT_COMMUNITY_SETTINGS.mw_link_chain_threshold + ) { + errors.push(WifiLinkErrorCodes.CHAIN_LOSS); + } + return errors; +}; + +const compareBatmanData = ( + reference: IBatManLinkData, + actual: IBatManLinkData +) => { + const errors: BatmanLinkErrorCodes[] = []; + if (actual === undefined) { + return [BatmanLinkErrorCodes.LINK_DOWN]; + } + return errors; +}; + +/** + * Function that receive 2 PontToPointLink and iterate over every mac to mac link and its data executing a function + * to compare the wifi data. + * @param referenceLink + * @param actualLink + */ +export const compareLinks = ({ + referenceLink, + actualLink, +}: { + referenceLink: PontToPointLink; + actualLink: PontToPointLink | undefined; +}) => { + if (!referenceLink) return; + + const ptoPErrors: ILinkPtoPErrors = { + macToMacErrors: {}, + hasErrors: false, + linkUp: true, + }; + + referenceLink.links.forEach((macToMacReference) => { + const setLinkIsDown = () => { + ptoPErrors.linkUp = false; + }; + + const macToMacActual = actualLink?.links.find( + (actual) => actual.id === macToMacReference.id + ); + + const isUp = !!actualLink; + if (!isUp) setLinkIsDown(); + + ptoPErrors.macToMacErrors[macToMacReference.id] = { + hasErrors: false, + linkErrors: {}, + linkUp: isUp, + }; + Object.entries(macToMacReference.data).forEach( + ([nodeNameReference, wifiDataReference]) => { + const wifiDataActual = macToMacActual?.data[nodeNameReference]; + const errors = + referenceLink.type === "wifi_links_info" + ? compareWifiData( + wifiDataReference as IWifiLinkData, + wifiDataActual as IWifiLinkData + ) + : compareBatmanData( + wifiDataReference as IBatManLinkData, + wifiDataActual as IBatManLinkData + ); + ptoPErrors.macToMacErrors[macToMacReference.id].linkErrors[ + nodeNameReference + ] = errors; + if (errors.length) { + ptoPErrors.macToMacErrors[macToMacReference.id].hasErrors = + true; + ptoPErrors.hasErrors = true; + } + if ( + (errors as WifiLinkErrorCodes[]).includes( + WifiLinkErrorCodes.LINK_DOWN + ) || + (errors as BatmanLinkErrorCodes[]).includes( + BatmanLinkErrorCodes.LINK_DOWN + ) + ) { + setLinkIsDown(); + } + } + ); + }); + return ptoPErrors; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts b/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts new file mode 100644 index 000000000..8c562143f --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts @@ -0,0 +1,32 @@ +import { + INodeInfo, + NodeErrorCodes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const processNodeErrors = ( + reference: INodeInfo, + actual: INodeInfo | undefined +) => { + const errors: NodeErrorCodes[] = []; + + // If not reference is a new node + if (!reference) return errors; + + if (!actual) return [NodeErrorCodes.NODE_DOWN]; + + // Check mac list are equal + if (reference.macs.length !== actual.macs.length) { + errors.push(NodeErrorCodes.MACS_MISSMATCH); + } + const sortedRefMacs = reference.macs.slice().sort(); + const sortedActualMacs = actual.macs.slice().sort(); + + for (let i = 0; i < sortedRefMacs.length; i++) { + if (sortedRefMacs[i] !== sortedActualMacs[i]) { + errors.push(NodeErrorCodes.MACS_MISSMATCH); + break; + } + } + + return errors; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/utils.ts b/plugins/lime-plugin-mesh-wide/src/lib/utils.ts new file mode 100644 index 000000000..3d01384ab --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/lib/utils.ts @@ -0,0 +1,34 @@ +export const readableBytes = (bytes: number) => { + const sizes = ["B", "KB", "MB", "GB", "TB"]; + + if (bytes === 0) return "0 Byte"; + const i = parseInt( + Math.floor(Math.log(bytes) / Math.log(1024)).toString(), + 10 + ); + if (i === 0) return `${bytes} ${sizes[i]}`; + + return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`; +}; + +/** + * Get the strings that appear on the first array but not on the second one + * @param array1 + * @param array2 + */ +export const getArrayDifference = (array1: string[], array2: string[]) => { + return array1.filter((item) => !array2.includes(item)); +}; + +export const isValidCoordinate = ( + lat: number | string, + lng: number | string +) => { + return ( + (!isNaN(Number(lat)) || !isNaN(Number(lng))) && + lat >= -90 && + lat <= 90 && + lng >= -180 && + lng <= 180 + ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts b/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts new file mode 100644 index 000000000..c8470df9e --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts @@ -0,0 +1,21 @@ +import { QueryKey } from "@tanstack/react-query"; + +import { + DataTypeMap, + DataTypes, + SharedStateReturnType, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import api from "utils/uhttpd.service"; + +export const doSharedStateApiCall = async ( + queryKey: QueryKey +) => { + const res = (await api.call(...queryKey)) as SharedStateReturnType< + DataTypeMap[T] + >; + if (res.error !== 0 && res.error !== 404) { + throw Error(`Shared state error: ${res.error}`); + } + return res.data; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx new file mode 100755 index 000000000..f001ff841 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx @@ -0,0 +1,12 @@ +import { Trans } from "@lingui/macro"; + +import { MapIcon } from "components/icons/teenny/map"; + +export const MeshWideMenu = () => ( + + + + Mesh Map + + +); diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx new file mode 100644 index 000000000..00bb979b2 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx @@ -0,0 +1,1150 @@ +import { + IBatManLinkData, + IBatmanLinks, + ILinks, + IMeshWideConfig, + INodes, + IWifiLinkData, + IWifiLinks, + LinkType, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const nodesReferenceState: INodes = { + "LiMe-462895": { + bleachTTL: 12, + author: "LiMe-462895", + coordinates: { + long: "-64.42703", + lat: "-31.80874", + }, + macs: ["a0:f3:c1:46:28:96", "a0:f3:c1:46:28:97", "a0:f3:c1:46:11:97"], + ipv4: "192.168.1.1", + ipv6: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + firmware_version: "1.0.0", + uptime: 1010.03, + device: "Router", + board: "", + hostname: "", + }, + "LiMe-da4eaa": { + bleachTTL: 12, + author: "LiMe-da4eaa", + coordinates: { + long: "-64.42315", + lat: "-31.79461", + }, + macs: [ + "14:cc:20:da:4e:ab", + "14:cc:20:da:4e:ac", + // Following macs are related to batman links + "02:ab:46:fc:3a:bd", + "02:58:47:fc:3a:bd", + ], + ipv4: "192.168.1.2", + ipv6: "2001:0db8:85a3:0000:0000:8a2e:0370:7335", + firmware_version: "1.0.1", + uptime: 37.89, + device: "Switch", + board: "", + hostname: "", + }, + primero: { + bleachTTL: 12, + author: "primero", + coordinates: { + long: "-64.41609", + lat: "-31.80461", + }, + macs: [ + "a8:40:41:1d:f9:35", + "a8:40:41:1d:f9:35", + // Following macs are related to batman links + "02:db:d6:46:28:95", + "02:ab:46:46:28:95", + "02:58:47:46:28:95", + ], + ipv4: "192.168.1.3", + ipv6: "2001:0db8:85a3:0000:0000:8a2e:0370:7336", + firmware_version: "1.0.2", + uptime: 37.89, + device: "Hub", + board: "", + hostname: "", + }, + segundo: { + bleachTTL: 12, + author: "segundo", + coordinates: { + long: "-64.43209", + lat: "-31.79461", + }, + macs: [ + "a8:40:41:1d:f9:ff", + "a8:40:41:1d:f9:aa", + // Following macs are related to batman links + "02:db:d6:da:4e:aa", + "02:58:47:da:4e:aa", + "02:ab:46:da:4e:aa", + ], + ipv4: "192.168.1.3", + ipv6: "2001:0db8:85a3:0000:0000:8a2e:0370:7336", + firmware_version: "1.0.2", + uptime: 37.89, + device: "Hub", + board: "", + hostname: "", + }, +}; + +export const linksReferenceState: IWifiLinks = { + primero: [ + { + tx_rate: 150000, + dst_mac: "A0:F3:C1:46:28:97", + chains: [-63, -59], + signal: -58, + rx_rate: 180000, + src_mac: "a8:40:41:1d:f9:35", + }, + { + tx_rate: 162000, + dst_mac: "14:CC:20:DA:4E:AC", + chains: [-57, -51], + signal: -50, + rx_rate: 240000, + src_mac: "a8:40:41:1d:f9:35", + }, + ], + segundo: [ + { + tx_rate: 150000, + dst_mac: "A0:F3:C1:46:11:97", + chains: [-58, -59], + signal: -58, + rx_rate: 180000, + src_mac: "a8:40:41:1d:f9:ff", + }, + { + tx_rate: 162000, + dst_mac: "14:CC:20:DA:4E:AC", + chains: [-52, -51], + signal: -50, + rx_rate: 240000, + src_mac: "a8:40:41:1d:f9:aa", + }, + ] as IWifiLinkData[], + "LiMe-da4eaa": [ + { + tx_rate: 65000, + dst_mac: "A0:F3:C1:46:28:96", + chains: [-25, -25], + src_mac: "14:cc:20:da:4e:ab", + rx_rate: 65000, + signal: -25, + }, + { + tx_rate: 270000, + dst_mac: "A0:F3:C1:46:28:97", + chains: [-50, -47], + src_mac: "14:cc:20:da:4e:ac", + rx_rate: 150000, + signal: -45, + }, + { + tx_rate: 243000, + dst_mac: "A8:40:41:1D:F9:35", + chains: [-75, -64], + src_mac: "14:cc:20:da:4e:ac", + rx_rate: 162000, + signal: -64, + }, + { + tx_rate: 243000, + dst_mac: "A8:40:41:1D:F9:aa", + chains: [-75, -64], + src_mac: "14:cc:20:da:4e:ac", + rx_rate: 162000, + signal: -64, + }, + ] as IWifiLinkData[], + "LiMe-462895": [ + { + tx_rate: 78000, + dst_mac: "14:CC:20:DA:4E:AB", + chains: [-43, -46], + src_mac: "a0:f3:c1:46:28:96", + rx_rate: 78000, + signal: 2, + }, + { + tx_rate: 243000, + dst_mac: "14:CC:20:DA:4E:AC", + chains: [-68, -41], + src_mac: "a0:f3:c1:46:28:97", + rx_rate: 216000, + signal: -41, + }, + { + tx_rate: 240000, + dst_mac: "A8:40:41:1D:F9:35", + chains: [-77, -65], + src_mac: "a0:f3:c1:46:28:97", + rx_rate: 135000, + signal: -65, + }, + { + tx_rate: 240000, + dst_mac: "A8:40:41:1D:F9:ff", + chains: [-64, -65], + src_mac: "a0:f3:c1:46:11:97", + rx_rate: 135000, + signal: -65, + }, + ] as IWifiLinkData[], +}; + +export const batManReferenceState: IBatmanLinks = { + primero: [ + { + hard_ifindex: 18, + last_seen_msecs: 1300, + iface: "eth0-1_250", + dst_mac: "02:db:d6:da:4e:aa", + src_mac: "02:db:d6:46:28:95", + }, + { + hard_ifindex: 26, + last_seen_msecs: 20, + iface: "wlan1-mesh_250", + dst_mac: "02:ab:46:da:4e:aa", + src_mac: "02:ab:46:46:28:95", + }, + { + hard_ifindex: 26, + last_seen_msecs: 40, + iface: "wlan1-mesh_250", + dst_mac: "02:ab:46:fc:3a:bd", + src_mac: "02:ab:46:46:28:95", + }, + { + hard_ifindex: 28, + last_seen_msecs: 1710, + iface: "wlan0-mesh_250", + dst_mac: "02:58:47:fc:3a:bd", + src_mac: "02:58:47:46:28:95", + }, + { + hard_ifindex: 28, + last_seen_msecs: 1450, + iface: "wlan0-mesh_250", + dst_mac: "02:58:47:da:4e:aa", + src_mac: "02:58:47:46:28:95", + }, + ] as IBatManLinkData[], + "LiMe-da4eaa": [ + { + hard_ifindex: 26, + last_seen_msecs: 1670, + iface: "wlan1-mesh_250", + dst_mac: "02:ab:46:da:4e:aa", + src_mac: "02:ab:46:fc:3a:bd", + }, + { + hard_ifindex: 26, + last_seen_msecs: 1350, + iface: "wlan1-mesh_250", + dst_mac: "02:ab:46:46:28:95", + src_mac: "02:ab:46:fc:3a:bd", + }, + { + hard_ifindex: 28, + last_seen_msecs: 1430, + iface: "wlan0-mesh_250", + dst_mac: "02:58:47:46:28:95", + src_mac: "02:58:47:fc:3a:bd", + }, + { + hard_ifindex: 28, + last_seen_msecs: 1030, + iface: "wlan0-mesh_250", + dst_mac: "02:58:47:da:4e:aa", + src_mac: "02:58:47:fc:3a:bd", + }, + ], + segundo: [ + { + hard_ifindex: 18, + last_seen_msecs: 1670, + src_mac: "02:db:d6:da:4e:aa", + dst_mac: "02:db:d6:46:28:95", + iface: "eth0-1_250", + }, + { + hard_ifindex: 26, + last_seen_msecs: 550, + src_mac: "02:58:47:da:4e:aa", + dst_mac: "02:58:47:46:28:95", + iface: "wlan0-mesh_250", + }, + { + hard_ifindex: 26, + last_seen_msecs: 260, + src_mac: "02:58:47:da:4e:aa", + dst_mac: "02:58:47:fc:3a:bd", + iface: "wlan0-mesh_250", + }, + { + hard_ifindex: 28, + last_seen_msecs: 340, + src_mac: "02:ab:46:da:4e:aa", + dst_mac: "02:ab:46:fc:3a:bd", + iface: "wlan1-mesh_250", + }, + { + hard_ifindex: 28, + last_seen_msecs: 550, + src_mac: "02:ab:46:da:4e:aa", + dst_mac: "02:ab:46:46:28:95", + iface: "wlan1-mesh_250", + }, + ] as IBatManLinkData[], +}; + +// Use the same as on the reference state deleting a specific node +// const nodeName = "LiMe-462895"; +const nodeName = "primero"; + +// Used to delete a mac from a node. To see what happend if the returning list is different +// This will delete a mac from the node macs list +const macToDelete = ""; +// const macToDelete = "a0:f3:c1:46:11:97"; +// delete a link where the src_mac is +// const linkToDelete = macToDelete; +const linkToDelete = "a0:f3:c1:46:11:97"; +// const linkToDelete = ""; + +export const links = (type: T): ILinks => { + const data = + type === "wifi_links_info" ? linksReferenceState : batManReferenceState; + + // Create a deep copy of the state to avoid mutating the original object + const newState: ILinks = JSON.parse(JSON.stringify(data)); + + let source_macs_to_remove = []; + if (nodeName) { + // Get source_macs from the node to be removed + source_macs_to_remove = newState[nodeName].map((item: any) => + item.src_mac.toLowerCase() + ); + + // Remove the specified node + delete newState[nodeName]; + } + + // Remove data items with matching dest_mac in other objects + Object.keys(newState).forEach((key: string) => { + newState[key] = newState[key].filter((item) => { + return ( + !source_macs_to_remove.includes(item.dst_mac.toLowerCase()) || + // Added to delete a specific link of a node and not an entire node + item.src_mac.toLowerCase() === linkToDelete.toLowerCase() || + item.dst_mac.toLowerCase() === linkToDelete.toLowerCase() + ); + }); + }); + + return newState; +}; + +export const nodes = (): INodes => { + const newState = JSON.parse(JSON.stringify(nodesReferenceState)) as INodes; + + // This only delete a particular mac from the list of macs + for (const [k, v] of Object.entries(newState)) { + v.macs = v.macs.filter((mac) => mac !== macToDelete); + } + + // This delete an entire node + delete newState[nodeName]; + + return newState; +}; + +export const getMeshWideConfig = async () => meshWideConfig; +// +const options = { + primary_interface: "eth0", + main_ipv4_address: "10.170.128.0/16/17", +}; + +const meshWideConfig: IMeshWideConfig = [ + { + name: "lime system", + options, + }, + { + name: "lime network", + options, + }, + { + name: "lime wifi", + options, + }, + { + name: "generic_uci_config prometheus", + options, + }, + { + name: "run_asset prometheus_enable", + options, + }, +]; +// export const getRadioData = async () => radioDataResponse_simplified; + +// +// export const radioDataResponse_simplified: IMeshWideStatusResponse = { +// result: { +// "ql-czuk-bbone": { +// bleachTTL: 28, +// data: { +// hostname: "ql-czuk-bbone", +// coordinates: { +// lon: "-64.41515", +// lat: "-31.80130", +// }, +// macs: [ +// "a8:40:41:1d:f8:5c", +// "a8:40:41:1d:2a:a0", +// "02:cc:4e:1d:2a:a2", +// "aa:40:41:1d:f8:5c", +// "a8:40:41:1c:86:73", +// "aa:40:41:1c:86:73", +// "02:ab:46:1d:2a:a2", +// ], +// links: ["a8:40:41:1c:83:dd", "a8:40:41:1d:fa:29"], +// }, +// author: "ql-czuk-bbone", +// }, +// "ql-graciela-bbone": { +// bleachTTL: 28, +// data: { +// hostname: "ql-graciela-bbone", +// coordinates: { +// lon: "-64.42703", +// lat: "-31.80874", +// }, +// macs: [ +// "02:cc:4e:1c:85:aa", +// "a8:40:41:1c:83:f8", +// "02:ab:46:1c:85:aa", +// "ae:40:41:1c:85:a8", +// "a8:40:41:1c:83:dd", +// "a8:40:41:1c:85:a8", +// "aa:40:41:1c:85:a8", +// "02:58:47:1c:85:aa", +// ], +// links: ["a8:40:41:1c:86:73", "a8:40:41:1d:f9:f2"], +// }, +// author: "ql-graciela-bbone", +// }, +// "ql-berta": { +// bleachTTL: 28, +// data: { +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: [ +// "a8:40:41:1d:fa:29", +// "aa:40:41:1f:71:60", +// "a8:40:41:1f:71:60", +// "a8:40:41:1d:f9:f2", +// "02:cc:4e:1f:71:62", +// "02:ab:46:1f:71:62", +// ], +// links: ["a8:40:41:1c:83:f8", "a8:40:41:1d:f8:5c"], +// hostname: "ql-berta", +// }, +// author: "ql-berta", +// }, +// }, +// }; +// +// export const radioDataResponse: IMeshWideStatusResponse = { +// result: { +// "si-radio": { +// bleachTTL: 23, +// data: { +// hostname: "si-radio", +// coordinates: { +// lon: "-64.39240", +// lat: "-31.82056", +// }, +// macs: [ +// "aa:40:41:1c:85:50", +// "02:cc:4e:1c:85:52", +// "a8:40:41:1c:84:1a", +// "a8:40:41:1c:85:50", +// "02:58:47:1c:85:52", +// "ae:40:41:1c:85:50", +// "02:ab:46:1c:85:52", +// "a8:40:41:1c:84:16", +// ], +// links: [ +// "64:66:b3:87:4e:d1", +// "14:cc:20:ad:b0:d9", +// "a8:40:41:1c:83:eb", +// ], +// }, +// author: "si-radio", +// }, +// "ql-berta": { +// bleachTTL: 28, +// data: { +// links: ["a8:40:41:1c:83:f8"], +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: [ +// "a8:40:41:1d:fa:29", +// "aa:40:41:1f:71:60", +// "a8:40:41:1f:71:60", +// "a8:40:41:1d:f9:f2", +// "02:cc:4e:1f:71:62", +// "02:ab:46:1f:71:62", +// ], +// hostname: "ql-berta", +// }, +// author: "ql-berta", +// }, +// "ql-esteban": { +// bleachTTL: 25, +// data: { +// links: ["", ""], +// coordinates: { +// lon: "-64.41600680351257", +// lat: "-31.801688993108318", +// }, +// macs: [ +// "a0:f3:c1:48:cf:ec", +// "a0:f3:c1:48:cf:ed", +// "a2:f3:c1:48:cf:ec", +// "a2:f3:c1:48:cf:ed", +// ], +// hostname: "ql-esteban", +// }, +// author: "ql-esteban", +// }, +// "rl-hogardecristo": { +// bleachTTL: 22, +// data: { +// hostname: "rl-hogardecristo", +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: ["02:58:47:c2:e2:1a", "28:87:ba:c2:e2:1a"], +// links: ["a8:40:41:1c:85:a4"], +// }, +// author: "rl-hogardecristo", +// }, +// "ql-czuk-bbone": { +// bleachTTL: 28, +// data: { +// hostname: "ql-czuk-bbone", +// coordinates: { +// lon: "-64.41515", +// lat: "-31.80130", +// }, +// macs: [ +// "a8:40:41:1d:f8:5c", +// "a8:40:41:1d:2a:a0", +// "02:cc:4e:1d:2a:a2", +// "aa:40:41:1d:f8:5c", +// "a8:40:41:1c:86:73", +// "aa:40:41:1c:86:73", +// "02:ab:46:1d:2a:a2", +// ], +// links: ["a8:40:41:1c:84:20", "a8:40:41:1c:83:dd"], +// }, +// author: "ql-czuk-bbone", +// }, +// "ql-czuk": { +// bleachTTL: 25, +// data: { +// links: [ +// "14:cc:20:ad:b0:83", +// "64:66:b3:87:4b:39", +// "a2:f3:c1:48:cf:ed", +// ], +// coordinates: { +// lon: "-64.41506", +// lat: "-31.80137", +// }, +// macs: [ +// "a8:40:41:1f:71:f0", +// "02:58:47:1f:71:f2", +// "a8:40:41:1c:86:7f", +// "a8:40:41:1c:86:96", +// "02:ab:46:1f:71:f2", +// "02:cc:4e:1f:71:f2", +// ], +// hostname: "ql-czuk", +// }, +// author: "ql-czuk", +// }, +// "ql-refu-bbone": { +// bleachTTL: 25, +// data: { +// links: [ +// "a8:40:41:1d:f8:5c", +// "9c:a2:f4:8c:b8:58", +// "a8:40:41:1c:85:a4", +// "9c:a2:f4:8c:b9:48", +// "a8:40:41:1d:27:b4", +// "a8:40:41:1d:f8:f9", +// ], +// coordinates: { +// lon: "-64.385177", +// lat: "-31.837354", +// }, +// macs: [ +// "02:cc:4e:1c:85:46", +// "a8:40:41:1c:85:44", +// "02:ab:46:1c:85:46", +// "a8:40:41:1c:84:20", +// "02:58:47:1c:85:46", +// "a8:40:41:1c:84:28", +// ], +// hostname: "ql-refu-bbone", +// }, +// author: "ql-refu-bbone", +// }, +// "rl-vacas": { +// bleachTTL: 25, +// data: { +// hostname: "rl-vacas", +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: ["9c:a2:f4:8c:b9:48", "02:58:47:8c:b9:48"], +// links: [ +// "a8:40:41:1c:85:44", +// "a8:40:41:1c:85:a4", +// "a8:40:41:1d:27:b4", +// ], +// }, +// author: "rl-vacas", +// }, +// "mc-escuela-larrea": { +// bleachTTL: 23, +// data: { +// links: [ +// "a8:40:41:1c:85:5a", +// "a8:40:41:1c:84:99", +// "a8:40:41:1c:86:6d", +// "a8:40:41:1d:f9:26", +// "a8:40:41:1c:85:5a", +// "a8:40:41:1c:84:99", +// ], +// coordinates: { +// lon: "-64.37752", +// lat: "-31.85442", +// }, +// macs: [ +// "a8:40:41:1c:86:6e", +// "aa:40:41:1c:86:6d", +// "a8:40:41:1c:86:6d", +// "aa:40:41:1d:2a:b0", +// "a8:40:41:1d:2a:b0", +// "02:cc:4e:1d:2a:b2", +// "02:ab:46:1d:2a:b2", +// ], +// hostname: "mc-escuela-larrea", +// }, +// author: "mc-escuela-larrea", +// }, +// "ql-graciela": { +// bleachTTL: 28, +// data: { +// hostname: "ql-graciela", +// coordinates: { +// lon: "-64.42705", +// lat: "-31.80873", +// }, +// macs: [ +// "02:58:47:1c:85:3e", +// "ae:40:41:1c:85:3c", +// "02:cc:4e:1c:85:3e", +// "02:ab:46:1c:85:3e", +// "a8:40:41:1c:84:18", +// "a8:40:41:1c:84:05", +// "aa:40:41:1c:85:3c", +// "a8:40:41:1c:85:3c", +// ], +// links: [ +// "a8:40:41:1c:86:1d", +// "a8:40:41:1d:2a:40", +// "a0:f3:c1:85:fb:42", +// "a8:40:41:1c:86:2d", +// ], +// }, +// author: "ql-graciela", +// }, +// "ql-quinteros": { +// bleachTTL: 27, +// data: { +// hostname: "ql-quinteros", +// coordinates: { +// lon: "-64.4300052523613", +// lat: "-31.805773853144796", +// }, +// macs: [ +// "aa:40:41:1d:2a:40", +// "02:cc:4e:1d:2a:42", +// "a8:40:41:1c:86:2d", +// "a8:40:41:1d:2a:40", +// "02:ab:46:1d:2a:42", +// "ae:40:41:1d:2a:40", +// "02:58:47:1d:2a:42", +// "a8:40:41:1c:86:1d", +// ], +// links: [ +// "a0:f3:c1:85:fb:43", +// "a8:40:41:1d:f9:2c", +// "a8:40:41:1c:84:05", +// "a8:40:41:1c:85:3c", +// "a0:f3:c1:85:fb:42", +// "a8:40:41:1d:f8:fb", +// "a8:40:41:1c:84:18", +// ], +// }, +// author: "ql-quinteros", +// }, +// "mc-lidia": { +// bleachTTL: 22, +// data: { +// links: [ +// "a8:40:41:1c:85:5a", +// "a8:40:41:1c:84:99", +// "a8:40:41:1c:86:6d", +// ], +// coordinates: { +// lon: "-64.37990", +// lat: "-31.85474", +// }, +// macs: [ +// "a8:40:41:1d:27:7c", +// "a8:40:41:1c:85:2e", +// "02:ab:46:1d:27:7e", +// "aa:40:41:1d:27:7c", +// ], +// hostname: "mc-lidia", +// }, +// author: "mc-lidia", +// }, +// "ql-ipem265": { +// bleachTTL: 13, +// data: { +// links: ["a8:40:41:1c:86:96"], +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: [ +// "a8:40:41:1c:85:98", +// "02:ab:46:1c:85:9a", +// "aa:40:41:1c:85:98", +// "a8:40:41:1c:84:0b", +// "02:58:47:1c:85:9a", +// "02:cc:4e:1c:85:9a", +// "a8:40:41:1c:84:2e", +// "ae:40:41:1c:85:98", +// ], +// hostname: "ql-ipem265", +// }, +// author: "ql-ipem265", +// }, +// "ql-irenecasa": { +// bleachTTL: 25, +// data: { +// hostname: "ql-irenecasa", +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: [ +// "66:70:02:4e:cc:e2", +// "02:ab:46:4e:cc:e1", +// "64:70:02:4e:cc:e2", +// "62:70:02:4e:cc:e2", +// "64:70:02:4e:cc:e3", +// "02:58:47:4e:cc:e1", +// ], +// links: ["64:66:b3:87:4b:38", "64:66:b3:87:4b:39"], +// }, +// author: "ql-irenecasa", +// }, +// "ql-flor": { +// bleachTTL: 25, +// data: { +// links: ["a8:40:41:1c:86:7f"], +// coordinates: { +// lon: "-64.41365", +// lat: "-31.79897", +// }, +// macs: [ +// "16:cc:20:ad:b0:82", +// "02:ab:46:ad:b0:81", +// "14:cc:20:ad:b0:83", +// "02:58:47:ad:b0:81", +// "14:cc:20:ad:b0:82", +// ], +// hostname: "ql-flor", +// }, +// author: "ql-flor", +// }, +// "si-andrea": { +// bleachTTL: 23, +// data: { +// links: ["a8:40:41:1c:85:50", "a8:40:41:1c:85:a4"], +// coordinates: { +// lon: "-64.40097", +// lat: "-31.81854", +// }, +// macs: [ +// "16:cc:20:ad:b0:d9", +// "14:cc:20:ad:b0:d9", +// "12:cc:20:ad:b0:d9", +// "02:ab:46:ad:b0:d8", +// "02:58:47:ad:b0:d8", +// "14:cc:20:ad:b0:da", +// ], +// hostname: "si-andrea", +// }, +// author: "si-andrea", +// }, +// "rl-tanque": { +// bleachTTL: 23, +// data: { +// links: [], +// coordinates: { +// lon: "-64.38414", +// lat: "-31.84013", +// }, +// macs: ["a8:40:41:1d:f9:05", "a8:40:41:1d:fa:26"], +// hostname: "rl-tanque", +// }, +// author: "rl-tanque", +// }, +// "mc-yohana": { +// bleachTTL: 23, +// data: { +// links: ["a8:40:41:1c:85:a4", "a8:40:41:1d:27:b4"], +// coordinates: { +// lon: "-64.37864", +// lat: "-31.83969", +// }, +// macs: ["9c:a2:f4:8c:b8:58", "02:58:47:8c:b8:58"], +// hostname: "mc-yohana", +// }, +// author: "mc-yohana", +// }, +// "mc-eli": { +// bleachTTL: 21, +// data: { +// links: ["a8:40:41:1d:29:68", "a8:40:41:1d:2a:1c"], +// coordinates: { +// lon: "-64.38097", +// lat: "-31.85566", +// }, +// macs: ["9c:a2:f4:8c:b6:f4", "02:58:47:8c:b6:f4"], +// hostname: "mc-eli", +// }, +// author: "mc-eli", +// }, +// "si-soniam": { +// bleachTTL: 23, +// data: { +// links: [ +// "a8:40:41:1c:85:50", +// "64:70:02:4e:cd:0b", +// "a8:40:41:1c:84:16", +// ], +// coordinates: { +// lon: "-64.39240", +// lat: "-31.82056", +// }, +// macs: [ +// "66:66:b3:87:4e:d0", +// "64:66:b3:87:4e:d0", +// "62:66:b3:87:4e:d0", +// "64:66:b3:87:4e:d1", +// "02:ab:46:87:4e:cf", +// "02:58:47:87:4e:cf", +// ], +// hostname: "si-soniam", +// }, +// author: "si-soniam", +// }, +// "mc-martinez": { +// bleachTTL: 22, +// data: { +// hostname: "mc-martinez", +// coordinates: { +// lon: "-64.37988", +// lat: "-31.85802", +// }, +// macs: [ +// "ae:40:41:1d:29:68", +// "02:ab:46:1d:29:6a", +// "02:58:47:1d:29:6a", +// "a8:40:41:1c:84:99", +// "02:cc:4e:1d:29:6a", +// "a8:40:41:1c:85:1f", +// "a8:40:41:1d:29:68", +// "aa:40:41:1d:29:68", +// ], +// links: [ +// "a8:40:41:1c:85:5a", +// "a8:40:41:1c:86:6d", +// "a8:40:41:1c:85:2e", +// "9c:a2:f4:8c:b6:f4", +// "a8:40:41:1d:2a:1c", +// "a8:40:41:1c:85:5c", +// ], +// }, +// author: "mc-martinez", +// }, +// "mc-capilla": { +// bleachTTL: 23, +// data: { +// links: [ +// "a8:40:41:1c:84:28", +// "a8:40:41:1c:86:6e", +// "a8:40:41:1c:86:6d", +// ], +// coordinates: { +// lon: "-64.37827", +// lat: "-31.85482", +// }, +// macs: [ +// "a8:40:41:1d:f9:26", +// "aa:40:41:1f:74:f4", +// "a8:40:41:1d:f8:f9", +// "02:cc:4e:1f:74:f6", +// "02:ab:46:1f:74:f6", +// "a8:40:41:1f:74:f4", +// ], +// hostname: "mc-capilla", +// }, +// author: "mc-capilla", +// }, +// "ql-refu-bbone-2": { +// bleachTTL: 22, +// data: { +// links: [ +// "a8:40:41:1c:84:1a", +// "9c:a2:f4:8c:b8:58", +// "a8:40:41:1d:27:b4", +// "28:87:ba:c2:e2:1a", +// ], +// coordinates: { +// lon: "-64.385177", +// lat: "-31.837354", +// }, +// macs: [ +// "02:cc:4e:1c:85:a6", +// "a8:40:41:1c:85:a4", +// "a8:40:41:1c:83:eb", +// "aa:40:41:1c:83:e3", +// "a8:40:41:1c:83:e3", +// "aa:40:41:1c:83:eb", +// "02:58:47:1c:85:a6", +// "02:ab:46:1c:85:a6", +// ], +// hostname: "ql-refu-bbone-2", +// }, +// author: "ql-refu-bbone-2", +// }, +// "mc-rocio": { +// bleachTTL: 22, +// data: { +// links: [ +// "a8:40:41:1c:85:1f", +// "a8:40:41:1d:29:68", +// "9c:a2:f4:8c:b6:f4", +// "a8:40:41:1c:84:99", +// "a8:40:41:1c:86:6d", +// "a8:40:41:1c:85:2e", +// ], +// coordinates: { +// lon: "-64.38025", +// lat: "-31.85570", +// }, +// macs: [ +// "a8:40:41:1c:85:5a", +// "02:cc:4e:1d:2a:1e", +// "aa:40:41:1c:85:5a", +// "a8:40:41:1c:85:5c", +// "aa:40:41:1c:85:5c", +// "02:ab:46:1d:2a:1e", +// "02:58:47:1d:2a:1e", +// "a8:40:41:1d:2a:1c", +// ], +// hostname: "mc-rocio", +// }, +// author: "mc-rocio", +// }, +// "lbl-mikigonza": { +// bleachTTL: 28, +// data: { +// hostname: "lbl-mikigonza", +// coordinates: { +// lon: "-64.425602", +// lat: "-31.734109", +// }, +// macs: [ +// "a0:f3:c1:86:1e:f2", +// "a0:f3:c1:86:1e:f3", +// "a2:f3:c1:86:1e:f2", +// ], +// links: [""], +// }, +// author: "lbl-mikigonza", +// }, +// "ql-graciela-bbone": { +// bleachTTL: 28, +// data: { +// hostname: "ql-graciela-bbone", +// coordinates: { +// lon: "-64.42703", +// lat: "-31.80874", +// }, +// macs: [ +// "02:cc:4e:1c:85:aa", +// "a8:40:41:1c:83:f8", +// "02:ab:46:1c:85:aa", +// "ae:40:41:1c:85:a8", +// "a8:40:41:1c:83:dd", +// "a8:40:41:1c:85:a8", +// "aa:40:41:1c:85:a8", +// "02:58:47:1c:85:aa", +// ], +// links: ["a8:40:41:1c:86:73", "a8:40:41:1d:f9:f2"], +// }, +// author: "ql-graciela-bbone", +// }, +// "rl-tanque-2": { +// bleachTTL: 23, +// data: { +// links: ["a8:40:41:1c:85:a4", "9c:a2:f4:8c:b8:58"], +// coordinates: { +// lon: "-64.41609", +// lat: "-31.80461", +// }, +// macs: [ +// "02:58:47:1d:27:b6", +// "a8:40:41:1c:85:50", +// "a8:40:41:1d:27:b4", +// "aa:40:41:1d:27:b4", +// "a8:40:41:1c:85:4f", +// ], +// hostname: "rl-tanque-2", +// }, +// author: "rl-tanque-2", +// }, +// "ql-cutieddo": { +// bleachTTL: 28, +// data: { +// links: ["a8:40:41:1c:86:2d", "a0:f3:c1:85:fb:43"], +// coordinates: { +// lon: "-64.43312", +// lat: "-31.80787", +// }, +// macs: [ +// "a8:40:41:1d:f9:2c", +// "a8:40:41:1f:75:c4", +// "aa:40:41:1f:75:c4", +// "a8:40:41:1d:f8:fb", +// "02:ab:46:1f:74:7a", +// "02:cc:4e:1f:74:7a", +// ], +// hostname: "ql-cutieddo", +// }, +// author: "ql-cutieddo", +// }, +// "si-claudio": { +// bleachTTL: 21, +// data: { +// hostname: "si-claudio", +// coordinates: { +// lon: "-64.39444", +// lat: "-31.82071", +// }, +// macs: [ +// "66:70:02:4e:cd:0a", +// "64:70:02:4e:cd:0b", +// "64:70:02:4e:cd:0a", +// "02:ab:46:4e:cd:09", +// ], +// links: ["64:66:b3:87:4e:d1", "a8:40:41:1c:84:16"], +// }, +// author: "si-claudio", +// }, +// "ql-irene": { +// bleachTTL: 25, +// data: { +// links: [ +// "a2:f3:c1:48:cf:ec", +// "64:70:02:4e:cc:e2", +// "64:70:02:4e:cc:e3", +// "a2:f3:c1:48:cf:ed", +// "a8:40:41:1c:86:96", +// ], +// coordinates: { +// lon: "-64.41682", +// lat: "-31.80584", +// }, +// macs: [ +// "02:ab:46:87:4b:37", +// "66:66:b3:87:4b:38", +// "02:58:47:87:4b:37", +// "64:66:b3:87:4b:38", +// "64:66:b3:87:4b:39", +// "62:66:b3:87:4b:38", +// ], +// hostname: "ql-irene", +// }, +// author: "ql-irene", +// }, +// "ql-guillermina": { +// bleachTTL: 27, +// data: { +// links: [ +// "a8:40:41:1c:85:3c", +// "a8:40:41:1d:2a:40", +// "a8:40:41:1f:71:f0", +// "a8:40:41:1c:86:2d", +// "a8:40:41:1d:f9:2c", +// ], +// coordinates: { +// lon: "-64.43312", +// lat: "-31.80740", +// }, +// macs: [ +// "a0:f3:c1:85:fb:43", +// "02:ab:46:85:fb:41", +// "02:58:47:85:fb:41", +// "a0:f3:c1:85:fb:42", +// "a6:f3:c1:85:fb:42", +// "a2:f3:c1:85:fb:42", +// ], +// hostname: "ql-guillermina", +// }, +// author: "ql-guillermina", +// }, +// }, +// }; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx new file mode 100644 index 000000000..45f0ab488 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx @@ -0,0 +1,65 @@ +import { Trans } from "@lingui/macro"; +import React from "react"; + +import Loading from "components/loading"; + +import { useLoadLeaflet } from "plugins/lime-plugin-locate/src/locateQueries"; +import { FloatingAlert } from "plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert"; +import { MeshWideMap } from "plugins/lime-plugin-mesh-wide/src/containers/Map"; +import { SelectedFeatureBottomSheet } from "plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet"; +import { + BatmanLinksProvider, + MeshWideLinksProvider, +} from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; +import { NodesProvider } from "plugins/lime-plugin-mesh-wide/src/hooks/useNodes"; + +const MeshWide = () => { + const { + isError: isAssetError, + isFetchedAfterMount: assetsLoaded, + isLoading: isLoadingAssets, + } = useLoadLeaflet({ + refetchOnWindowFocus: false, + }); + + const loading = isLoadingAssets; + + if (loading) { + return ( +
+ +
+ ); + } + + if (isAssetError) { + return ( +
+ Error loading leaflet +
+ ); + } + + return ( + <> + + + + {/* route("/meshwide/config")} />*/} + + ); +}; + +const MeshWidePage = () => { + return ( + + + + + + + + ); +}; + +export default MeshWidePage; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx new file mode 100644 index 000000000..62b6887d2 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -0,0 +1,179 @@ +import { useMutation, useQuery } from "@tanstack/react-query"; + +import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; +import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; +import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; +import { + DataTypes, + IBatmanLinks, + IMeshWideConfig, + INodes, + IWifiLinks, + SelectedMapFeature, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import { useSharedData } from "utils/useSharedData"; + +const refetchInterval = 5000; + +export function useMeshWideLinksReference(params) { + const dataType: DataTypes = "wifi_links_info"; + const queryKey = + getFromSharedStateKeys.getFromSharedStateMultiWriter(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +export function useMeshWideLinks(params) { + const dataType: DataTypes = "wifi_links_info"; + const queryKey = getFromSharedStateKeys.getFromSharedStateAsync(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +export function useMeshWideBatmanReference(params) { + const dataType: DataTypes = "bat_links_info"; + const queryKey = + getFromSharedStateKeys.getFromSharedStateMultiWriter(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +export function useMeshWideBatman(params) { + const dataType: DataTypes = "bat_links_info"; + const queryKey = getFromSharedStateKeys.getFromSharedStateAsync(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +export function useMeshWideNodesReference(params) { + const dataType: DataTypes = "node_info"; + const queryKey = + getFromSharedStateKeys.getFromSharedStateMultiWriter(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +export function useMeshWideNodes(params) { + const dataType: DataTypes = "node_info"; + const queryKey = getFromSharedStateKeys.getFromSharedStateAsync(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +/** + * Insert into shared state + * + * Don't use those mutations itself, use it implementing it on the useReferenceState hook in order + * to unify criterias and add a confirmation modal + */ + +export const useSetNodeInfoReferenceState = (params) => { + const type = "node_info"; + const { data } = useMeshWideNodes({}); + const queryKey = getFromSharedStateKeys.insertIntoSharedStateKey( + type, + data + ); + return useMutation( + queryKey, + () => doSharedStateApiCall(queryKey), + { + ...params, + } + ); +}; + +export const useSetWifiLinksInfoReferenceState = (params) => { + const type = "wifi_links_info"; + const { data } = useMeshWideLinks({}); + const queryKey = getFromSharedStateKeys.insertIntoSharedStateKey( + type, + data + ); + return useMutation( + queryKey, + () => doSharedStateApiCall(queryKey), + { + ...params, + } + ); +}; + +export const useSetBatmanLinksInfoReferenceState = (params) => { + const type = "bat_links_info"; + const { data } = useMeshWideBatman({}); + const queryKey = getFromSharedStateKeys.insertIntoSharedStateKey( + type, + data + ); + return useMutation( + queryKey, + () => doSharedStateApiCall(queryKey), + { + ...params, + } + ); +}; + +/** + * Set mesh wide config + */ + +export function useMeshWideConfig(params) { + return useQuery( + ["lime-meshwide", "get_mesh_config"], + getMeshWideConfig, + { + ...params, + } + ); +} + +/** + * This query is used to store the selected feature on the map. + * + * Used to store the state between components. + */ +export const useSelectedMapFeature = () => { + return useSharedData([ + "lime-meshwide", + "select_map_feature", + ]); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx new file mode 100644 index 000000000..237afe239 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx @@ -0,0 +1,30 @@ +import { + DataTypeMap, + DataTypes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +export const getFromSharedStateMultiWriterKey = [ + "shared-state", + "getFromSharedStateMultiWriter", +]; +export const getFromSharedStateAsyncKey = ["shared-state-async", "get"]; + +export const insertIntoSharedStateKey = [ + "shared-state", + "insertIntoSharedStateMultiWriter", +]; + +export const getFromSharedStateKeys = { + getFromSharedStateAsync: (dataType: DataTypes) => [ + ...getFromSharedStateAsyncKey, + { data_type: dataType }, + ], + getFromSharedStateMultiWriter: (dataType: DataTypes) => [ + ...getFromSharedStateMultiWriterKey, + { data_type: dataType }, + ], + insertIntoSharedStateKey: ( + dataType: T, + data: DataTypeMap[T] + ) => [...insertIntoSharedStateKey, { data_type: dataType, json: data }], +}; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx new file mode 100644 index 000000000..a73fcd179 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx @@ -0,0 +1,200 @@ +import { QueryKey } from "@tanstack/react-query"; + +import { + MacToMacLink, + PontToPointLink, +} from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; + +/** + * Describe a link with a coordinates + */ + +export type LinkDataTypes = { + wifi_links_info: IWifiLinkData; + bat_links_info: IBatManLinkData; +}; +export type LinkType = keyof LinkDataTypes; +export type ILocatedLink = { + [key: string]: LinkDataTypes[T] & { + coordinates: Coordinates; + }; +}; +export type BaseMacToMacLink = MacToMacLink; + +/** + * List of located links. + * + * Are grouped by id based on their coordinates + * + * The array of classes contains an indeterminated number of links that are from certain point to another. + */ +export type LocatedLinkData = { + [key: string]: PontToPointLink; +}; + +type MacPair = { + dst_mac: string; + src_mac: string; +}; + +/** + * Link info retrieved from the API with the wifi data + */ +export type IWifiLinkData = { + tx_rate: number; + chains: number[]; + signal: number; + rx_rate: number; +} & MacPair; + +/** + * Link info retrieved from the API with the batman data + */ +export type IBatManLinkData = { + hard_ifindex: number; + last_seen_msecs: number; + iface: string; +} & MacPair; + +/** + * List of Link info retrieved from the API + */ +export interface ILinks { + [key: string]: Array; +} + +export type IWifiLinks = ILinks<"wifi_links_info">; +export type IBatmanLinks = ILinks<"bat_links_info">; + +export type Coordinates = { + lat: string; + long: string; +}; + +export interface INodeInfo { + bleachTTL: number; + author: string; + coordinates?: Coordinates; // Coordinates may not be set + board: string; + device: string; + macs: string[]; + hostname: string; + ipv4: string; + ipv6: string; + firmware_version: string; + uptime: number; +} + +export type INodes = { [key: string]: INodeInfo }; + +export type LinkMapFeature = { + actual: PontToPointLink; + reference: PontToPointLink; +}; + +export type NodeMapFeature = { + actual: INodeInfo; + reference: INodeInfo; + name: string; +}; + +export type MeshWideDataError = { + queryKey: QueryKey; + error?: unknown; +}; + +export type InvalidNodes = Set; +export type ErrorsDetails = { + invalidNodes: Set; + meshWideDataErrors: MeshWideDataError[]; + dataNotSetErrors: MeshWideDataError[]; +}; + +type FeatureMap = { + node: NodeMapFeature; + link: LinkMapFeature; + errorsDetails: ErrorsDetails; +}; + +type FeatureType = keyof FeatureMap; + +export type SelectedMapFeature = { + [T in FeatureType]: { + feature: FeatureMap[T]; + type: T; + id: number | string; + }; +}[FeatureType]; + +export interface IMeshWideSection { + name: string; + options: { [key: string]: string }; +} + +export type IMeshWideConfig = IMeshWideSection[]; + +export enum WifiLinkErrorCodes { + LINK_DOWN = "LINK_DOWN", + SIGNAL_LOSS = "SIGNAL_LOSS", + CHAIN_LOSS = "CHAIN_LOSS", +} + +export enum BatmanLinkErrorCodes { + LINK_DOWN = "LINK_DOWN", +} + +export enum NodeErrorCodes { + NODE_DOWN = "NODE_DOWN", + MACS_MISSMATCH = "MACS_MISSMATCH", +} + +/** + * Store the error for every wifi node data. Use the ids for the point to point and mac to mac as dictionary + */ +export type ILinkMtoMErrors = { + linkErrors: { + [nodeName: string]: WifiLinkErrorCodes[] | BatmanLinkErrorCodes[]; + }; + hasErrors: boolean; + linkUp: boolean; +}; + +export type ILinkPtoPErrors = { + macToMacErrors: { + [macToMacKey: MacToMacLinkId]: ILinkMtoMErrors; + }; + hasErrors: boolean; + linkUp: boolean; +}; + +export type ILinkErrors = { + [pointToPointKey: MacToMacLinkId]: ILinkPtoPErrors; +}; + +/** + * Type to store the link detail id, created deterministically by the + * two macs of this link + */ +export type MacToMacLinkId = string; + +/** + * Type to store a point to point link detail id, created deterministically by the + * two geo points of this link + */ +export type PointToPointLinkId = string; + +/** + * Query keys types + */ + +export type DataTypeMap = { + node_info: INodes; + wifi_links_info: IWifiLinks; + bat_links_info: IBatmanLinks; +}; +export type DataTypes = keyof DataTypeMap; +export type SharedStateTypes = DataTypeMap[keyof DataTypeMap]; +export type SharedStateReturnType = { + data: T; + error: number; +}; diff --git a/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx b/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx new file mode 100644 index 000000000..f9348b4d5 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx @@ -0,0 +1,44 @@ +import { Trans } from "@lingui/macro"; + +import { FullScreenModal } from "components/Modal/FullScreenModal"; +import Divider from "components/divider"; + +import { + AddNewSectionBtn, + ConfigSection, +} from "plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection"; +import { MeshStatus } from "plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus"; +import { useMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; + +const MeshWideConfigPage = () => { + const { data: meshWideConfig, isLoading } = useMeshWideConfig({}); + + return ( + <> + Mesh wide config} + isLoading={isLoading} + > + {meshWideConfig && ( + <> +
+ {meshWideConfig.map((dropdown, index) => ( + + ))} + +
+
+ + +
+ + )} +
+ + ); +}; + +export default MeshWideConfigPage; diff --git a/plugins/lime-plugin-node-admin/src/components/config/config.js b/plugins/lime-plugin-node-admin/src/components/config/config.js deleted file mode 100644 index f72bbd5d8..000000000 --- a/plugins/lime-plugin-node-admin/src/components/config/config.js +++ /dev/null @@ -1,33 +0,0 @@ -import { ListItem } from "components/list"; -import Loading from "components/loading"; - -import style from "./config.style.less"; - -export const Config = ({ - title, - subtitle, - value, - onClick, - isLoading, - ...props -}) => { - return ( - -
-
-
{title}
- {isLoading && } - {!isLoading && ( -
-
{subtitle}
-
{value}
-
- )} -
-
-
-
-
-
- ); -}; diff --git a/plugins/lime-plugin-node-admin/src/components/config/config.tsx b/plugins/lime-plugin-node-admin/src/components/config/config.tsx new file mode 100644 index 000000000..f3c4792e8 --- /dev/null +++ b/plugins/lime-plugin-node-admin/src/components/config/config.tsx @@ -0,0 +1,48 @@ +import { ComponentChildren } from "preact"; + +import { ListItem } from "components/list"; +import Loading from "components/loading"; + +import style from "./config.style.less"; + +type ConfigProps = { + title: ComponentChildren; + subtitle?: ComponentChildren; + value: ComponentChildren; + onClick: () => void; + isLoading: boolean; +}; + +export const Config = ({ + title, + subtitle, + value, + onClick, + isLoading, + ...props +}: ConfigProps) => { + return ( + +
+
+
{title}
+ {isLoading && } + {!isLoading && ( +
+ {subtitle && ( +
+ {" "} + {subtitle}{" "} +
+ )} +
{value}
+
+ )} +
+
+
+
+
+
+ ); +}; diff --git a/src/components/Modal/FullScreenModal.tsx b/src/components/Modal/FullScreenModal.tsx new file mode 100644 index 000000000..7dec9c634 --- /dev/null +++ b/src/components/Modal/FullScreenModal.tsx @@ -0,0 +1,43 @@ +import { ComponentChildren } from "preact"; +import { route } from "preact-router"; + +import Loading from "components/loading"; + +/** + * Used to show a new view with a close button that return to the backUrl param. Is placed over + * the navbar creating a modal like effect. + */ +export const FullScreenModal = ({ + title, + children, + isLoading, + backUrl = "/meshwide", +}: { + title: ComponentChildren; + children: ComponentChildren; + isLoading?: boolean; + backUrl?: string; +}) => { + return ( +
+
+
route(backUrl)} + > + X +
+
{title}
+
+ {isLoading ? ( +
+ +
+ ) : ( +
+ {children} +
+ )} +
+ ); +}; diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx new file mode 100644 index 000000000..f2a5f54af --- /dev/null +++ b/src/components/Modal/Modal.tsx @@ -0,0 +1,204 @@ +import { Trans } from "@lingui/macro"; +import { ComponentChildren, createContext } from "preact"; +import { useContext, useState } from "preact/hooks"; +import { useCallback } from "react"; + +import { Button } from "components/buttons/button"; +import Divider from "components/divider"; + +interface ModalContextProps { + isModalOpen: boolean; + toggleModal: () => void; + setModalState: (state?: ModalState) => void; + isLoading: boolean; +} + +type CallbackFn = () => void | Promise; + +interface ModalState { + content?: ComponentChildren; + title: ComponentChildren | string; + cancelBtn?: boolean; + successCb?: CallbackFn; + successBtnText?: ComponentChildren; + deleteCb?: CallbackFn; + deleteBtnText?: ComponentChildren; + isLoading?: boolean; +} + +const ModalContext = createContext({ + isModalOpen: false, + toggleModal: () => {}, + setModalState: () => {}, + isLoading: false, +}); + +export const useModal = () => { + const context = useContext(ModalContext); + if (context === undefined) { + throw new Error("useModal must be used within a UseModalProvider"); + } + return context; +}; + +export type ModalActions = "success" | "delete"; + +export const UseModalProvider = ({ children }) => { + const [isModalOpen, setModalOpen] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const [modalState, setModalState] = useState({ + content: <>, + title: "", + cancelBtn: false, + successCb: () => {}, + successBtnText: Success, + deleteCb: () => {}, + deleteBtnText: Cancel, + }); + + const toggleModal = useCallback(() => { + setModalOpen((prevIsModalOpen) => !prevIsModalOpen); + }, [isModalOpen]); + + const runCb = useCallback( + async (cb: CallbackFn) => { + if (isLoading) return; + setIsLoading(true); + await cb(); + setIsLoading(false); + }, + [isLoading] + ); + + const successCb = + modalState.successCb != null ? () => runCb(modalState.successCb) : null; + const deleteCb = + modalState.deleteCb != null ? () => runCb(modalState.deleteCb) : null; + + return ( + + {children} + + {modalState.content} + + + ); +}; + +const Modal = ({ + isModalOpen, + toggleModal, + children, + title, + cancelBtn = true, + successCb, + successBtnText = Success, + deleteCb, + deleteBtnText = Cancel, + isLoading, +}: { + isModalOpen: boolean; + toggleModal: () => void; + children?: ComponentChildren; +} & ModalState) => { + const stopPropagation = (e) => { + e.stopPropagation(); + }; + return ( + <> +
+
{ + if (!isLoading) toggleModal(); + }} + > + + + ); +}; + +export default Modal; diff --git a/src/components/app.tsx b/src/components/app.tsx index d14b9ac75..ddde55816 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -6,6 +6,9 @@ import Router from "preact-router"; import { useEffect } from "preact/hooks"; import { Provider } from "react-redux"; +import { UseModalProvider } from "components/Modal/Modal"; +import { ToastProvider } from "components/toast/toastProvider"; + import { Menu } from "containers/Menu"; import { RebootPage } from "containers/RebootPage"; import SubHeader from "containers/SubHeader"; @@ -85,7 +88,7 @@ const App = () => { }, [session, login]); if (!session?.username || !boardData) { - return "Loading..."; + return
"Loading..."
; } return ( @@ -106,13 +109,14 @@ const AppDefault = () => { }, []); return ( - {/*@ts-ignore*/} - {/* @ts-ignore */} - {/* @ts-ignore */} - + + + + + diff --git a/src/components/bottom-sheet/BottomSheet.tsx b/src/components/bottom-sheet/BottomSheet.tsx new file mode 100644 index 000000000..7b4a4fc2d --- /dev/null +++ b/src/components/bottom-sheet/BottomSheet.tsx @@ -0,0 +1,299 @@ +import { useCallback, useEffect, useRef, useState } from "preact/hooks"; +import { animated, useSpring } from "react-spring"; + +import style from "./style.less"; +import { + TBottomSheetEventsKey, + bottomSheetEvents, + syncHeight, + useReduceMotion, +} from "./utils"; + +const DRAWER_HEIGHT = window.innerHeight; +const INITIAL_DRAWER_DISTANCE_FROM_TOP = 400; +const MAX_WIDTH = 560; +const DRAWER_SNAP_MARGIN = 100; +const COLLAPSED_HEIGHT = 75; +const THUMB_HEIGHT = 35; + +// resize listener +window.addEventListener("resize", syncHeight); +syncHeight(); + +type TBottomSheetProps = { + /** + * nested children + */ + children: JSX.Element; + /** + * optional specific aria label for close button + */ + closeButtonAriaLabel?: string; + /** + * Activate close button + */ + closeButton?: boolean; + /** + * Custom initial expanded height + */ + initialDrawerDistanceTop?: number; + /** + * Is the BottomSheet visible on the scren? + */ + isOpen: boolean; + /** + * Optional custom maxWidth for the BottomSheet in px + */ + maxWidth?: string; + /** + * Fires when close button is fired + */ + onClose: () => void; + /** + * Fires when the status changes + */ + onStatusChange?: (status: string) => void; + /** + * Optional Subtitle for the BottomSheet + */ + subtitle?: string; + /** + * Optional Title for the BottomSheet + */ + title?: string; + /** + * Element to be shown either if the sheet is expanded at all or not + */ + footer?: JSX.Element; +}; + +export const BottomSheet: React.FC = ({ + children, + closeButtonAriaLabel = "Close", + closeButton = true, + initialDrawerDistanceTop = INITIAL_DRAWER_DISTANCE_FROM_TOP, + isOpen, + maxWidth = MAX_WIDTH, + onClose, + onStatusChange, + subtitle, + title, + footer, +}) => { + // STATE + const scrollRef = useRef(null); + const [bottom, setBottom] = useState(-DRAWER_HEIGHT); + const [draggingPosition, setDraggingPosition] = useState( + null + ); + const [debugLog, setDebugLog] = useState(""); + + // ANIMATION + const prefersReducedMotion = useReduceMotion(); + const styles = useSpring({ + bottom, + immediate: prefersReducedMotion, + config: { friction: 20 }, + }); + + // HANDLERS + const handlePointerDown = ( + // @ts-ignore + e: React.TouchEvent | React.MouseEvent + ) => { + // @ts-ignore + const event = (e?.touches != null ? e.touches[0] : e) as MouseEvent; + // handle safari body scroll bug + document.documentElement.classList.add("is-locked"); + const newDraggingPosition = + (e.currentTarget.parentElement?.getBoundingClientRect().bottom ?? + 0) - event.clientY; + setDraggingPosition(newDraggingPosition); + }; + + const handlePointerMove = useCallback( + (e: TouchEvent | MouseEvent) => { + // @ts-ignore + const event = e?.touches != null ? e?.touches[0] : e; + if (draggingPosition != null) { + const newBottom = + window.innerHeight - event.clientY - draggingPosition; + if (newBottom !== bottom) { + setBottom(newBottom); + } + } + }, + [bottom, draggingPosition] + ); + + const handleScrollRepositioning = () => { + if (scrollRef && scrollRef.current) { + scrollRef.current.scrollTop = 0; + } + }; + + const handleStatusChange = useCallback( + (status: TBottomSheetEventsKey) => { + const newStatus = bottomSheetEvents[status]; + const newDebugLog = + debugLog !== "" ? `${debugLog}, ${newStatus}` : newStatus; + setDebugLog(newDebugLog); + onStatusChange && onStatusChange(newStatus); + }, + [debugLog, onStatusChange] + ); + + // LISTENERS + + // toggling the bottom sheet + useEffect(() => { + if (isOpen) { + handleStatusChange("expanded"); + handleScrollRepositioning(); + setBottom(-initialDrawerDistanceTop); + } else { + handleStatusChange("dismissed"); + setBottom(-DRAWER_HEIGHT); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isOpen]); + + // dragging + useEffect(() => { + const handlePointerUp = () => { + document.documentElement.classList.remove("is-locked"); + + if (draggingPosition == null) { + return; + } + + // snap logic + if (bottom > -DRAWER_SNAP_MARGIN) { + handleStatusChange("snapToTop"); + setBottom(0); + } else if (bottom < -DRAWER_HEIGHT + COLLAPSED_HEIGHT) { + handleStatusChange("dismissed"); + onClose(); + setBottom(-DRAWER_HEIGHT); + } else if ( + bottom < + COLLAPSED_HEIGHT - DRAWER_HEIGHT + DRAWER_SNAP_MARGIN + ) { + handleStatusChange("collapsed"); + setBottom(-DRAWER_HEIGHT + COLLAPSED_HEIGHT); + } + setDraggingPosition(null); + }; + + document.addEventListener("touchend", handlePointerUp); + document.addEventListener("touchmove", handlePointerMove); + document.addEventListener("mouseup", handlePointerUp); + document.addEventListener("mousemove", handlePointerMove); + return () => { + document.removeEventListener("touchend", handlePointerUp); + document.removeEventListener("touchmove", handlePointerMove); + document.removeEventListener("mouseup", handlePointerUp); + document.removeEventListener("mousemove", handlePointerMove); + }; + }, [ + bottom, + debugLog, + draggingPosition, + handlePointerMove, + handleStatusChange, + onClose, + ]); + + const bodyHeight = + DRAWER_HEIGHT + + bottom - + (title || subtitle ? COLLAPSED_HEIGHT : THUMB_HEIGHT); + + return ( +
+ +
+
+
{ + e.preventDefault(); + // get rid of the ghost drag image in the view + e.dataTransfer.setDragImage(new Image(), 0, 0); + }} + draggable={true} + className={style.ThumbBarWrapper} + style={ + draggingPosition != null + ? { + cursor: "grabbing", + } + : { + cursor: "grab", + } + } + > +
+
+
+
+ {title && ( +

{title}

+ )} + {subtitle &&

{subtitle}

} +
+ {closeButton && ( + + )} +
+
+
+ {children} +
+
+ + {bodyHeight > 0 && ( +
+ {footer} +
+ )} +
+ ); +}; diff --git a/src/components/bottom-sheet/credits.md b/src/components/bottom-sheet/credits.md new file mode 100644 index 000000000..1e1ac0247 --- /dev/null +++ b/src/components/bottom-sheet/credits.md @@ -0,0 +1,3 @@ +Code borrowed from: + +https://github.com/kaitlynhova/BottomSheet/ diff --git a/src/components/bottom-sheet/index.ts b/src/components/bottom-sheet/index.ts new file mode 100644 index 000000000..4f7c1036f --- /dev/null +++ b/src/components/bottom-sheet/index.ts @@ -0,0 +1 @@ +export * from "./BottomSheet"; diff --git a/src/components/bottom-sheet/style.less b/src/components/bottom-sheet/style.less new file mode 100644 index 000000000..2d8842d4e --- /dev/null +++ b/src/components/bottom-sheet/style.less @@ -0,0 +1,92 @@ +@surface: #fff; +@onSurface: #191919; +@onSurfaceSecondary: #666; +@surfaceThumbBar: #ddd; +@surfaceHover: #eee; + +.BottomSheetStyled { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", + "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", + "Helvetica Neue", sans-serif; + background: @surface; + box-shadow: 0 1px 8px rgb(0 0 0 / 30%); + border-radius: 8px; + margin: auto; + max-width: 560px; + width: 100%; + height: 100%; +} + +.CloseButton { + height: 40px; + background: @surface; + cursor: pointer; + border: none; + padding: 8px; + border-radius: 100%; + position: absolute; + right: 16px; + &:hover { + background: @surfaceHover; + } +} + +.DebugLog { + color: @onSurface; +} + +.Header { + display: flex; + position: relative; + justify-content: center; + padding-bottom: 16px; +} + +.HeaderTitle { + display: flex; + flex-direction: column; + text-align: center; + justify-content: center; + & h1 { + color: @onSurface; + font-size: 1.125rem; + line-height: 1.5; + margin: 0; + } + & h2 { + color: @onSurfaceSecondary; + font-size: 0.875rem; + line-height: 1; + font-weight: 600; + margin: 0; + } +} + +.SheetBody { + overflow-y: hidden; + width: 100%; + transition: height 200ms; +} + +.ThumbBarWrapper { + width: 100%; + display: flex; + justify-content: center; + cursor: move; /* fallback if grab cursor is unsupported */ +} + +.ThumbBar { + background: @surfaceThumbBar; + width: 64px; + margin: 8px auto; + height: 0.25rem; + border-radius: 4px; +} + +.FooterWrapper { + position: fixed; + bottom: 0; + left: 50%; + width: 100%; + transform: translateX(-50%); +} diff --git a/src/components/bottom-sheet/utils.ts b/src/components/bottom-sheet/utils.ts new file mode 100644 index 000000000..12e7f0e32 --- /dev/null +++ b/src/components/bottom-sheet/utils.ts @@ -0,0 +1,44 @@ +import { useEffect, useState } from "preact/hooks"; + +export const syncHeight = () => { + document.documentElement.style.setProperty( + "--window-inner-height", + `${window.innerHeight}px` + ); +}; + +export type TBottomSheetEvents = { + collapsed: string; + dismissed: string; + expanded: string; + snapToTop: string; +}; + +export type TBottomSheetEventsKey = keyof TBottomSheetEvents; + +export const bottomSheetEvents: TBottomSheetEvents = { + collapsed: "in collapse state", + dismissed: "was dismissed", + expanded: "is expanded", + snapToTop: "snapped to top", +}; + +// from react-reduce-motion +// Note: library had type issues, didn't have time to fix those +export const useReduceMotion = () => { + const [matches, setMatch] = useState( + window.matchMedia("(prefers-reduced-motion: reduce)").matches + ); + useEffect(() => { + const mq = window.matchMedia("(prefers-reduced-motion: reduce)"); + const handleChange = () => { + setMatch(mq.matches); + }; + handleChange(); + mq.addEventListener("change", handleChange); + return () => { + mq.removeEventListener("change", handleChange); + }; + }, []); + return matches; +}; diff --git a/src/components/buttons/button.tsx b/src/components/buttons/button.tsx new file mode 100644 index 000000000..c57255d52 --- /dev/null +++ b/src/components/buttons/button.tsx @@ -0,0 +1,87 @@ +import React from "react"; + +export interface ButtonProps { + onClick?: (e) => void; + children?: any; // type error with Trans component + size?: "sm" | "md" | "lg"; + color?: "primary" | "secondary" | "danger" | "info" | "disabled"; + href?: string; + outline?: boolean; + disabled?: boolean; +} + +export const Button = ({ + size = "md", + color = "primary", + onClick, + children, + href, + disabled, + outline = false, + ...props +}: ButtonProps) => { + let sizeClasses = "", + colorClasses = ""; + switch (size) { + case "sm": + sizeClasses = "py-2 px-4 text-sm"; + break; + case "md": + sizeClasses = "py-4 px-6 min-w-[theme('spacing[52]')]"; + break; + case "lg": + sizeClasses = "py-6 px-8"; + break; + } + + color = disabled ? "disabled" : color; + + switch (color) { + case "secondary": + colorClasses = outline + ? "border-2 border-button-secondary text-button-secondary hover:bg-button-secondary hover:text-white" + : "bg-button-secondary text-white hover:bg-button-primary "; + break; + case "danger": + colorClasses = outline + ? "border-2 border-danger text-danger hover:bg-danger hover:text-white" + : "bg-danger text-white border-2 border-danger hover:text-danger hover:bg-white"; + break; + case "info": + colorClasses = outline + ? "border-2 border-button-info text-button-info hover:bg-button-info hover:text-white" + : "bg-button-info text-white border-2 border-button-info hover:text-button-info hover:bg-white"; + break; + case "disabled": + colorClasses = outline + ? "border-2 border-button-disabled text-button-disabled hover:bg-button-disabled hover:text-white" + : "bg-button-disabled text-white border-2 border-button-disabled hover:text-button-disabled hover:bg-white"; + break; + case "primary": + default: + colorClasses = outline + ? "border-2 border-button-primary text-button-primary hover:bg-button-primary hover:text-white" + : "bg-button-primary text-white hover:bg-button-secondary"; + break; + } + + const cls = `cursor-pointer font-semibold rounded-xl text-center place-content-center transition-all duration-300 + justify-center border-0 ${sizeClasses} ${colorClasses}`; + const Btn = () => ( +
(!disabled ? onClick(e) : null)} + className={cls} + {...props} + > + {children} +
+ ); + return href ? ( + + + + ) : ( + + ); +}; diff --git a/src/components/buttons/floatting-button.tsx b/src/components/buttons/floatting-button.tsx new file mode 100644 index 000000000..aac72bae0 --- /dev/null +++ b/src/components/buttons/floatting-button.tsx @@ -0,0 +1,24 @@ +import { ComponentChildren } from "preact"; +import React from "react"; + +import { Button, ButtonProps } from "components/buttons/button"; + +interface FloatingButtonProps { + children?: ComponentChildren | string; +} + +const FloatingButton = ({ + size = "sm", + children = "+", + ...rest +}: FloatingButtonProps & ButtonProps) => { + return ( +
+ +
+ ); +}; + +export default FloatingButton; diff --git a/src/components/collapsible/index.js b/src/components/collapsible/index.js index 617f8ccee..3713a9e16 100644 --- a/src/components/collapsible/index.js +++ b/src/components/collapsible/index.js @@ -1,20 +1,28 @@ import { useToggle } from "react-use"; -import style from "./style.less"; +import { ChevronDown, ChevronUp } from "components/icons/teenny/chevrons"; -export const Collapsible = ({ title, children, initCollapsed }) => { +export const Collapsible = ({ + title, + children, + initCollapsed, + optionsComponent = null, +}) => { const [collapsed, toggleCollapsed] = useToggle(initCollapsed); + return ( -
-
-
{title}
-
{collapsed ? "ᐯ" : "ᐱ"}
+
+
+
{title}
+
+ {optionsComponent} + {collapsed ? : } +
- {!collapsed &&
{children}
} + {!collapsed &&
{children}
}
); }; diff --git a/src/components/collapsible/style.less b/src/components/collapsible/style.less deleted file mode 100644 index cd5b92e9e..000000000 --- a/src/components/collapsible/style.less +++ /dev/null @@ -1,5 +0,0 @@ -.collapsible { - border: 1px solid #222; - padding: 1em; - border-radius: .5em; -} diff --git a/src/components/divider/index.tsx b/src/components/divider/index.tsx new file mode 100644 index 000000000..f7cf81b71 --- /dev/null +++ b/src/components/divider/index.tsx @@ -0,0 +1,10 @@ +type DividerColors = "gray" | "white"; +const Divider = ({ color = "gray" }: { color?: DividerColors }) => ( +
+); + +export default Divider; diff --git a/src/components/icons/SvgIcon.tsx b/src/components/icons/SvgIcon.tsx new file mode 100644 index 000000000..b699343d7 --- /dev/null +++ b/src/components/icons/SvgIcon.tsx @@ -0,0 +1,42 @@ +import { VNode } from "preact"; + +export interface IconProps { + width?: string; + height?: string; + className?: string; + dataTestId?: string; + fill?: string; + onClick?: (e) => void; +} + +interface SvgIconProps { + children?: VNode; + viewBox?: string; +} + +export const SvgIcon = ({ + children, + viewBox = "0 0 24 24", + className = "h-8 w-8", // 32px + dataTestId = "", + fill = "", + width, + height, + onClick, +}: SvgIconProps & IconProps) => { + return ( +
+ + {children} + +
+ ); +}; diff --git a/src/components/icons/bin.tsx b/src/components/icons/bin.tsx new file mode 100644 index 000000000..b26c2a9a8 --- /dev/null +++ b/src/components/icons/bin.tsx @@ -0,0 +1,17 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const BinIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/src/components/icons/edit.tsx b/src/components/icons/edit.tsx new file mode 100644 index 000000000..a5f6f90a4 --- /dev/null +++ b/src/components/icons/edit.tsx @@ -0,0 +1,17 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const EditIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/src/components/icons/teenny/chevrons.jsx b/src/components/icons/teenny/chevrons.jsx new file mode 100644 index 000000000..7a710f2a0 --- /dev/null +++ b/src/components/icons/teenny/chevrons.jsx @@ -0,0 +1,31 @@ +export const ChevronUp = () => ( + + + +); + +export const ChevronDown = () => ( + + + +); diff --git a/src/components/icons/teenny/pin.jsx b/src/components/icons/teenny/pin.jsx new file mode 100644 index 000000000..f2cad3657 --- /dev/null +++ b/src/components/icons/teenny/pin.jsx @@ -0,0 +1,22 @@ +export const PinIcon = () => ( + + + + +); diff --git a/src/components/inputs/InputField.tsx b/src/components/inputs/InputField.tsx new file mode 100644 index 000000000..2adc49556 --- /dev/null +++ b/src/components/inputs/InputField.tsx @@ -0,0 +1,31 @@ +import { ComponentChild } from "preact"; +import { FieldValues, Path } from "react-hook-form"; +import { UseFormRegister } from "react-hook-form/dist/types/form"; +import { RegisterOptions } from "react-hook-form/dist/types/validator"; + +const InputField = ({ + id, + label, + register, + options, +}: { + id: Path; + label: string | ComponentChild; + register?: UseFormRegister; + options?: RegisterOptions; +}) => { + return ( +
+ + +
+ ); +}; + +export default InputField; diff --git a/src/components/toast/index.tsx b/src/components/toast/index.tsx index cf72a3eaf..102a67c45 100644 --- a/src/components/toast/index.tsx +++ b/src/components/toast/index.tsx @@ -1,14 +1,19 @@ import { ComponentChildren } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import { animated, useSpring } from "react-spring"; import style from "./style.less"; type ToastType = "success" | "error" | "info"; -type ToastProps = { +export interface IToastProps { text: ComponentChildren; type?: ToastType; onHide?: () => void; -}; + onAction?: () => void; + actionText?: string; + duration?: number; +} const getStyle = (type: ToastType) => { switch (type) { @@ -21,12 +26,66 @@ const getStyle = (type: ToastType) => { } }; -const Toast = ({ text, type = "info", onHide }: ToastProps) => ( -
-
- {text} +const Toast = ({ + text, + type = "info", + onHide, + onAction, + actionText = "Undo", + duration, +}: IToastProps) => { + const [showToast, setShowToast] = useState(true); + const _onAction = () => { + if (onAction) onAction(); + }; + + const _onHide = () => { + setShowToast(false); + if (onHide) onHide(); + }; + + const animationProps = useSpring({ + from: { transform: "translateY(180%)" }, + to: { transform: "translateY(0)" }, + config: { duration: 30 }, + }); + + useEffect(() => { + if (duration) { + const timer = setTimeout(() => { + _onHide(); + }, duration); + return () => clearTimeout(timer); + } + }, [duration, _onHide]); + + if (!showToast) return; + + return ( +
+ { + e.stopPropagation(); + _onHide(); + }} + > +
{text}
+ {onAction && ( +
{ + e.stopPropagation(); + _onAction(); + }} + className={"text-primary-light"} + > + {actionText} +
+ )} +
-
-); + ); +}; export default Toast; diff --git a/src/components/toast/style.less b/src/components/toast/style.less index 849af08d2..818f8f4c0 100644 --- a/src/components/toast/style.less +++ b/src/components/toast/style.less @@ -1,20 +1,26 @@ .toastWrapper { - width: 100%; - position: fixed; - z-index: 99990; - bottom: 0px; - right: 0px; + width: 100%; + position: fixed; + z-index: 99990; + bottom: 40px; + right: 0px; } .toast { - background: #000; - margin: 2em 2em; - text-align: center; + background: #313033; + margin: 2em 2em; transition: all 250ms ease-in; - color: #FFF; - cursor: pointer; - padding: 0.5em; -}; + color: #fff; + cursor: pointer; + padding: 14px 16px; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + border-radius: 4px; + + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} .success { background: #389256; diff --git a/src/components/toast/toastProvider.tsx b/src/components/toast/toastProvider.tsx new file mode 100644 index 000000000..76eccb50d --- /dev/null +++ b/src/components/toast/toastProvider.tsx @@ -0,0 +1,38 @@ +import { ComponentChildren } from "preact"; +import React, { createContext, useContext, useState } from "react"; + +import Toast, { IToastProps } from "components/toast/index"; + +const ToastContext = createContext< + | { + showToast: (toastProps: IToastProps) => void; + hideToast: () => void; + } + | undefined +>(undefined); + +interface ToastProviderProps { + children: ComponentChildren; +} + +export const ToastProvider: React.FC = ({ children }) => { + const [toastProps, setToastProps] = useState(null); + + const showToast = (props: IToastProps) => setToastProps(props); + const hideToast = () => setToastProps(null); + + return ( + + {children} + {toastProps && } + + ); +}; + +export const useToast = () => { + const context = useContext(ToastContext); + if (context === undefined) { + throw new Error("useToast must be used within a ToastProvider"); + } + return context; +}; diff --git a/src/config.ts b/src/config.ts index b4302bbdd..2d09e9a92 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,6 +3,7 @@ import ChangeNode from "plugins/lime-plugin-changeNode"; import Fbw from "plugins/lime-plugin-fbw"; import Firmware from "plugins/lime-plugin-firmware"; import Locate from "plugins/lime-plugin-locate"; +import MeshWide from "plugins/lime-plugin-mesh-wide"; import Metrics from "plugins/lime-plugin-metrics"; import NetworkAdmin from "plugins/lime-plugin-network-admin"; import NodeAdmin from "plugins/lime-plugin-node-admin"; @@ -16,6 +17,7 @@ export const plugins: LimePlugin[] = [ Rx, Align, Locate, + MeshWide, Metrics, Notes, NodeAdmin, diff --git a/src/utils/constants.js b/src/utils/constants.js index 8db62bcc6..d633a93ab 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -4,4 +4,6 @@ export const DEFAULT_COMMUNITY_SETTINGS = { bad_bandwidth: "1", good_signal: "-65", good_bandwidth: "5", + mw_link_signal_threshold: 10, + mw_link_chain_threshold: 3, }; diff --git a/src/utils/useSharedData.ts b/src/utils/useSharedData.ts new file mode 100644 index 000000000..577686127 --- /dev/null +++ b/src/utils/useSharedData.ts @@ -0,0 +1,17 @@ +import { useQuery } from "@tanstack/react-query"; + +import queryCache from "utils/queryCache"; + +/** + * This hook is used as generic hook to share data between components using react query. On certain way is a state + * management hook using the capabilities of the react query queryCache + * @param queryKey + */ +export const useSharedData = ( + queryKey: Array +): { data: T | null; setData: (newData: T) => void } => { + const { data } = useQuery(queryKey, () => null); + const setData = (newData: T) => queryCache.setQueryData(queryKey, newData); + + return { data, setData }; +}; diff --git a/src/utils/utils.tsx b/src/utils/utils.tsx new file mode 100644 index 000000000..68b889a4a --- /dev/null +++ b/src/utils/utils.tsx @@ -0,0 +1,3 @@ +export function isEmpty(obj: object): boolean { + return Object.keys(obj).length === 0; +} diff --git a/tailwind.config.js b/tailwind.config.js index e1888ccf0..9773ed829 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,3 +1,6 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const colors = require("tailwindcss/colors"); + /** @type {import('tailwindcss').Config} */ module.exports = { // mode: "jit", @@ -8,7 +11,27 @@ module.exports = { ], darkMode: false, // or 'media' or 'class' theme: { - extend: {}, + extend: { + colors: { + primary: { + DEFAULT: "#38927f", + light: "#6BC3AE", + dark: "#006453", + card: "#DBE5E0", + }, + button: { + primary: "#1BC47D", + secondary: "#6BC3AE", + info: "#00ADEE", + disabled: "#BABABA", + }, + danger: "#EB7575", + info: "#EAAB7E", + success: "#76BD7D", + internet: "#5F65FF", + disabled: colors.gray["500"], + }, + }, }, plugins: [], }; diff --git a/tsconfig.json b/tsconfig.json index 32e04bb05..a24c42f47 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { /* Basic Options */ - "target": "ES5", + "target": "es2015", "allowJs": true, "checkJs": true, "jsx": "preserve", @@ -15,6 +15,7 @@ /* Module Resolution Options */ "moduleResolution": "node", + "module": "esnext", "esModuleInterop": true, "baseUrl": ".", "paths": { From be826c927ca18aa59c85e706db32758b359fb935 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 7 May 2024 06:49:09 -0500 Subject: [PATCH 02/22] chore(meshupgrade): implement mesh upgrade wizard (#415) See https://github.com/libremesh/lime-app/pull/415 --- .../src/upgradeAvailable.js | 2 +- .../lime-plugin-mesh-wide-upgrade/index.ts | 7 + .../src/components/modals.tsx | 96 +++++++ .../src/components/nextStepFooter.tsx | 11 + .../src/components/nodeUpgradeInfo.tsx | 72 +++++ .../upgradeState/ConfirmationPending.tsx | 25 ++ .../components/upgradeState/ErrorState.tsx | 16 ++ .../components/upgradeState/LoadingPage.tsx | 19 ++ .../upgradeState/NewVersionAvailable.tsx | 42 +++ .../components/upgradeState/NoNewVersion.tsx | 19 ++ .../upgradeState/ParallelErrors.tsx | 28 ++ .../upgradeState/TransactionStarted.tsx | 17 ++ .../upgradeState/UpgradeScheduled.tsx | 25 ++ .../src/containers/meshWideUpgradeStatus.tsx | 80 ++++++ .../src/containers/nodesList.tsx | 27 ++ .../src/hooks/meshWideUpgradeProvider.tsx | 225 +++++++++++++++ .../src/hooks/useStepper.tsx | 271 ++++++++++++++++++ .../src/meshUpgradeApi.tsx | 52 ++++ .../src/meshUpgradePage.spec.js | 12 + .../src/meshUpgradePage.tsx | 100 +++++++ .../src/meshUpgradeQueries.tsx | 97 +++++++ .../src/meshUpgradeQueriesKeys.tsx | 23 ++ .../src/meshUpgradeTypes.ts | 71 +++++ .../src/utils/api.ts | 98 +++++++ .../src/utils/divs.tsx | 9 + .../src/utils/eupgrade.ts | 14 + .../src/utils/processError.ts | 11 + .../src/utils/upgradeStatusMessages.tsx | 97 +++++++ .../src/components/Components.tsx | 11 +- .../components/FeatureDetail/LinkDetail.tsx | 8 +- .../src/components/configPage/MeshStatus.tsx | 9 +- .../src/icons/SuccessIcon.tsx | 3 - .../src/icons/errorIcon.tsx | 11 - .../src/screens/configPage.tsx | 6 +- src/components/divider/index.tsx | 13 +- src/components/icons/notification/rocket.tsx | 14 + src/components/icons/notification/warning.tsx | 14 + src/components/icons/status.tsx | 27 ++ src/components/icons/teenny/chevrons.jsx | 16 ++ src/components/list-material/index.ts | 1 + src/components/list-material/list.tsx | 82 ++++++ src/components/notifications/notification.tsx | 51 ++++ src/components/status/footer.tsx | 26 ++ src/components/status/statusAndButton.tsx | 37 +++ src/components/status/statusMessage.tsx | 22 ++ src/config.ts | 2 + src/utils/meshWideSyncCall.ts | 133 +++++++++ src/utils/queries.js | 12 +- src/utils/uhttpd.service.js | 12 +- src/utils/useSharedData.ts | 3 +- 50 files changed, 2037 insertions(+), 42 deletions(-) create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/index.ts create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.spec.js create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes.ts create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/utils/eupgrade.ts create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/utils/processError.ts create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx delete mode 100644 plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx delete mode 100644 plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx create mode 100644 src/components/icons/notification/rocket.tsx create mode 100644 src/components/icons/notification/warning.tsx create mode 100644 src/components/icons/status.tsx create mode 100644 src/components/list-material/index.ts create mode 100644 src/components/list-material/list.tsx create mode 100644 src/components/notifications/notification.tsx create mode 100644 src/components/status/footer.tsx create mode 100644 src/components/status/statusAndButton.tsx create mode 100644 src/components/status/statusMessage.tsx create mode 100644 src/utils/meshWideSyncCall.ts diff --git a/plugins/lime-plugin-firmware/src/upgradeAvailable.js b/plugins/lime-plugin-firmware/src/upgradeAvailable.js index 4bd0a9d96..bc3cadfb7 100644 --- a/plugins/lime-plugin-firmware/src/upgradeAvailable.js +++ b/plugins/lime-plugin-firmware/src/upgradeAvailable.js @@ -22,7 +22,7 @@ export const UpgradeAvailableBanner = () => { // @ts-ignore {({ path }) => - !["firmware", "releaseInfo"].includes( + !["firmware", "releaseInfo", "meshwideupgrade"].includes( path.replace("/", "") ) && (
{ + let title = All nodes are ready; + let content = ( + Schedule a firmware upgrade for all nodes on the network + ); + if (!allNodesReady) { + title = Some nodes are not ready; + content = ( + + Are you sure you want to start mesh wide upgrade?
+ Check node list to see the network status +
+ ); + } + + return useParallelQueriesModal({ + allNodesReady, + cb, + title, + content, + }); +}; + +export const useConfirmModal = ({ + allNodesReady, + cb, +}: IUseParallelQueriesModalProps) => { + let title = All nodes are upgraded successfully; + let content = ( + Confirm mesh wide upgrade for all nodes on the network + ); + if (!allNodesReady) { + title = Some nodes don't upgraded properly; + content = ( + + Are you sure you want to confirm the upgrade?
+ Check node list to see the network status +
+ ); + } + return useParallelQueriesModal({ + allNodesReady, + cb, + title, + content, + }); +}; + +interface IUseParallelQueriesModalProps { + allNodesReady: boolean; + cb?: (e) => void; + title?: VNode; + content?: VNode; +} + +const useParallelQueriesModal = ({ + allNodesReady, + cb, + title, + content, +}: IUseParallelQueriesModalProps) => { + const { toggleModal, setModalState } = useModal(); + const runAndClose = useCallback(() => { + cb(null); + toggleModal(); + }, [cb, toggleModal]); + + const showModal = useCallback(() => { + setModalState({ + content, + title, + successCb: allNodesReady ? runAndClose : undefined, + deleteCb: !allNodesReady ? runAndClose : undefined, + successBtnText: Schedule, + deleteBtnText: Schedule, + }); + toggleModal(); + }, [ + setModalState, + content, + title, + allNodesReady, + runAndClose, + toggleModal, + ]); + return { showModal, toggleModal }; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx new file mode 100644 index 000000000..e2c82d4e8 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx @@ -0,0 +1,11 @@ +import { FooterStatus } from "components/status/footer"; + +import { useStep } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper"; + +const NextStepFooter = () => { + const { step, showFooter } = useStep(); + + return <>{showFooter && }; +}; + +export default NextStepFooter; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx new file mode 100644 index 000000000..775754693 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx @@ -0,0 +1,72 @@ +import { Trans } from "@lingui/macro"; +import { ComponentChildren } from "preact"; + +import { StatusIcon, StatusIcons } from "components/icons/status"; +import { ListItemCollapsible } from "components/list-material"; + +import { MeshWideNodeUpgradeInfo } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { + InfoStatusMessageMap, + detailedInfoStatusMessageMap, + mainNodeStatusMessageMap, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages"; + +export interface INodeInfoBodyItemProps { + title: ComponentChildren; + description: ComponentChildren; +} + +const NodeInfoBodyItem = ({ title, description }: INodeInfoBodyItemProps) => ( +
+
{title}
+
{description}
+
+); + +const NodeUpgradeInfoItem = ({ + info, + name, +}: { + info: MeshWideNodeUpgradeInfo; + name: string; +}) => { + const status: StatusIcons = + info.upgrade_state === "ERROR" ? "warning" : "success"; + + const nodeStatusInfo = + detailedInfoStatusMessageMap(info)[info.upgrade_state] ?? + detailedInfoStatusMessageMap()["DEFAULT"]; + + const mainNodeStatusInfo = mainNodeStatusMessageMap[info.main_node]; + let descriptionMsg = InfoStatusMessageMap[info.upgrade_state] ?? ( + Error retrieving the status, is this node outdated? + ); + if (mainNodeStatusInfo) { + descriptionMsg = (Main Node) {descriptionMsg}; + } + return ( + } + rightText={"Info"} + > + + {mainNodeStatusInfo && } + Board} + description={{info.board_name}} + /> + Firmware version} + description={{info.current_fw}} + /> + Ip} + description={{info.node_ip}} + /> + + ); +}; + +export default NodeUpgradeInfoItem; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx new file mode 100644 index 000000000..2bc4e62c7 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx @@ -0,0 +1,25 @@ +import { Trans } from "@lingui/macro"; + +import { ParallelErrors } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors"; +import { useParallelConfirmUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; + +export const ConfirmationPending = () => { + const { errors } = useParallelConfirmUpgrade(); + + return ( + <> +
+ Upgrade done +
+
+ + Check if network is working properly and confirm the upgrade +
+ If not confirmed, the upgrade will be rolled back after a + while +
+
+ {errors?.length > 0 && } + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx new file mode 100644 index 000000000..186be2212 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx @@ -0,0 +1,16 @@ +import { Trans } from "@lingui/macro"; +import { VNode } from "preact"; + +export const ErrorState = ({ msg }: { msg: string | VNode }) => { + return ( +
+
+ ! +
+
+ Error! +
+
{msg}
+
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx new file mode 100644 index 000000000..d46b30670 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx @@ -0,0 +1,19 @@ +import { VNode } from "preact"; + +import Loading from "components/loading"; + +export const LoadingPage = ({ + title, + description, +}: { + title: VNode; + description?: VNode; +}) => { + return ( +
+ +
{title}
+ {description &&
{description}
} +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx new file mode 100644 index 000000000..2031f2aa5 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx @@ -0,0 +1,42 @@ +import { Trans } from "@lingui/macro"; + +import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; + +import { useBoardData } from "utils/queries"; + +export const NewVersionAvailable = ({ + readyForUpgrade, +}: { + readyForUpgrade?: boolean; +}) => { + const { data: boardData } = useBoardData(); + const { data: newVersion } = useNewVersion(); + + return ( +
+
+ {readyForUpgrade ? ( + Start Mesh Wide Transaction + ) : ( + New version available! + )} +
+
+ This node version: +
+ {boardData && boardData.release.description} +
+
+ New available version: +
+ {newVersion && newVersion.version} +
+ {readyForUpgrade && ( +
+ Is ready for upgrade! +
+
+ )} +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx new file mode 100644 index 000000000..ed09442ee --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx @@ -0,0 +1,19 @@ +import { Trans } from "@lingui/macro"; + +import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; + +import { useBoardData } from "utils/queries"; + +export const NoNewVersionAvailable = () => { + const { data: boardData } = useBoardData(); + const { data: newVersion } = useNewVersion(); + + return ( +
+
+
+ No new version available! +
+
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx new file mode 100644 index 000000000..3f5f12387 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx @@ -0,0 +1,28 @@ +import { Trans } from "@lingui/macro"; + +import { StatusMessage } from "components/status/statusMessage"; + +import { ParallelMutationError, SyncCallErrors } from "utils/meshWideSyncCall"; + +export const ParallelErrors = ({ errors }: { errors: SyncCallErrors }) => { + return ( + // Important to not add any style to this fragment because could add errors on growing on long lists + <> + + Some nodes have errors: + +
+ {errors.map((error, key) => { + if (error instanceof ParallelMutationError) { + return ( +
+ {error.ip}: {error.message} +
+ ); + } + return
{error.toString()}
; + })} +
+ + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx new file mode 100644 index 000000000..63de80451 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx @@ -0,0 +1,17 @@ +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; + +export const TransactionStarted = () => { + const { someNodeDownloading } = useMeshUpgrade(); + + return ( +
+ Transaction started! + {someNodeDownloading && ( +
+ Some nodes seems to be downloading, check network page for + more information +
+ )} +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx new file mode 100644 index 000000000..ac2a9a1f6 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx @@ -0,0 +1,25 @@ +import { Trans } from "@lingui/macro"; + +import { ParallelErrors } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors"; +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { useParallelScheduleUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; + +export const UpgradeScheduled = () => { + const { totalNodes } = useMeshUpgrade(); + const { errors, results } = useParallelScheduleUpgrade(); + const nodesToBeUpgraded = results.length; + + return ( + <> +
+ Upgrade is scheduled! +
+
+ + {nodesToBeUpgraded} of {totalNodes} will be upgraded + +
+ {errors?.length > 0 && } + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx new file mode 100644 index 000000000..036ab60cf --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx @@ -0,0 +1,80 @@ +import { Trans } from "@lingui/macro"; + +import { ConfirmationPending } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending"; +import { ErrorState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState"; +import { LoadingPage } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage"; +import { NewVersionAvailable } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable"; +import { NoNewVersionAvailable } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion"; +import { TransactionStarted } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted"; +import { UpgradeScheduled } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled"; +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { CenterFlex } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs"; + +const MeshWideUpgradeStatusState = () => { + const { stepperState, meshWideError } = useMeshUpgrade(); + + switch (stepperState) { + case "ERROR": + return ; + case "ABORTING": + return ( + Aborting} + description={ + + Sending abort message to this node. The abort order + will be propagated to all nodes. + + } + /> + ); + case "UPDATE_AVAILABLE": + return ; + case "DOWNLOADING_MAIN": + return Downloading} />; + case "DOWNLOADED_MAIN": + return ; + case "TRANSACTION_STARTED": + case "NODES_DOWNLOADING": + return ; + case "SENDING_START_SCHEDULE": + return ( + Scheduling upgrade} + description={ + Schedule upgrade to all available nodes + } + /> + ); + case "UPGRADING": + return ( + Node is upgrading} + description={Await until it reboots} + /> + ); + case "UPGRADE_SCHEDULED": + return ; + case "SENDING_CONFIRMATION": + return ( + Sending confirmation} + description={Confirming all upgraded nodes} + /> + ); + case "CONFIRMATION_PENDING": + return ; + case "CONFIRMED": + return <>Confirmed!; + default: + return ; + } +}; + +export const MeshWideUpgradeStatus = () => { + return ( + + + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx new file mode 100644 index 000000000..014e85757 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx @@ -0,0 +1,27 @@ +import Loading from "components/loading"; + +import NodeUpgradeInfoItem from "plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo"; +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; + +export const NodesList = () => { + const { data, isLoading } = useMeshUpgrade(); + + if (isLoading || data === undefined) { + return ; + } + + return ( + <> + {data && + Object.entries(data).map(([key, nodeInfo], index) => { + return ( + + ); + })} + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx new file mode 100644 index 000000000..3c52b1224 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx @@ -0,0 +1,225 @@ +import { ComponentChildren, createContext } from "preact"; +import { useMemo } from "preact/compat"; +import { useEffect } from "preact/hooks"; +import { useCallback, useContext } from "react"; + +import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; +import { getStepperStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper"; +import { + useAbort, + useBecomeMainNode, + useMeshUpgradeNodeStatus, + useMeshWideUpgradeInfo, + useParallelConfirmUpgrade, + useParallelScheduleUpgrade, + useStartFirmwareUpgradeTransaction, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; +import { meshUpgradeQueryKeys } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys"; +import { + MeshWideError, + MeshWideUpgradeInfo, + NodeMeshUpgradeInfo, + StepperState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { getMeshWideError } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/processError"; + +import { useSession } from "utils/queries"; +import queryCache from "utils/queryCache"; + +const NODE_STATUS_REFETCH_INTERVAL = 2000; + +interface MeshWideUpgradeContextProps { + data?: MeshWideUpgradeInfo; + thisNode: NodeMeshUpgradeInfo; + totalNodes: number; + isLoading: boolean; + isError: boolean; + error: unknown; + newVersionAvailable: boolean; + stepperState: StepperState; + becomeMainNode: () => void; + startFwUpgradeTransaction: () => void; + meshWideError?: MeshWideError; + allNodesReadyForUpgrade: boolean; + allNodesConfirmed: boolean; + someNodeDownloading: boolean; + abort: () => void; +} + +export const MeshWideUpgradeContext = + createContext({ + isLoading: false, + isError: false, + error: null, + totalNodes: 0, + newVersionAvailable: false, + stepperState: "INITIAL", + thisNode: null, + becomeMainNode: () => {}, + startFwUpgradeTransaction: () => {}, + abort: () => {}, + allNodesReadyForUpgrade: false, + allNodesConfirmed: false, + someNodeDownloading: false, + }); + +export const MeshWideUpgradeProvider = ({ + children, +}: { + children: ComponentChildren; +}) => { + // UseCallback to invalidate queries + const invalidateQueries = useCallback(() => { + queryCache.invalidateQueries({ + queryKey: meshUpgradeQueryKeys.getMeshUpgradeNodeStatus(), + }); + }, []); + + const invalidateLogin = useCallback(() => { + queryCache.invalidateQueries({ + queryKey: ["session", "get"], + }); + }, []); + + const { + data: nodesUpgradeInfo, + isLoading: meshWideInfoLoading, + isError: isMeshWideQueryError, + error: meshWideQueryError, + } = useMeshWideUpgradeInfo({ + refetchInterval: NODE_STATUS_REFETCH_INTERVAL, + }); + + const { mutate: becomeMainNodeMutation } = useBecomeMainNode({ + onSuccess: () => { + invalidateQueries(); + }, + }); + + const { mutate: fwUpgradeTransaction } = useStartFirmwareUpgradeTransaction( + { + onSuccess: () => { + invalidateQueries(); + }, + } + ); + + const { mutate: abort, isLoading: isAborting } = useAbort({}); + + const { data: session } = useSession(); + const { data: newVersionData } = useNewVersion({ + enabled: session?.username !== undefined, + }); + + const newVersionAvailable = !!(newVersionData && newVersionData.version); + const totalNodes = + nodesUpgradeInfo && Object.entries(nodesUpgradeInfo).length; + + const { + data: thisNode, + isLoading: thisNodeLoading, + isError: isThisNodeError, + } = useMeshUpgradeNodeStatus({ + refetchInterval: NODE_STATUS_REFETCH_INTERVAL, + }); + + const eupgradeStatus = thisNode?.eupgradestate; + + const meshSafeUpgrade = useParallelScheduleUpgrade(); + const confirmUpgrade = useParallelConfirmUpgrade(); + + // useMemo to check that all nodes have the status of READY_FOR_UPGRADE + const allNodesReadyForUpgrade = useMemo(() => { + return Object.values(nodesUpgradeInfo || {}).every( + (node) => node.upgrade_state === "READY_FOR_UPGRADE" + ); + }, [nodesUpgradeInfo]); + + const allNodesConfirmed = useMemo(() => { + return Object.values(nodesUpgradeInfo || {}).every( + (node) => node.upgrade_state === "CONFIRMED" + ); + }, [nodesUpgradeInfo]); + + const someNodeDownloading = useMemo(() => { + return Object.values(nodesUpgradeInfo || {}).some( + (node) => node.upgrade_state === "DOWNLOADING" + ); + }, [nodesUpgradeInfo]); + + const stepperState = getStepperStatus( + nodesUpgradeInfo, + thisNode, + isThisNodeError, + newVersionAvailable, + eupgradeStatus, + meshSafeUpgrade, + confirmUpgrade, + someNodeDownloading, + isAborting + ); + + const meshWideError = getMeshWideError(thisNode); + + const becomeMainNode = useCallback(() => { + becomeMainNodeMutation({}); + }, [becomeMainNodeMutation]); + + const startFwUpgradeTransaction = useCallback(() => { + fwUpgradeTransaction({}); + }, [fwUpgradeTransaction]); + + const isLoading = meshWideInfoLoading || thisNodeLoading; + + let isError; + let error; + // If the state is upgrading, ignore the errors because is normal to lose the connection + if (stepperState !== "UPGRADING") { + isError = isMeshWideQueryError; + error = meshWideQueryError; + } + + useEffect(() => { + if ( + meshWideQueryError && + (meshWideQueryError as any).code != null && + (meshWideQueryError as any).code === -32002 // Auth failed error code + ) { + invalidateLogin(); + } + }, [invalidateLogin, meshWideQueryError, stepperState]); + + return ( + + {children} + + ); +}; + +export const useMeshUpgrade = () => { + const context = useContext(MeshWideUpgradeContext); + if (context === undefined) { + throw new Error( + "useMeshUpgrade must be used within a MeshWideUpgradeProvider" + ); + } + return context; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx new file mode 100644 index 000000000..8b8a351de --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx @@ -0,0 +1,271 @@ +import { Trans } from "@lingui/macro"; +import { useMemo } from "react"; + +import { IStatusAndButton } from "components/status/statusAndButton"; + +import { + useConfirmModal, + useScheduleUpgradeModal, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { + UseConfirmUpgradeType, + UseScheduleMeshSafeUpgradeType, + useParallelConfirmUpgrade, + useParallelScheduleUpgrade, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; +import { + MeshWideUpgradeInfo, + NodeMeshUpgradeInfo, + StepperState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { EupgradeStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/eupgrade"; + +export const getStepperStatus = ( + nodeInfo: MeshWideUpgradeInfo | undefined, + thisNode: NodeMeshUpgradeInfo | undefined, + thisNodeError: boolean, + newVersionAvailable: boolean, + downloadStatus: EupgradeStatus, + scheduleMeshSafeUpgradeStatus: UseScheduleMeshSafeUpgradeType | undefined, + confirmUpgradeStatus: UseConfirmUpgradeType | undefined, + someNodeAreDownloading: boolean, + isAborting: boolean +): StepperState => { + if (!nodeInfo || !thisNode) return "INITIAL"; + + if (isAborting) { + return "ABORTING"; + } + + if (downloadStatus === "download-failed") { + return "ERROR"; + } + + if ( + thisNode.upgrade_state === "DEFAULT" || + thisNode.upgrade_state === "ABORTED" + ) { + if (newVersionAvailable) return "UPDATE_AVAILABLE"; + return "NO_UPDATE"; + } + + if (thisNode.main_node === "STARTING") { + if (downloadStatus === "downloaded") { + return "DOWNLOADED_MAIN"; + } + return "DOWNLOADING_MAIN"; + } + if ( + thisNode.upgrade_state === "READY_FOR_UPGRADE" || + thisNode.upgrade_state === "DOWNLOADING" || + thisNode.upgrade_state === "UPGRADE_SCHEDULED" + ) { + // We suppose that if the upgrade is scheduled, and we lost the connection is because is upgrading + if (thisNode.upgrade_state === "UPGRADE_SCHEDULED" && thisNodeError) { + return "UPGRADING"; + } + if (scheduleMeshSafeUpgradeStatus?.isLoading) { + return "SENDING_START_SCHEDULE"; + } + if (someNodeAreDownloading) { + return "NODES_DOWNLOADING"; + } + if ( + scheduleMeshSafeUpgradeStatus?.results?.length || + scheduleMeshSafeUpgradeStatus?.errors?.length + ) { + return "UPGRADE_SCHEDULED"; + } + // Here the user can send the schedule upgrade to the nodes + return "TRANSACTION_STARTED"; + } + if ( + thisNode.upgrade_state === "CONFIRMATION_PENDING" || + thisNode.upgrade_state === "CONFIRMED" + ) { + if (confirmUpgradeStatus?.isLoading) { + return "SENDING_CONFIRMATION"; + } + if (confirmUpgradeStatus?.errors?.length) { + return "CONFIRMATION_PENDING"; + } + return thisNode.upgrade_state; + } + if (thisNode.upgrade_state === "ERROR") { + return "ERROR"; + } + return "INITIAL"; +}; + +export type ShowFooterStepperState = Extract< + StepperState, + | "UPDATE_AVAILABLE" + | "DOWNLOADED_MAIN" + | "TRANSACTION_STARTED" + | "UPGRADE_SCHEDULED" + | "CONFIRMATION_PENDING" + | "ERROR" +>; + +export function isShowFooterStepperState( + value: string +): value is ShowFooterStepperState { + return [ + "UPDATE_AVAILABLE", + "DOWNLOADED_MAIN", + "TRANSACTION_STARTED", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} + +function isShowAbortButtonState( + value: string +): value is ShowFooterStepperState { + return [ + "TRANSACTION_STARTED", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} + +export const useStep = () => { + const { + stepperState, + becomeMainNode, + startFwUpgradeTransaction, + allNodesReadyForUpgrade, + abort, + } = useMeshUpgrade(); + + const { callMutations: startScheduleMeshUpgrade, errors: scheduleErrors } = + useParallelScheduleUpgrade(); + + const { callMutations: confirmMeshUpgrade, errors: confirmErrors } = + useParallelConfirmUpgrade(); + + const { showModal: showScheduleModal } = useScheduleUpgradeModal({ + allNodesReady: allNodesReadyForUpgrade, + cb: () => { + startScheduleMeshUpgrade(); + }, + }); + + const { showModal: showConfirmationModal } = useConfirmModal({ + // Ideally we have to implement some kind of state before run the upgrade to check if all nodes are up again. + allNodesReady: true, + cb: () => { + confirmMeshUpgrade(); + }, + }); + + const showFooter = isShowFooterStepperState(stepperState); + + const step: IStatusAndButton | null = useMemo(() => { + if (!showFooter) return null; + + let step: IStatusAndButton; + switch (stepperState as ShowFooterStepperState) { + case "UPDATE_AVAILABLE": + step = { + status: "success", + onClick: () => becomeMainNode(), + children: ( + + Download remote firmware +
+ to start mesh upgrade +
+ ), + btn: Start mesh upgrade, + }; + break; + case "DOWNLOADED_MAIN": + step = { + status: "success", + onClick: startFwUpgradeTransaction, + children: Ready to start mesh wide upgrade, + btn: Start, + }; + break; + case "TRANSACTION_STARTED": + step = { + status: allNodesReadyForUpgrade ? "success" : "warning", + onClick: () => { + showScheduleModal(); + }, + children: allNodesReadyForUpgrade ? ( + Ready to start mesh wide upgrade + ) : ( + + Some nodes are not ready for upgrade
+ Check node details for more info +
+ ), + btn: Schedule upgrade, + }; + break; + case "UPGRADE_SCHEDULED": { + const data: Omit = { + onClick: showScheduleModal, + btn: Schedule again, + }; + if (scheduleErrors?.length) { + step = { + ...data, + status: "warning", + children: Some nodes have errors, + }; + } + step = { + ...data, + status: "success", + children: All nodes scheduled successful, + }; + break; + } + case "CONFIRMATION_PENDING": + step = { + status: "success", + onClick: showConfirmationModal, + children: Confirm upgrade on all nodes, + btn: Confirm, + }; + break; + case "ERROR": + default: + step = { + status: "warning", + children: Try last step again, + }; + } + if (isShowAbortButtonState(stepperState)) { + const showAbort: Pick< + IStatusAndButton, + "btnCancel" | "onClickCancel" + > = { + btnCancel: Abort, + onClickCancel: async () => { + await abort(); + }, + }; + step = { ...step, ...showAbort }; + } + return step; + }, [ + abort, + allNodesReadyForUpgrade, + becomeMainNode, + scheduleErrors?.length, + showConfirmationModal, + showFooter, + showScheduleModal, + startFwUpgradeTransaction, + stepperState, + ]); + + return { step, showFooter }; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx new file mode 100644 index 000000000..aa913fc96 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx @@ -0,0 +1,52 @@ +import { + MeshWideUpgradeInfo, + NodeMeshUpgradeInfo, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { + callToRemoteNode, + meshUpgradeApiCall, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; + +import api from "utils/uhttpd.service"; + +export const getMeshWideUpgradeInfo = async () => { + const res = await api.call("shared-state-async", "get", { + data_type: "mesh_wide_upgrade", + }); + if (res.error) { + throw new Error( + `Error getting mesh wide upgrade info from shared state async, code error ${res.error}` + ); + } + return res.data as MeshWideUpgradeInfo; +}; + +export const getMeshUpgradeNodeStatus = async () => { + return (await api.call( + "lime-mesh-upgrade", + "get_node_status", + {} + )) as NodeMeshUpgradeInfo; +}; + +export const setBecomeMainNode = async () => { + return (await meshUpgradeApiCall("become_main_node")) as string; +}; + +export const setStartFirmwareUpgradeTransaction = async () => { + return await meshUpgradeApiCall("start_firmware_upgrade_transaction"); +}; + +export const setAbort = async () => { + return await meshUpgradeApiCall("abort"); +}; + +// Remote API calls + +export async function remoteScheduleUpgrade({ ip }: { ip: string }) { + return await callToRemoteNode({ ip, apiMethod: "start_safe_upgrade" }); +} + +export async function remoteConfirmUpgrade({ ip }: { ip: string }) { + return await callToRemoteNode({ ip, apiMethod: "confirm_boot_partition" }); +} diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.spec.js b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.spec.js new file mode 100644 index 000000000..39edfdb39 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.spec.js @@ -0,0 +1,12 @@ +import "@testing-library/jest-dom"; + +describe("Mesh wide upgrade Page", () => { + beforeEach(() => {}); + + afterEach(() => {}); + + it.skip("should show loader when eupgrade status is loading", async () => {}); + it.skip("should show no updates available component when no upgrade is available", async () => {}); + it.skip("should show ready to start transaction when new firmware is downloaded", async () => {}); + it.skip("should show node error when an error is returned", async () => {}); +}); diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx new file mode 100644 index 000000000..2ef388f15 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx @@ -0,0 +1,100 @@ +import { Trans } from "@lingui/macro"; +import { useState } from "preact/hooks"; + +import { StatusIcon } from "components/icons/status"; +import Loading from "components/loading"; +import Notification from "components/notifications/notification"; + +import NextStepFooter from "plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter"; +import { ErrorState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState"; +import { MeshWideUpgradeStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus"; +import { NodesList } from "plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList"; +import { + MeshWideUpgradeProvider, + useMeshUpgrade, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { CenterFlex } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs"; + +const MeshWideUpgrade = () => { + const { + data: meshWideNodes, + isLoading, + thisNode, + isError, + error, + } = useMeshUpgrade(); + const [showNodeList, setShowNodeList] = useState(false); + + if (isError) { + return ( + + + Errors found getting mesh info! + {error &&
{error.toString()}
} +
+ } + /> + + ); + } + + if (isLoading || meshWideNodes === undefined || thisNode === undefined) { + return ( + + + + ); + } + + return ( +
+ setShowNodeList(!showNodeList)} + className={"cursor-pointer"} + > + {showNodeList ? ( + Show state + ) : ( + Show nodes + )} +
+ } + > + + Upgrade all network nodes at once. This proces will take a + while and will require user interaction. + + + {thisNode.upgrade_state === "ABORTED" && ( +
+ + This node aborted successfully +
+ )} +
+ {showNodeList && } + {!showNodeList && } +
+ +
+ ); +}; + +const MeshUpgradePage = () => { + return ( + + + + ); +}; + +export default MeshUpgradePage; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx new file mode 100644 index 000000000..1a0894e6d --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx @@ -0,0 +1,97 @@ +import { useMutation, useQuery } from "@tanstack/react-query"; + +import { + getMeshUpgradeNodeStatus, + getMeshWideUpgradeInfo, + remoteConfirmUpgrade, + remoteScheduleUpgrade, + setAbort, + setBecomeMainNode, + setStartFirmwareUpgradeTransaction, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi"; +import { meshUpgradeQueryKeys } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys"; +import { + MeshWideUpgradeInfo, + NodeMeshUpgradeInfo, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { getNodeIpsByStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; + +import { useMeshWideSyncCall } from "utils/meshWideSyncCall"; + +// Shared state related queries + +export function useMeshWideUpgradeInfo(params) { + return useQuery( + meshUpgradeQueryKeys.getMeshWideUpgradeInfo(), + getMeshWideUpgradeInfo, + { + ...params, + } + ); +} + +// Synchronous queries/mutations + +export function useMeshUpgradeNodeStatus(params) { + return useQuery( + meshUpgradeQueryKeys.getMeshUpgradeNodeStatus(), + getMeshUpgradeNodeStatus, + { + ...params, + } + ); +} + +export function useBecomeMainNode(params) { + return useMutation({ + mutationFn: setBecomeMainNode, + ...params, + }); +} + +export function useStartFirmwareUpgradeTransaction(params) { + return useMutation({ + mutationFn: setStartFirmwareUpgradeTransaction, + ...params, + }); +} + +export function useAbort(params) { + return useMutation({ + mutationFn: setAbort, + ...params, + }); +} + +// Parallel queries/mutations + +export type UseScheduleMeshSafeUpgradeType = ReturnType< + typeof useParallelScheduleUpgrade +>; +export const useParallelScheduleUpgrade = (opts?) => { + // State to store the errors + const { data: nodes } = useMeshWideUpgradeInfo({}); + const ips = getNodeIpsByStatus(nodes, "READY_FOR_UPGRADE"); + // localStorage.setItem("hideReleaseBannerPlease", value); + return useMeshWideSyncCall({ + mutationKey: meshUpgradeQueryKeys.remoteScheduleUpgrade(), + mutationFn: remoteScheduleUpgrade, + ips, + options: opts, + }); +}; + +export type UseConfirmUpgradeType = ReturnType< + typeof useParallelConfirmUpgrade +>; +export const useParallelConfirmUpgrade = (opts?) => { + // State to store the errors + const { data: nodes } = useMeshWideUpgradeInfo({}); + const ips = getNodeIpsByStatus(nodes, "CONFIRMATION_PENDING"); + return useMeshWideSyncCall({ + mutationKey: meshUpgradeQueryKeys.remoteConfirmUpgrade(), + mutationFn: remoteConfirmUpgrade, + ips, + options: opts, + }); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx new file mode 100644 index 000000000..dc947d179 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx @@ -0,0 +1,23 @@ +import { QueryKey } from "@tanstack/react-query"; + +interface MeshUpgradeQueryKeysProps { + [key: string]: QueryKey; +} + +const MeshUpgradeQueryKeys: MeshUpgradeQueryKeysProps = { + meshWideUpgradeInfo: ["shared-state-async", "get", "mesh_wide_upgrade"], + getMeshUpgradeNodeStatus: ["lime-mesh-upgrade", "get_node_status"], + remoteScheduleUpgrade: ["lime-mesh-upgrade", "schedule_upgrade"], + remoteConfirmUpgrade: ["lime-mesh-upgrade", "confirm_boot_partition"], +}; + +export const meshUpgradeQueryKeys = { + getMeshWideUpgradeInfo: (): QueryKey => + MeshUpgradeQueryKeys.meshWideUpgradeInfo, + getMeshUpgradeNodeStatus: (): QueryKey => + MeshUpgradeQueryKeys.getMeshUpgradeNodeStatus, + remoteScheduleUpgrade: (): QueryKey => + MeshUpgradeQueryKeys.remoteScheduleUpgrade, + remoteConfirmUpgrade: (): QueryKey => + MeshUpgradeQueryKeys.remoteConfirmUpgrade, +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes.ts new file mode 100644 index 000000000..10fd27122 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes.ts @@ -0,0 +1,71 @@ +import { EupgradeStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/eupgrade"; + +export type MainNodeStatusType = "NO" | "STARTING" | "MAIN_NODE"; + +export type UpgradeStatusType = + | "DEFAULT" // No transaction + | "DOWNLOADING" // Transaction started + | "READY_FOR_UPGRADE" + | "UPGRADE_SCHEDULED" + | "CONFIRMATION_PENDING" + | "CONFIRMED" + | "ABORTED" + | "ERROR"; + +// Inner state to check the stepper state. It differs from the upgradeStatusType +// because is an inner state for the ui used on the main node, and is calculated +// on the ui side. +export type StepperState = + | "INITIAL" // No transaction + | "NO_UPDATE" // No update available + | "UPDATE_AVAILABLE" // New version available + | "DOWNLOADING_MAIN" // Downloading firmware to setup as master node + | "DOWNLOADED_MAIN" // Downloaded firmware to setup as master node + | "TRANSACTION_STARTED" // Transaction initiated and sharing new firmware + | "SENDING_START_SCHEDULE" // Sending start to start the upgrade + | "NODES_DOWNLOADING" // Some nodes on the network are downloading the firmware + | "UPGRADE_SCHEDULED" // Upgrade scheduled + | "UPGRADING" // Doing the upgrade + | "CONFIRMATION_PENDING" // Upgrade done, confirmation pending. + | "SENDING_CONFIRMATION" // Sending confirmation to confirm the upgrade + | "CONFIRMED" // Upgrade done, confirmed. + | "ERROR" // Error + | "ABORTING"; // Aborting + +/** + * Interface that describe the result for this node mesh upgrade status + */ +export interface NodeMeshUpgradeInfo { + timestamp: string; + main_node: MainNodeStatusType; + error: string; + transaction_state: string; + upgrade_state: UpgradeStatusType; + eupgradestate: EupgradeStatus; + repo_url?: string; + candidate_fw?: string; + board_name: string; + current_fw: string; + node_ip: string; +} + +export type MeshWideNodeUpgradeInfo = { + bleachTTL: number; + author: string; +} & NodeMeshUpgradeInfo; + +export interface MeshWideUpgradeInfo { + [key: string]: MeshWideNodeUpgradeInfo; +} + +export interface MeshWideRPCReturnTypes { + code: "SUCCESS" | "ERROR"; + error?: string; +} + +export type MeshWideError = { + errorCode: string; + errorMessage: string; +}; + +export type MeshUpgradeApiErrorTypes = string; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts new file mode 100644 index 000000000..8b23f3edf --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts @@ -0,0 +1,98 @@ +import { + MeshUpgradeApiErrorTypes, + MeshWideRPCReturnTypes, + MeshWideUpgradeInfo, + UpgradeStatusType, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; + +import { ParallelMutationError } from "utils/meshWideSyncCall"; +import { login } from "utils/queries"; +import api, { UhttpdService } from "utils/uhttpd.service"; + +export const meshUpgradeApiCall = async ( + method: string, + customApi?: UhttpdService +) => { + const httpService = customApi || api; + const res = (await httpService.call( + "lime-mesh-upgrade", + method, + {} + )) as MeshWideRPCReturnTypes; + if (res.error) { + throw new MeshUpgradeApiError(res.error, res.code); + } + return res.code; +}; + +export class MeshUpgradeApiError extends Error { + message: string; + code: MeshUpgradeApiErrorTypes; + constructor(message: string, code: MeshUpgradeApiErrorTypes) { + super(message); // Pass the message to the Error constructor + this.name = "MeshUpgradeApiError"; // Set the name of the error + this.message = message; + this.code = code; + Object.setPrototypeOf(this, MeshUpgradeApiError.prototype); + } +} + +/** + * Wrapper that tries to call a remote node and returns the result or throws an error + * + * First it tries to login and if success do a specific call to the remote node + * @param ip + * @param apiMethod + */ +export async function callToRemoteNode({ + ip, + apiMethod, +}: { + ip: string; + apiMethod: string; +}) { + const customApi = new UhttpdService(ip); + try { + await login({ username: "lime-app", password: "generic", customApi }); + } catch (error) { + throw new ParallelMutationError( + `Cannot login`, + customApi.customIp, + error + ); + } + try { + return await meshUpgradeApiCall(apiMethod, customApi); + } catch (error) { + let additionalInfo = ""; + if (error instanceof MeshUpgradeApiError) { + additionalInfo = `: ${error.message}`; + } + throw new ParallelMutationError( + `Cannot startSafeUpgrade${additionalInfo}`, + ip, + error + ); + } +} + +/** + * From a MeshWideUpgradeInfo nodes it returns the ips of the nodes that are in certain status provided + * @param nodes the nodes to check + * @param status the status to check the criteria + */ +export const getNodeIpsByStatus = ( + nodes: MeshWideUpgradeInfo, + status: UpgradeStatusType +) => { + if (!nodes) return []; + return Object.values(nodes) + .filter( + (node) => + node.node_ip !== null && + node.node_ip !== undefined && + node.node_ip.trim() !== "" && + node.upgrade_state === status + ) + .map((node) => node.node_ip as string); // 'as string' is safe here due to the filter condition +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx new file mode 100644 index 000000000..4b4e94b44 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx @@ -0,0 +1,9 @@ +import { VNode } from "preact"; + +export const CenterFlex = ({ children }: { children: VNode }) => { + return ( +
+ {children} +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/eupgrade.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/eupgrade.ts new file mode 100644 index 000000000..e3c689754 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/eupgrade.ts @@ -0,0 +1,14 @@ +export function isEupgradeStatus( + status: EupgradeStatus | undefined | null +): status is EupgradeStatus { + return EupgradeStatusStates.includes(status); +} + +export const EupgradeStatusStates = [ + "not-initiated", + "downloading", + "downloaded", + "download-failed", +] as const; + +export type EupgradeStatus = typeof EupgradeStatusStates[number]; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/processError.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/processError.ts new file mode 100644 index 000000000..cdfad0c84 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/processError.ts @@ -0,0 +1,11 @@ +import { + MeshWideError, + NodeMeshUpgradeInfo, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; + +export const getMeshWideError = ( + thisNode: NodeMeshUpgradeInfo +): MeshWideError | undefined => { + if (!thisNode || thisNode.upgrade_state !== "ERROR") return; + return { errorMessage: thisNode.error, errorCode: thisNode.upgrade_state }; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx new file mode 100644 index 000000000..049f96ea9 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx @@ -0,0 +1,97 @@ +import { Trans } from "@lingui/macro"; +import { ComponentChildren } from "preact"; + +import { INodeInfoBodyItemProps } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo"; +import { + MainNodeStatusType, + MeshWideNodeUpgradeInfo, + UpgradeStatusType, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; + +export const InfoStatusMessageMap: { + [status in UpgradeStatusType]: ComponentChildren; +} = { + DEFAULT: No upgrade in progres, + DOWNLOADING: Downloading new firmware, + READY_FOR_UPGRADE: Firmware downloaded, + UPGRADE_SCHEDULED: Upgrade scheduled, + CONFIRMATION_PENDING: Confirmation pending, + CONFIRMED: Confirmed, + ERROR: This node has an error, + ABORTED: This node aborted successfully, +}; + +type DetailedInfoStatusMessageMapType = { + [status in UpgradeStatusType]: INodeInfoBodyItemProps; +}; +export const detailedInfoStatusMessageMap = ( + nodeInfo?: MeshWideNodeUpgradeInfo +): DetailedInfoStatusMessageMapType => { + return { + DEFAULT: { + title: Everything is up to date!, + description: No new version available is found, + }, + DOWNLOADING: { + title: This node is downloading a new firmware, + description: Wait until the download is finished!, + }, + READY_FOR_UPGRADE: { + title: Firmware download and verified, + description: This node es ready for upgrade, + }, + UPGRADE_SCHEDULED: { + title: The upgrade is scheduled, + description: ( + After a time the upgrade will be performed + ), + }, + CONFIRMATION_PENDING: { + title: Awaiting confirmation, + description: ( + + The firmware seems to be installed successfully. Confirm + that the node is working properly or will be downgraded to + the previous version + + ), + }, + CONFIRMED: { + title: Upgrade successful, + description: ( + + Congratulations, this node was upgraded and confirmed + successfully + + ), + }, + ERROR: { + title: This node has an error!, + description: nodeInfo.error, + }, + ABORTED: { + title: This node aborted, + description: Start mesh wide firmware upgrade again, + }, + }; +}; + +type MainNodeInfoStatusMessageMapType = { + [status in MainNodeStatusType]: INodeInfoBodyItemProps; +}; + +export const mainNodeStatusMessageMap: MainNodeInfoStatusMessageMapType = { + NO: null, + STARTING: { + title: Setting up main node, + description: ( + The become main node process is starting on this node + ), + }, + MAIN_NODE: { + title: This is a main node, + description: ( + Other nodes will download the firmware from it + ), + }, +}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Components.tsx b/plugins/lime-plugin-mesh-wide/src/components/Components.tsx index 7305e4563..9c802d2be 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Components.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Components.tsx @@ -3,15 +3,14 @@ import { VNode } from "preact"; import { Button } from "components/buttons/button"; import { BinIcon } from "components/icons/bin"; import { EditIcon } from "components/icons/edit"; - -import SuccessIcon from "plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon"; -import ErrorIcon from "plugins/lime-plugin-mesh-wide/src/icons/errorIcon"; +import { StatusIcon } from "components/icons/status"; interface IStatusMessage { isError: boolean; children: VNode | string; } +// todo(kon): merge with src/components/status/statusAndButton.tsx export const StatusAndButton = ({ isError, children, @@ -39,7 +38,11 @@ export const StatusMessage = ({
- {isError ? : } + {isError ? ( + + ) : ( + + )} {children}
); diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index f9c15ef42..7436f2ebf 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -1,6 +1,7 @@ import { Trans } from "@lingui/macro"; import { useState } from "preact/hooks"; +import { Warning } from "components/icons/status"; import Tabs from "components/tabs"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; @@ -9,7 +10,6 @@ import { getQueryByLinkType, usePointToPointErrors, } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; -import ErrorIcon from "plugins/lime-plugin-mesh-wide/src/icons/errorIcon"; import { MacToMacLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; import { readableBytes } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { @@ -40,7 +40,7 @@ const BatmanDetail = ({
{name}{" "} - {errorsArray?.length > 0 && } + {errorsArray?.length > 0 && }
@@ -69,7 +69,7 @@ const WifiDetail = ({
{name}{" "} - {errorsArray?.length > 0 && } + {errorsArray?.length > 0 && }
@@ -183,7 +183,7 @@ const LinkFeatureDetail = ({ actual, reference }: LinkMapFeature) => { Link {i + 1}{" "} {errors && errors?.macToMacErrors[link.id]?.hasErrors ? ( - + ) : null}
diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx index 8f90a14fd..7dc84e848 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx @@ -1,14 +1,13 @@ import { Trans } from "@lingui/macro"; +import { FooterStatus } from "components/status/footer"; import { useToast } from "components/toast/toastProvider"; -import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; - export const MeshStatus = () => { const { showToast } = useToast(); return ( - { showToast({ @@ -31,6 +30,6 @@ export const MeshStatus = () => { Last update: 30 second ago
- + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx b/plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx deleted file mode 100644 index 0c606d9a2..000000000 --- a/plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const SuccessIcon = () => ; - -export default SuccessIcon; diff --git a/plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx b/plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx deleted file mode 100644 index 1417d3775..000000000 --- a/plugins/lime-plugin-mesh-wide/src/icons/errorIcon.tsx +++ /dev/null @@ -1,11 +0,0 @@ -const ErrorIcon = () => ( - - ! - -); - -export default ErrorIcon; diff --git a/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx b/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx index f9348b4d5..8da449a5f 100644 --- a/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx +++ b/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx @@ -1,7 +1,6 @@ import { Trans } from "@lingui/macro"; import { FullScreenModal } from "components/Modal/FullScreenModal"; -import Divider from "components/divider"; import { AddNewSectionBtn, @@ -30,10 +29,7 @@ const MeshWideConfigPage = () => { ))}
-
- - -
+ )} diff --git a/src/components/divider/index.tsx b/src/components/divider/index.tsx index f7cf81b71..8ea051254 100644 --- a/src/components/divider/index.tsx +++ b/src/components/divider/index.tsx @@ -1,9 +1,16 @@ type DividerColors = "gray" | "white"; -const Divider = ({ color = "gray" }: { color?: DividerColors }) => ( +type DividerSize = "full" | "short"; +const Divider = ({ + color = "gray", + width = "short", +}: { + color?: DividerColors; + width?: DividerSize; +}) => (
); diff --git a/src/components/icons/notification/rocket.tsx b/src/components/icons/notification/rocket.tsx new file mode 100644 index 000000000..030154c6f --- /dev/null +++ b/src/components/icons/notification/rocket.tsx @@ -0,0 +1,14 @@ +export const NotificationRocket = () => ( + + + +); diff --git a/src/components/icons/notification/warning.tsx b/src/components/icons/notification/warning.tsx new file mode 100644 index 000000000..fbc42394e --- /dev/null +++ b/src/components/icons/notification/warning.tsx @@ -0,0 +1,14 @@ +export const NotificationWarning = () => ( + + + +); diff --git a/src/components/icons/status.tsx b/src/components/icons/status.tsx new file mode 100644 index 000000000..684d146de --- /dev/null +++ b/src/components/icons/status.tsx @@ -0,0 +1,27 @@ +/** + * Contain icons related to status message. Minimal components usually using a simple character + */ + +export type StatusIcons = "success" | "warning"; + +export const StatusIcon = ({ status }: { status: StatusIcons }) => { + switch (status) { + case "warning": + return ; + case "success": + default: + return ; + } +}; + +export const Tick = () => ; + +export const Warning = () => ( + + ! + +); diff --git a/src/components/icons/teenny/chevrons.jsx b/src/components/icons/teenny/chevrons.jsx index 7a710f2a0..12ae771e8 100644 --- a/src/components/icons/teenny/chevrons.jsx +++ b/src/components/icons/teenny/chevrons.jsx @@ -29,3 +29,19 @@ export const ChevronDown = () => ( /> ); + +export const ChevronRight = () => ( + + + +); diff --git a/src/components/list-material/index.ts b/src/components/list-material/index.ts new file mode 100644 index 000000000..491ccf0c1 --- /dev/null +++ b/src/components/list-material/index.ts @@ -0,0 +1 @@ +export * from "./list"; diff --git a/src/components/list-material/list.tsx b/src/components/list-material/list.tsx new file mode 100644 index 000000000..dfdc1182a --- /dev/null +++ b/src/components/list-material/list.tsx @@ -0,0 +1,82 @@ +import { ComponentChildren } from "preact"; +import { useToggle } from "react-use"; + +import Divider from "components/divider"; +import { ChevronDown, ChevronRight } from "components/icons/teenny/chevrons"; + +interface IListItemProps { + leftComponent?: ComponentChildren; + rightComponent?: ComponentChildren; + title: string; + description?: string | ComponentChildren; + rightText?: string | ComponentChildren; + onClick?: (ev) => void; +} + +export const ListItem = ({ + leftComponent, + rightComponent, + title, + description, + rightText, + onClick, +}: IListItemProps) => { + return ( +
+
+ {leftComponent && ( +
+
{leftComponent}
+
+ )} +
+
+
{title}
+ {description && ( +

{description}

+ )} +
+
+
+ {rightText && ( +

+ {rightText} +

+ )} + {rightComponent && ( +
{rightComponent}
+ )} +
+
+ +
+ ); +}; + +export const ListItemCollapsible = ({ + initCollapsed = true, + rightComponent, + children, + ...rest +}: { + initCollapsed?: boolean; + children: ComponentChildren; +} & IListItemProps) => { + const [collapsed, toggleCollapsed] = useToggle(initCollapsed); + const _rightComponent = + rightComponent ?? collapsed ? : ; + + return ( + <> + + {!collapsed &&
{children}
} + + ); +}; diff --git a/src/components/notifications/notification.tsx b/src/components/notifications/notification.tsx new file mode 100644 index 000000000..41a80591d --- /dev/null +++ b/src/components/notifications/notification.tsx @@ -0,0 +1,51 @@ +import { ComponentChildren } from "preact"; + +import { NotificationRocket } from "components/icons/notification/rocket"; +import { NotificationWarning } from "components/icons/notification/warning"; + +type NotificationType = "warning" | "update"; + +const Notification = ({ + title, + children, + right, + onClick, + type = "update", +}: { + title: string; + children: ComponentChildren; + right?: string | ComponentChildren; + onClick?: () => void; + type?: NotificationType; +}) => { + let icon; + switch (type) { + case "warning": + icon = ; + break; + default: + icon = ; + break; + } + return ( +
+
{icon}
+
+
+
+ {title} +
+ {right &&
{right}
} +
+
{children}
+
+
+ ); +}; + +export default Notification; diff --git a/src/components/status/footer.tsx b/src/components/status/footer.tsx new file mode 100644 index 000000000..fa9f06eb5 --- /dev/null +++ b/src/components/status/footer.tsx @@ -0,0 +1,26 @@ +import Divider from "components/divider"; +import { + IStatusAndButton, + StatusAndButton, +} from "components/status/statusAndButton"; + +export type FooterProps = IStatusAndButton & { fixed?: boolean }; + +export const FooterStatus = ({ + children, + fixed = true, + ...rest +}: FooterProps) => { + return ( +
+ + + <>{children} + +
+ ); +}; diff --git a/src/components/status/statusAndButton.tsx b/src/components/status/statusAndButton.tsx new file mode 100644 index 000000000..632c3e87e --- /dev/null +++ b/src/components/status/statusAndButton.tsx @@ -0,0 +1,37 @@ +import { VNode } from "preact"; + +import { Button } from "components/buttons/button"; +import { IStatusMessage, StatusMessage } from "components/status/statusMessage"; + +export type IStatusAndButton = { + btn?: VNode | string; + btnCancel?: VNode | string; + onClick?: () => void; + onClickCancel?: () => void; +} & IStatusMessage; + +export const StatusAndButton = ({ + status, + children, + btn, + btnCancel, + onClick, + onClickCancel, +}: IStatusAndButton) => { + const containerClasses = + "flex flex-col items-center justify-center text-center bg-white py-5 gap-3"; + + return ( +
+ {children} +
+ {btnCancel && ( + + )} + {btn && } +
+
+ ); +}; diff --git a/src/components/status/statusMessage.tsx b/src/components/status/statusMessage.tsx new file mode 100644 index 000000000..6131f0ae9 --- /dev/null +++ b/src/components/status/statusMessage.tsx @@ -0,0 +1,22 @@ +import { VNode } from "preact"; + +import { StatusIcon, StatusIcons } from "components/icons/status"; + +export interface IStatusMessage { + status?: StatusIcons; + children: VNode | string; +} +export const StatusMessage = ({ + status, + children, + classes, +}: { + classes?: string; +} & IStatusMessage) => ( +
+ {status && } + {children} +
+); diff --git a/src/config.ts b/src/config.ts index 2d09e9a92..0fef6d70f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,6 +4,7 @@ import Fbw from "plugins/lime-plugin-fbw"; import Firmware from "plugins/lime-plugin-firmware"; import Locate from "plugins/lime-plugin-locate"; import MeshWide from "plugins/lime-plugin-mesh-wide"; +import MeshWideUpgrade from "plugins/lime-plugin-mesh-wide-upgrade"; import Metrics from "plugins/lime-plugin-metrics"; import NetworkAdmin from "plugins/lime-plugin-network-admin"; import NodeAdmin from "plugins/lime-plugin-node-admin"; @@ -27,4 +28,5 @@ export const plugins: LimePlugin[] = [ RemoteSupport, Pirania, Fbw, // fbw does not have menu item + MeshWideUpgrade, // Does not have menu item ]; diff --git a/src/utils/meshWideSyncCall.ts b/src/utils/meshWideSyncCall.ts new file mode 100644 index 000000000..130841147 --- /dev/null +++ b/src/utils/meshWideSyncCall.ts @@ -0,0 +1,133 @@ +import { MutationKey } from "@tanstack/query-core/src/types"; +import { UseMutationOptions, useMutation } from "@tanstack/react-query"; +import { useCallback } from "react"; + +import queryCache from "utils/queryCache"; +import { useSharedData } from "utils/useSharedData"; + +export class ParallelMutationError extends Error { + ip: string; + error: Error; + constructor(message: string, ip: string, error: Error) { + super(message); // Pass the message to the Error constructor + this.name = "ParallelMutationError"; // Set the name of the error + this.ip = ip; + this.error = error; + + // Set the prototype explicitly. + Object.setPrototypeOf(this, ParallelMutationError.prototype); + } +} + +interface IMutationFnVariables { + ip: string; + variables?: TVariables; +} + +export type SyncCallErrors = Array; +type SyncCallResults = TResult[]; +/** + * This object is used to store the results and errors of all the mutations calls. + * This data is stored on the queryCache using the useSharedData hook + * Storing isLoading there makes us able to avoid using a context to share the loading state + * between different hook instances. If we want to use a setState, we should wrap the hook + * with a context for the whole app + */ +type SyncCallCacheObject = { + errors: SyncCallErrors; + results: SyncCallResults; + isLoading?: boolean; +}; + +interface IMeshWideSyncCall { + mutationKey: MutationKey; + mutationFn: ({ + ip, + variables, + }: IMutationFnVariables) => Promise; + ips: string[]; + variables?: TVariables; + options?: UseMutationOptions< + TResult, + ParallelMutationError, + IMutationFnVariables + >; +} + +/** + * This hook is an implementation that will allow to call multiple mutations in parallel to different ips. + * + * In order to reuse the data on different parts, it implements caches using the queryCache. The results and errors for + * all the calls are stored using useSharedData query. + * + * In addition, is possible to acces to every single call accesing to the [...mutationKey, ip] key on the queryCache. + * + * @param mutationKey Mutation key to store the results and errors + * @param mutationFn Function that will be called for every ip + * @param ips List of ips to call the mutation + * @param variables Variables to pass to the mutation + * @param options Options for the mutation + */ +export const useMeshWideSyncCall = ({ + mutationKey, + mutationFn, + ips, + variables, + options, +}: IMeshWideSyncCall) => { + const { data: mutationResults, setData: setResults } = useSharedData< + SyncCallCacheObject + >([...mutationKey, "results"]); + + const { mutateAsync } = useMutation< + TResult, + ParallelMutationError, + IMutationFnVariables + >({ mutationFn, mutationKey, ...options }); + + const _callSingleMutation = useCallback( + async (ip: string) => { + try { + const result = await mutateAsync({ ip, variables }); + queryCache.setQueryData([...mutationKey, ip], result); + return result; + } catch (error) { + queryCache.setQueryData([...mutationKey, ip], error); + throw error; + } + }, + [mutationKey, mutateAsync, variables] + ); + + const callMutations = useCallback(async () => { + if (mutationResults?.isLoading) return mutationResults; + + setResults({ errors: [], results: [], isLoading: true }); + + const mutations = ips.map((ip) => { + return _callSingleMutation(ip); + }); + + const results = await Promise.allSettled(mutations); + + const errors: SyncCallErrors = results + .filter((result) => result.status === "rejected") + .map((result) => (result as PromiseRejectedResult).reason); + const successfulResults: SyncCallResults = results + .filter((result) => result.status === "fulfilled") + .map((result) => (result as PromiseFulfilledResult).value); + + setResults({ errors, results: successfulResults, isLoading: false }); + return { + errors, // This contains all the errors from the mutations + results: successfulResults, + }; + }, [_callSingleMutation, ips, mutationResults, setResults]); + + return { + callMutations, + errors: mutationResults?.errors, // This contains all the errors from the mutations + results: mutationResults?.results, + isLoading: mutationResults?.isLoading, + }; +}; diff --git a/src/utils/queries.js b/src/utils/queries.js index fd62ffc45..989b3ca82 100644 --- a/src/utils/queries.js +++ b/src/utils/queries.js @@ -18,13 +18,23 @@ export function useSession() { return useQuery(["session", "get"], getSession, { staleTime: Infinity }); } -function login({ username, password }) { +/** + * Login function + * @param username the username + * @param password the password + * @param customApi it accepts a custom instance of UhttpdService to be used for login to a custom API + */ +export function login({ username, password, customApi = null }) { + if (customApi) { + return customApi.login(username, password); + } return api.login(username, password); } export function useLogin() { return useMutation(login, { onSuccess: (res) => { + // @ts-ignore queryCache.setQueryData(["session", "get"], () => res.data); }, }); diff --git a/src/utils/uhttpd.service.js b/src/utils/uhttpd.service.js index 30a8d16b0..9229ff6ab 100644 --- a/src/utils/uhttpd.service.js +++ b/src/utils/uhttpd.service.js @@ -17,15 +17,19 @@ const parseResult = (result) => }); export class UhttpdService { - constructor() { - this.url = `${window.origin}/ubus`; + constructor(customIp) { + this.customIp = customIp; + this.url = customIp + ? `http://${customIp}/ubus` + : `${window.origin}/ubus`; this.jsonrpc = "2.0"; this.sec = 0; this.requestList = []; + this.sidKey = `sid-${customIp}`; // Store sid by url to be able to use multiple instances of uhttpdService } sid() { - const sid = sessionStorage.getItem("sid"); + const sid = sessionStorage.getItem(this.sidKey); return sid || UNAUTH_SESSION_ID; } @@ -64,7 +68,7 @@ export class UhttpdService { new Promise((res, rej) => { if (response.ubus_rpc_session) { sessionStorage.setItem( - "sid", + this.sidKey, response.ubus_rpc_session ); res(response); diff --git a/src/utils/useSharedData.ts b/src/utils/useSharedData.ts index 577686127..80e0a5866 100644 --- a/src/utils/useSharedData.ts +++ b/src/utils/useSharedData.ts @@ -1,3 +1,4 @@ +import { MutationKey } from "@tanstack/query-core/src/types"; import { useQuery } from "@tanstack/react-query"; import queryCache from "utils/queryCache"; @@ -8,7 +9,7 @@ import queryCache from "utils/queryCache"; * @param queryKey */ export const useSharedData = ( - queryKey: Array + queryKey: MutationKey ): { data: T | null; setData: (newData: T) => void } => { const { data } = useQuery(queryKey, () => null); const setData = (newData: T) => queryCache.setQueryData(queryKey, newData); From eb530bca47f373892ab6f853972da6b7d2f8c18d Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 7 May 2024 13:51:56 +0200 Subject: [PATCH 03/22] chore(meshupgrade): add mesh wide upgrade to the menu --- plugins/lime-plugin-mesh-wide-upgrade/index.ts | 2 ++ .../src/meshUpgradeMenu.tsx | 12 ++++++++++++ src/components/icons/teenny/globe.jsx | 14 ++++++++++++++ src/config.ts | 5 +++-- 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100755 plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx create mode 100644 src/components/icons/teenny/globe.jsx diff --git a/plugins/lime-plugin-mesh-wide-upgrade/index.ts b/plugins/lime-plugin-mesh-wide-upgrade/index.ts index 6481abc26..18c78799f 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/index.ts +++ b/plugins/lime-plugin-mesh-wide-upgrade/index.ts @@ -1,7 +1,9 @@ +import { MeshUpgradeMenu } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu"; import MeshUpgradePage from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage"; export default { name: "MeshWideUpgrade", page: MeshUpgradePage, + menu: MeshUpgradeMenu, isCommunityProtected: true, } as LimePlugin; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx new file mode 100755 index 000000000..cb5d73711 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx @@ -0,0 +1,12 @@ +import { Trans } from "@lingui/macro"; + +import { GlobeAmericasIcon } from "components/icons/teenny/globe"; + +export const MeshUpgradeMenu = () => ( + + + + Mesh Wide Upgrade + + +); diff --git a/src/components/icons/teenny/globe.jsx b/src/components/icons/teenny/globe.jsx new file mode 100644 index 000000000..aeb9599ab --- /dev/null +++ b/src/components/icons/teenny/globe.jsx @@ -0,0 +1,14 @@ +export const GlobeAmericasIcon = () => ( + + + +); diff --git a/src/config.ts b/src/config.ts index 0fef6d70f..c77a6ab9a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,7 +4,7 @@ import Fbw from "plugins/lime-plugin-fbw"; import Firmware from "plugins/lime-plugin-firmware"; import Locate from "plugins/lime-plugin-locate"; import MeshWide from "plugins/lime-plugin-mesh-wide"; -import MeshWideUpgrade from "plugins/lime-plugin-mesh-wide-upgrade"; +import MeshUpgrade from "plugins/lime-plugin-mesh-wide-upgrade"; import Metrics from "plugins/lime-plugin-metrics"; import NetworkAdmin from "plugins/lime-plugin-network-admin"; import NodeAdmin from "plugins/lime-plugin-node-admin"; @@ -24,9 +24,10 @@ export const plugins: LimePlugin[] = [ NodeAdmin, NetworkAdmin, Firmware, + MeshWide, + MeshUpgrade, ChangeNode, RemoteSupport, Pirania, Fbw, // fbw does not have menu item - MeshWideUpgrade, // Does not have menu item ]; From 4b4831a783d0e18920e76b8581289b4102932e30 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 7 May 2024 06:54:13 -0500 Subject: [PATCH 04/22] chore(rxPage): implement new landing (#388) Implement new landing page with - last internet path and internet status - Most active iface - Eth ports usage --- .eslintignore | 1 + .linguirc | 20 - lingui.config.js | 23 + package-lock.json | 610 ++++++++++++------ package.json | 8 +- plugins/lime-plugin-metrics/src/metricsApi.js | 8 +- .../lime-plugin-metrics/src/metricsQueries.js | 30 +- .../src/components/components.tsx | 30 + .../lime-plugin-rx/src/components/footer.tsx | 52 ++ .../src/components/internetPathChart.tsx | 212 ++++++ .../src/components/internetStatus.tsx | 56 ++ .../src/components/signalColor.tsx | 34 + .../lime-plugin-rx/src/icons/alignIcon.tsx | 7 + plugins/lime-plugin-rx/src/icons/pathIcon.tsx | 7 + .../lime-plugin-rx/src/icons/portsIcon.tsx | 7 + plugins/lime-plugin-rx/src/rxApi.js | 8 - plugins/lime-plugin-rx/src/rxApi.ts | 12 + plugins/lime-plugin-rx/src/rxEpics.js | 0 plugins/lime-plugin-rx/src/rxPage.js | 217 ------- plugins/lime-plugin-rx/src/rxPage.tsx | 25 + .../src/{rxQueries.js => rxQueries.ts} | 4 +- plugins/lime-plugin-rx/src/rxTypes.ts | 55 ++ .../src/sections/alignment.spec.tsx | 51 ++ .../lime-plugin-rx/src/sections/alignment.tsx | 125 ++++ .../src/sections/internetPath.spec.tsx | 87 +++ .../src/sections/internetPath.tsx | 135 ++++ .../src/sections/wired.spec.tsx | 139 ++++ plugins/lime-plugin-rx/src/sections/wired.tsx | 77 +++ src/assets/icons/AlterMundiLogo.svg | 50 ++ src/assets/icons/LibreRouterLogo.svg | 20 + src/components/elements/button.tsx | 57 ++ src/components/icons/circle.tsx | 7 + src/components/icons/circlecheckIcon.tsx | 7 + src/components/icons/globeIcon.tsx | 25 + src/components/icons/xmarkIcon.tsx | 7 + src/components/loading/loading-dots.tsx | 28 + src/utils/test_utils.js | 1 + tailwind.config.js | 4 + 38 files changed, 1810 insertions(+), 436 deletions(-) delete mode 100644 .linguirc create mode 100644 lingui.config.js create mode 100644 plugins/lime-plugin-rx/src/components/components.tsx create mode 100644 plugins/lime-plugin-rx/src/components/footer.tsx create mode 100644 plugins/lime-plugin-rx/src/components/internetPathChart.tsx create mode 100644 plugins/lime-plugin-rx/src/components/internetStatus.tsx create mode 100644 plugins/lime-plugin-rx/src/components/signalColor.tsx create mode 100644 plugins/lime-plugin-rx/src/icons/alignIcon.tsx create mode 100644 plugins/lime-plugin-rx/src/icons/pathIcon.tsx create mode 100644 plugins/lime-plugin-rx/src/icons/portsIcon.tsx delete mode 100644 plugins/lime-plugin-rx/src/rxApi.js create mode 100644 plugins/lime-plugin-rx/src/rxApi.ts delete mode 100644 plugins/lime-plugin-rx/src/rxEpics.js delete mode 100644 plugins/lime-plugin-rx/src/rxPage.js create mode 100644 plugins/lime-plugin-rx/src/rxPage.tsx rename plugins/lime-plugin-rx/src/{rxQueries.js => rxQueries.ts} (87%) create mode 100644 plugins/lime-plugin-rx/src/rxTypes.ts create mode 100644 plugins/lime-plugin-rx/src/sections/alignment.spec.tsx create mode 100644 plugins/lime-plugin-rx/src/sections/alignment.tsx create mode 100644 plugins/lime-plugin-rx/src/sections/internetPath.spec.tsx create mode 100644 plugins/lime-plugin-rx/src/sections/internetPath.tsx create mode 100644 plugins/lime-plugin-rx/src/sections/wired.spec.tsx create mode 100644 plugins/lime-plugin-rx/src/sections/wired.tsx create mode 100644 src/assets/icons/AlterMundiLogo.svg create mode 100644 src/assets/icons/LibreRouterLogo.svg create mode 100644 src/components/elements/button.tsx create mode 100644 src/components/icons/circle.tsx create mode 100644 src/components/icons/circlecheckIcon.tsx create mode 100644 src/components/icons/globeIcon.tsx create mode 100644 src/components/icons/xmarkIcon.tsx create mode 100644 src/components/loading/loading-dots.tsx diff --git a/.eslintignore b/.eslintignore index 18c0adf99..cc9f7f8f7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,4 @@ storybook-static build package-lock.json i18n +tailwind.config.js diff --git a/.linguirc b/.linguirc deleted file mode 100644 index a6af6a044..000000000 --- a/.linguirc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "locales": ["es", "pt", "en", "it"], - "catalogs": [{ - "path": "i18n/{locale}/messages", - "include": ["src", "plugins"] - }], - "format": "po", - "compileNamespace": "cjs", - "extractBabelOptions": { - "presets": [ - "preact", - "@babel/preset-typescript", - "@lingui/babel-preset-react" - ] - }, - "sourceLocale": "en", - "fallbackLocales": { - "default": "en" - } -} diff --git a/lingui.config.js b/lingui.config.js new file mode 100644 index 000000000..e3f877f9e --- /dev/null +++ b/lingui.config.js @@ -0,0 +1,23 @@ +/** @type {import('@lingui/conf').LinguiConfig} */ +module.exports = { + locales: ["es", "pt", "en", "it"], + catalogs: [ + { + path: "i18n/{locale}/messages", + include: ["src", "plugins"], + }, + ], + format: "po", + compileNamespace: "cjs", + extractBabelOptions: { + presets: [ + "preact", + "@babel/preset-typescript", + "@lingui/babel-preset-react", + ], + }, + sourceLocale: "en", + fallbackLocales: { + default: "en", + }, +}; diff --git a/package-lock.json b/package-lock.json index dbe932a19..bf10a44c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,10 +32,10 @@ "devDependencies": { "@babel/preset-react": "^7.18.6", "@lingui/babel-preset-react": "^2.9.2", - "@lingui/cli": "^3.14.0", - "@lingui/detect-locale": "^3.14.0", - "@lingui/loader": "^3.14.0", - "@lingui/macro": "^3.14.0", + "@lingui/cli": "^3.17.2", + "@lingui/detect-locale": "^3.17.2", + "@lingui/loader": "^3.17.2", + "@lingui/macro": "^3.17.2", "@storybook/addon-actions": "^6.5.12", "@storybook/addon-controls": "^6.5.12", "@storybook/addon-essentials": "^6.5.12", @@ -2263,16 +2263,21 @@ } }, "node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/@babel/template": { "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", @@ -2359,31 +2364,37 @@ "node": ">=0.1.90" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, "engines": { - "node": ">=10.0.0" + "node": ">=12" } }, - "node_modules/@endemolshinegroup/cosmiconfig-typescript-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz", - "integrity": "sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "peer": true, "dependencies": { - "lodash.get": "^4", - "make-error": "^1", - "ts-node": "^9", - "tslib": "^2" - }, + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, "engines": { "node": ">=10.0.0" - }, - "peerDependencies": { - "cosmiconfig": ">=6" } }, "node_modules/@eslint/eslintrc": { @@ -3501,18 +3512,18 @@ "dev": true }, "node_modules/@lingui/babel-plugin-extract-messages": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.14.0.tgz", - "integrity": "sha512-4lcDgVdjYiObuFdDwnAG3jJxS+d3YLq4i7qywlHgjIqteKUH01S3paJRXhZaPvLGl56HarSq0kt8Pymxw8lOrA==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.17.2.tgz", + "integrity": "sha512-Ovhf8a6dBlIZJFOqk6/+LRgQvSlVMol6hxvnVGLsCr/0xNcKlpGUAJ+bvY6NrmxZubpTvZqNkH23u5nEAdXtfg==", "dev": true, "dependencies": { - "@babel/generator": "^7.11.6", - "@babel/runtime": "^7.11.2", - "@lingui/conf": "^3.14.0", + "@babel/generator": "^7.20.14", + "@babel/runtime": "^7.20.13", + "@lingui/conf": "3.17.2", "mkdirp": "^1.0.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" } }, "node_modules/@lingui/babel-plugin-transform-js": { @@ -3544,18 +3555,20 @@ } }, "node_modules/@lingui/cli": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.14.0.tgz", - "integrity": "sha512-QZURsIf7A97tf28b/ffpeL0DekA6tBmcwnj4FBui1SbQqJw1d4IPg2bUM5VRn3/25vhqpi9Uhx5m9x7Vv8QfCQ==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.17.2.tgz", + "integrity": "sha512-8hPZOfwB7KZolZ01diUqtprKva1RNAUUNdzISN9pmAUGw9zCPRY/dlOvM6obZi8v0VC/JKrcadOs4Z8krIS2QQ==", "dev": true, "dependencies": { - "@babel/generator": "^7.11.6", - "@babel/parser": "^7.11.5", - "@babel/plugin-syntax-jsx": "^7.10.4", - "@babel/runtime": "^7.11.2", - "@babel/types": "^7.11.5", - "@lingui/babel-plugin-extract-messages": "^3.14.0", - "@lingui/conf": "^3.14.0", + "@babel/generator": "^7.20.14", + "@babel/parser": "^7.20.15", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/runtime": "^7.20.13", + "@babel/types": "^7.20.7", + "@lingui/babel-plugin-extract-messages": "3.17.2", + "@lingui/conf": "3.17.2", + "@lingui/core": "3.17.2", + "@messageformat/parser": "^5.0.0", "babel-plugin-macros": "^3.0.1", "bcp-47": "^1.0.7", "chalk": "^4.1.0", @@ -3568,7 +3581,6 @@ "glob": "^7.1.4", "inquirer": "^7.3.3", "make-plural": "^6.2.2", - "messageformat-parser": "^4.1.3", "micromatch": "4.0.2", "mkdirp": "^1.0.4", "node-gettext": "^3.0.0", @@ -3582,14 +3594,14 @@ "ramda": "^0.27.1" }, "bin": { - "lingui": "lingui.js" + "lingui": "build/lingui.js" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0", - "babel-plugin-macros": "2 || 3", + "babel-plugin-macros": "2 || 3", "typescript": "2 || 3 || 4" } }, @@ -3697,20 +3709,32 @@ } }, "node_modules/@lingui/conf": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.14.0.tgz", - "integrity": "sha512-5GMAbIRad9FavqYsfZCRAwjcOLzE7tONDJe9lSYE5SSJbbG01RI5kR5P0B84DUhTI6cGXau+1dAcP9K+JbEx+g==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.17.2.tgz", + "integrity": "sha512-q3ADfpMYCYMgiu/lrYOOvE3ptxXIqYhA1ozyAq6ynguL8ppqfyaTluLoHfVJVWxnTMI/es9s2W9Kg81QH+nuXQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.11.2", - "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", + "@babel/runtime": "^7.20.13", "chalk": "^4.1.0", - "cosmiconfig": "^7.0.0", + "cosmiconfig": "^8.0.0", + "cosmiconfig-typescript-loader": "^4.3.0", "jest-validate": "^26.5.2", "lodash.get": "^4.4.2" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" + }, + "peerDependencies": { + "ts-node": ">=10", + "typescript": ">=4" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "typescript": { + "optional": true + } } }, "node_modules/@lingui/conf/node_modules/@jest/types": { @@ -3730,9 +3754,9 @@ } }, "node_modules/@lingui/conf/node_modules/@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3750,6 +3774,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@lingui/conf/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@lingui/conf/node_modules/jest-get-type": { "version": "26.3.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", @@ -3798,65 +3848,64 @@ "dev": true }, "node_modules/@lingui/core": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.14.0.tgz", - "integrity": "sha512-ertREq9oi9B/umxpd/pInm9uFO8FLK2/0FXfDmMqvH5ydswWn/c9nY5YO4W1h4/8LWO45mewypOIyjoue4De1w==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.17.2.tgz", + "integrity": "sha512-YOd068NanznN8lLQqOKPlAY0ill3rrgmiAvPRKuYkrxzJMIHqlIFO/2Kcc/RH5vClOmLfg+wgR4rsHK/kLKelQ==", "dev": true, - "peer": true, "dependencies": { - "@babel/runtime": "^7.11.2", - "make-plural": "^6.2.2", - "messageformat-parser": "^4.1.3" + "@babel/runtime": "^7.20.13", + "@messageformat/parser": "^5.0.0", + "make-plural": "^6.2.2" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" } }, "node_modules/@lingui/detect-locale": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.14.0.tgz", - "integrity": "sha512-IELWULt9I+iyVlxGES21cXoOwTcPSIisElAmr3/KJlqvJ9zXT3s4w4Jxw9j5oHJjdxBDRkifwpnVmGd57wrmzg==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.17.2.tgz", + "integrity": "sha512-rqyO16lj05WRfBuppo++mPzB1fQBFDhGqEFz5X97CbWXYp6AadOIkrm+pbn114Y2Yumy9QI7Cm4Ptbfk7CXO3Q==", "dev": true, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" } }, "node_modules/@lingui/loader": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/loader/-/loader-3.14.0.tgz", - "integrity": "sha512-FH14MexRLM8tBgSL1oK5dbaUBbY0P85CSLTNwFqAtFFj8K8wWxfdq4+rIkp/kSD+eggKNDYV4G89N9/3bsm3gQ==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/loader/-/loader-3.17.2.tgz", + "integrity": "sha512-0sZj84y5nyAkDyCKYj3QxhePN1w4egIpUEZANlk3K0o0yo2kJXsmi9pnCeG8Z5/GniuWxF4C/JIJejRn226OmQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.11.2", - "@lingui/cli": "^3.14.0", - "@lingui/conf": "^3.14.0", - "loader-utils": "^2.0.0", - "ramda": "^0.27.1" + "@babel/runtime": "^7.20.13", + "@lingui/cli": "3.17.2", + "@lingui/conf": "3.17.2", + "loader-utils": "^2.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" }, "peerDependencies": { "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/@lingui/macro": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.14.0.tgz", - "integrity": "sha512-NxTRrhrZ/cUO9PX/4vWys90Ku58+ExxHuE30IuDnnDldWhWlOdycmjDt9tB+yIiUdFym/veSxBs+h114FzG5mA==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.17.2.tgz", + "integrity": "sha512-kk1ZtwYSx5Knu/5LsRGisTqfNoLIeVkJJPn6xjZXcItoxUgRsykyKb3BqCJwxqYUClz4i4A8Ld/aA4xBi4apRQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.11.2", - "@lingui/conf": "^3.14.0", + "@babel/runtime": "^7.20.13", + "@babel/types": "^7.20.7", + "@lingui/conf": "3.17.2", "ramda": "^0.27.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.0.0" }, "peerDependencies": { "@lingui/core": "^3.13.0", "@lingui/react": "^3.13.0", - "babel-plugin-macros": "2 || 3" + "babel-plugin-macros": "2 || 3" } }, "node_modules/@lingui/react": { @@ -3984,6 +4033,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/@messageformat/parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", + "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", + "dev": true, + "dependencies": { + "moo": "^0.5.1" + } + }, "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -8973,6 +9031,34 @@ "node": ">=10.13.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "peer": true + }, "node_modules/@types/aria-query": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", @@ -10846,7 +10932,8 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/argparse": { "version": "2.0.1", @@ -14757,6 +14844,21 @@ "node": ">=10" } }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", + "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", + "dev": true, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "ts-node": ">=10", + "typescript": ">=4" + } + }, "node_modules/cp-file": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", @@ -15144,7 +15246,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/critters-webpack-plugin": { "version": "2.5.0", @@ -16204,6 +16307,7 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "peer": true, "engines": { "node": ">=0.3.1" } @@ -25716,7 +25820,8 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/make-plural": { "version": "6.2.2", @@ -25996,12 +26101,6 @@ "node": ">= 8" } }, - "node_modules/messageformat-parser": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.3.tgz", - "integrity": "sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==", - "dev": true - }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -26923,6 +27022,12 @@ "node": ">=0.10.0" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "dev": true + }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -32296,7 +32401,8 @@ "node_modules/regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true }, "node_modules/regenerator-transform": { "version": "0.15.0", @@ -36258,29 +36364,57 @@ "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==" }, "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "peer": true, "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, - "engines": { - "node": ">=10.0.0" - }, "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" } }, "node_modules/ts-pnp": { @@ -37165,6 +37299,13 @@ "integrity": "sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==", "dev": true }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "peer": true + }, "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -39271,6 +39412,7 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "peer": true, "engines": { "node": ">=6" } @@ -40802,11 +40944,18 @@ } }, "@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", + "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + } } }, "@babel/template": { @@ -40876,24 +41025,35 @@ "dev": true, "optional": true }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "peer": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "peer": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, "@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, - "@endemolshinegroup/cosmiconfig-typescript-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz", - "integrity": "sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==", - "dev": true, - "requires": { - "lodash.get": "^4", - "make-error": "^1", - "ts-node": "^9", - "tslib": "^2" - } - }, "@eslint/eslintrc": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", @@ -41804,14 +41964,14 @@ "dev": true }, "@lingui/babel-plugin-extract-messages": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.14.0.tgz", - "integrity": "sha512-4lcDgVdjYiObuFdDwnAG3jJxS+d3YLq4i7qywlHgjIqteKUH01S3paJRXhZaPvLGl56HarSq0kt8Pymxw8lOrA==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.17.2.tgz", + "integrity": "sha512-Ovhf8a6dBlIZJFOqk6/+LRgQvSlVMol6hxvnVGLsCr/0xNcKlpGUAJ+bvY6NrmxZubpTvZqNkH23u5nEAdXtfg==", "dev": true, "requires": { - "@babel/generator": "^7.11.6", - "@babel/runtime": "^7.11.2", - "@lingui/conf": "^3.14.0", + "@babel/generator": "^7.20.14", + "@babel/runtime": "^7.20.13", + "@lingui/conf": "3.17.2", "mkdirp": "^1.0.4" } }, @@ -41838,18 +41998,20 @@ } }, "@lingui/cli": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.14.0.tgz", - "integrity": "sha512-QZURsIf7A97tf28b/ffpeL0DekA6tBmcwnj4FBui1SbQqJw1d4IPg2bUM5VRn3/25vhqpi9Uhx5m9x7Vv8QfCQ==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.17.2.tgz", + "integrity": "sha512-8hPZOfwB7KZolZ01diUqtprKva1RNAUUNdzISN9pmAUGw9zCPRY/dlOvM6obZi8v0VC/JKrcadOs4Z8krIS2QQ==", "dev": true, "requires": { - "@babel/generator": "^7.11.6", - "@babel/parser": "^7.11.5", - "@babel/plugin-syntax-jsx": "^7.10.4", - "@babel/runtime": "^7.11.2", - "@babel/types": "^7.11.5", - "@lingui/babel-plugin-extract-messages": "^3.14.0", - "@lingui/conf": "^3.14.0", + "@babel/generator": "^7.20.14", + "@babel/parser": "^7.20.15", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/runtime": "^7.20.13", + "@babel/types": "^7.20.7", + "@lingui/babel-plugin-extract-messages": "3.17.2", + "@lingui/conf": "3.17.2", + "@lingui/core": "3.17.2", + "@messageformat/parser": "^5.0.0", "babel-plugin-macros": "^3.0.1", "bcp-47": "^1.0.7", "chalk": "^4.1.0", @@ -41862,7 +42024,6 @@ "glob": "^7.1.4", "inquirer": "^7.3.3", "make-plural": "^6.2.2", - "messageformat-parser": "^4.1.3", "micromatch": "4.0.2", "mkdirp": "^1.0.4", "node-gettext": "^3.0.0", @@ -41957,15 +42118,15 @@ } }, "@lingui/conf": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.14.0.tgz", - "integrity": "sha512-5GMAbIRad9FavqYsfZCRAwjcOLzE7tONDJe9lSYE5SSJbbG01RI5kR5P0B84DUhTI6cGXau+1dAcP9K+JbEx+g==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.17.2.tgz", + "integrity": "sha512-q3ADfpMYCYMgiu/lrYOOvE3ptxXIqYhA1ozyAq6ynguL8ppqfyaTluLoHfVJVWxnTMI/es9s2W9Kg81QH+nuXQ==", "dev": true, "requires": { - "@babel/runtime": "^7.11.2", - "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", + "@babel/runtime": "^7.20.13", "chalk": "^4.1.0", - "cosmiconfig": "^7.0.0", + "cosmiconfig": "^8.0.0", + "cosmiconfig-typescript-loader": "^4.3.0", "jest-validate": "^26.5.2", "lodash.get": "^4.4.2" }, @@ -41984,9 +42145,9 @@ } }, "@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -41998,6 +42159,18 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, + "cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "requires": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + } + }, "jest-get-type": { "version": "26.3.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", @@ -42039,44 +42212,43 @@ } }, "@lingui/core": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.14.0.tgz", - "integrity": "sha512-ertREq9oi9B/umxpd/pInm9uFO8FLK2/0FXfDmMqvH5ydswWn/c9nY5YO4W1h4/8LWO45mewypOIyjoue4De1w==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.17.2.tgz", + "integrity": "sha512-YOd068NanznN8lLQqOKPlAY0ill3rrgmiAvPRKuYkrxzJMIHqlIFO/2Kcc/RH5vClOmLfg+wgR4rsHK/kLKelQ==", "dev": true, - "peer": true, "requires": { - "@babel/runtime": "^7.11.2", - "make-plural": "^6.2.2", - "messageformat-parser": "^4.1.3" + "@babel/runtime": "^7.20.13", + "@messageformat/parser": "^5.0.0", + "make-plural": "^6.2.2" } }, "@lingui/detect-locale": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.14.0.tgz", - "integrity": "sha512-IELWULt9I+iyVlxGES21cXoOwTcPSIisElAmr3/KJlqvJ9zXT3s4w4Jxw9j5oHJjdxBDRkifwpnVmGd57wrmzg==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.17.2.tgz", + "integrity": "sha512-rqyO16lj05WRfBuppo++mPzB1fQBFDhGqEFz5X97CbWXYp6AadOIkrm+pbn114Y2Yumy9QI7Cm4Ptbfk7CXO3Q==", "dev": true }, "@lingui/loader": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/loader/-/loader-3.14.0.tgz", - "integrity": "sha512-FH14MexRLM8tBgSL1oK5dbaUBbY0P85CSLTNwFqAtFFj8K8wWxfdq4+rIkp/kSD+eggKNDYV4G89N9/3bsm3gQ==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/loader/-/loader-3.17.2.tgz", + "integrity": "sha512-0sZj84y5nyAkDyCKYj3QxhePN1w4egIpUEZANlk3K0o0yo2kJXsmi9pnCeG8Z5/GniuWxF4C/JIJejRn226OmQ==", "dev": true, "requires": { - "@babel/runtime": "^7.11.2", - "@lingui/cli": "^3.14.0", - "@lingui/conf": "^3.14.0", - "loader-utils": "^2.0.0", - "ramda": "^0.27.1" + "@babel/runtime": "^7.20.13", + "@lingui/cli": "3.17.2", + "@lingui/conf": "3.17.2", + "loader-utils": "^2.0.0" } }, "@lingui/macro": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.14.0.tgz", - "integrity": "sha512-NxTRrhrZ/cUO9PX/4vWys90Ku58+ExxHuE30IuDnnDldWhWlOdycmjDt9tB+yIiUdFym/veSxBs+h114FzG5mA==", + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.17.2.tgz", + "integrity": "sha512-kk1ZtwYSx5Knu/5LsRGisTqfNoLIeVkJJPn6xjZXcItoxUgRsykyKb3BqCJwxqYUClz4i4A8Ld/aA4xBi4apRQ==", "dev": true, "requires": { - "@babel/runtime": "^7.11.2", - "@lingui/conf": "^3.14.0", + "@babel/runtime": "^7.20.13", + "@babel/types": "^7.20.7", + "@lingui/conf": "3.17.2", "ramda": "^0.27.1" } }, @@ -42177,6 +42349,15 @@ "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", "dev": true }, + "@messageformat/parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", + "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", + "dev": true, + "requires": { + "moo": "^0.5.1" + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -45820,6 +46001,34 @@ "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true }, + "@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "peer": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "peer": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "peer": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "peer": true + }, "@types/aria-query": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", @@ -47358,7 +47567,8 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "dev": true, + "peer": true }, "argparse": { "version": "2.0.1", @@ -50387,6 +50597,13 @@ "yaml": "^1.10.0" } }, + "cosmiconfig-typescript-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", + "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", + "dev": true, + "requires": {} + }, "cp-file": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", @@ -50710,7 +50927,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "dev": true, + "peer": true }, "critters-webpack-plugin": { "version": "2.5.0", @@ -51534,7 +51752,8 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "dev": true, + "peer": true }, "diff-sequences": { "version": "29.0.0", @@ -58927,7 +59146,8 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "peer": true }, "make-plural": { "version": "6.2.2", @@ -59161,12 +59381,6 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, - "messageformat-parser": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.3.tgz", - "integrity": "sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==", - "dev": true - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -59887,6 +60101,12 @@ "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true }, + "moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "dev": true + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -63980,7 +64200,8 @@ "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true }, "regenerator-transform": { "version": "0.15.0", @@ -67138,17 +67359,34 @@ "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==" }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "peer": true, "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" + }, + "dependencies": { + "acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "peer": true + } } }, "ts-pnp": { @@ -67802,6 +68040,13 @@ "integrity": "sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "peer": true + }, "v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -69496,7 +69741,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "dev": true, + "peer": true }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index da10654c9..590afb6f3 100644 --- a/package.json +++ b/package.json @@ -31,10 +31,10 @@ "devDependencies": { "@babel/preset-react": "^7.18.6", "@lingui/babel-preset-react": "^2.9.2", - "@lingui/cli": "^3.14.0", - "@lingui/detect-locale": "^3.14.0", - "@lingui/loader": "^3.14.0", - "@lingui/macro": "^3.14.0", + "@lingui/cli": "^3.17.2", + "@lingui/detect-locale": "^3.17.2", + "@lingui/loader": "^3.17.2", + "@lingui/macro": "^3.17.2", "@storybook/addon-actions": "^6.5.12", "@storybook/addon-controls": "^6.5.12", "@storybook/addon-essentials": "^6.5.12", diff --git a/plugins/lime-plugin-metrics/src/metricsApi.js b/plugins/lime-plugin-metrics/src/metricsApi.js index 39a068097..46a9ded02 100644 --- a/plugins/lime-plugin-metrics/src/metricsApi.js +++ b/plugins/lime-plugin-metrics/src/metricsApi.js @@ -1,12 +1,16 @@ import api from "utils/uhttpd.service"; export const getMetrics = (ip) => { - console.log("getting metrics for ", ip); return api.call("lime-metrics", "get_metrics", { target: ip }); }; export const getGateway = () => api.call("lime-metrics", "get_gateway", {}).then((res) => res.gateway); -export const getPath = () => +export const getPath = async () => api.call("lime-metrics", "get_path", {}).then((res) => res.path); + +export const getLoss = async (ip) => + api + .call("lime-metrics", "get_loss", { target: ip }) + .then((res) => +res.loss); diff --git a/plugins/lime-plugin-metrics/src/metricsQueries.js b/plugins/lime-plugin-metrics/src/metricsQueries.js index 4700871f6..22cd030f0 100644 --- a/plugins/lime-plugin-metrics/src/metricsQueries.js +++ b/plugins/lime-plugin-metrics/src/metricsQueries.js @@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query"; import queryCache from "utils/queryCache"; -import { getGateway, getMetrics, getPath } from "./metricsApi"; +import { getGateway, getLoss, getMetrics, getPath } from "./metricsApi"; export function useMetrics(ip, params) { return useQuery(["lime-metrics", "get_metrics", ip], () => getMetrics(ip), { @@ -42,3 +42,31 @@ export function useGateway(params) { export function usePath(params) { return useQuery(["lime-metrics", "get_path"], getPath, params); } + +export function useLoss(ip, params) { + return useQuery(["lime-metrics", "get_loss", ip], () => getLoss(ip), { + retry: false, + ...params, + }); +} + +export const getAllLoss = async (nodes) => { + let losses = {}; + for (const node of nodes) { + const queryKey = ["lime-metrics", "get_loss", node.ip]; + await queryCache.invalidateQueries(queryKey); + losses[node.ip] = await queryCache.fetchQuery(queryKey); + } + return losses; +}; + +export function usePathLoss(nodes, params) { + return useQuery( + ["lime-metrics", "get_loss", nodes], + (query) => getAllLoss(query.queryKey[2]), + { + retry: false, + ...params, + } + ); +} diff --git a/plugins/lime-plugin-rx/src/components/components.tsx b/plugins/lime-plugin-rx/src/components/components.tsx new file mode 100644 index 000000000..05905eae8 --- /dev/null +++ b/plugins/lime-plugin-rx/src/components/components.tsx @@ -0,0 +1,30 @@ +import { ComponentChildren, FunctionalComponent } from "preact"; + +export const IconsClassName = "h-14 w-14"; + +interface SectionTitleProps { + children?: ComponentChildren; + icon: ComponentChildren; +} + +export const SectionTitle: FunctionalComponent = ({ + children, + icon, +}) => { + return ( +
+ {icon} +

{children}

+
+ ); +}; + +export const Section = ({ ...props }) => { + return ( +
+
+ {props.children} +
+
+ ); +}; diff --git a/plugins/lime-plugin-rx/src/components/footer.tsx b/plugins/lime-plugin-rx/src/components/footer.tsx new file mode 100644 index 000000000..3d766cea5 --- /dev/null +++ b/plugins/lime-plugin-rx/src/components/footer.tsx @@ -0,0 +1,52 @@ +import { Trans } from "@lingui/macro"; + +export const Footer = () => { + const imgClass = "h-16"; + return ( +
+
+ +
+
+
+ Need support? +
+
+ + Join{" "} + + foro.librerouter.org + + +
+
+ + Visit{" "} + + docs.altermundi.net + + +
+
+
+ +
+
+ ); +}; diff --git a/plugins/lime-plugin-rx/src/components/internetPathChart.tsx b/plugins/lime-plugin-rx/src/components/internetPathChart.tsx new file mode 100644 index 000000000..7b122bae6 --- /dev/null +++ b/plugins/lime-plugin-rx/src/components/internetPathChart.tsx @@ -0,0 +1,212 @@ +import { Trans } from "@lingui/macro"; +import React from "react"; + +import { GlobeIcon } from "components/icons/globeIcon"; +import LoadingDots from "components/loading/loading-dots"; + +import { useLoss } from "plugins/lime-plugin-metrics/src/metricsQueries"; + +type Node = { + ip: string; + hostname: string; +}; + +type Props = { + nodes: Node[]; + internet: boolean; +}; + +const circleRadius = 10; // Size of the circle +const circleSpacing = 40; // Distance between circles + +const calcLinePositionByIndex = (index) => { + const y1 = index * circleSpacing + circleRadius + circleRadius; + const y2 = y1 + (circleSpacing - circleRadius - circleRadius); + return { y1, y2 }; +}; + +interface CircleProps { + key?: number; + ip: string; + index: number; + text: any; // type error with Trans component + internet?: boolean; + isLoading?: boolean; + className?: string; +} + +const Circle = ({ + index, + className, + text, + internet = false, + isLoading = false, +}: CircleProps) => { + const innerCircleRadius = circleRadius - 6; + const textSpacingY = (index: number) => + index * circleSpacing + circleRadius + 5; + const textSpacingX = circleSpacing * 1.5; + const cy = index * circleSpacing + circleRadius; + + return ( + + {internet ? ( + + ) : ( + <> + + + + )} + + <> + {text} {isLoading && } + + + + ); +}; + +const NodeHop = ({ ip, index, text }: CircleProps) => { + const { data: loss, isFetching } = useLoss(ip, { + refetchOnWindowFocus: false, + enabled: false, + initialData: 0, + }); + + // For some reason the stirng interpolation did not work well here. + // So is need to declare each variable + const goodPathStroke = "stroke-primary-dark"; + const goodPathColor = "fill-primary-dark"; + const badPathStroke = "stroke-danger"; + const badPathColor = "fill-danger"; + + const circleColor = loss === 100 ? badPathColor : goodPathColor; + const lineColor = loss === 100 ? badPathStroke : goodPathStroke; + + const { y1, y2 } = calcLinePositionByIndex(index - 1); + return ( + <> + {y1 >= 0 && ( + + )} + + + ); +}; + +const InternetLastHop = ({ + ip, + index, + internet, +}: { + ip: string; + index: number; + internet: boolean; +}) => { + const { isFetching, data: loss } = useLoss(ip, { + refetchOnWindowFocus: false, + enabled: false, + }); + + const goodPathColor = "stroke-internet"; + const goodIconColor = "fill-internet"; + const badPathColor = "stroke-danger"; + const badIconColor = "fill-danger"; + const disabledPathColor = "stroke-gray-400"; + const disabledIconColor = "fill-gray-400"; + + const internetIcon = internet + ? goodIconColor + : !internet && loss === 100 + ? badIconColor + : disabledIconColor; + const internetPath = internet + ? goodPathColor + : !internet && loss === 100 + ? badPathColor + : disabledPathColor; + + const { y1, y2 } = calcLinePositionByIndex(index - 1); + + const internetText = Internet; + + return ( + <> + + + + ); +}; + +function LineChart({ nodes, internet }: Props) { + if (nodes === undefined) return; + + const totalHeight = (nodes.length + 1) * circleSpacing - circleRadius * 2; + + return ( + + {nodes.map((node: Node, index: number) => ( + + ))} + + + ); +} + +export default LineChart; diff --git a/plugins/lime-plugin-rx/src/components/internetStatus.tsx b/plugins/lime-plugin-rx/src/components/internetStatus.tsx new file mode 100644 index 000000000..9b51589d8 --- /dev/null +++ b/plugins/lime-plugin-rx/src/components/internetStatus.tsx @@ -0,0 +1,56 @@ +import { Trans } from "@lingui/macro"; + +import { Circle } from "components/icons/circle"; +import { CirclecheckIcon } from "components/icons/circlecheckIcon"; +import { XmarkIcon } from "components/icons/xmarkIcon"; + +import { IGetInternetStatus } from "plugins/lime-plugin-rx/src/rxTypes"; + +export const InternetStatus = ({ data }: { data: IGetInternetStatus }) => { + const checkIconClass = "h-10 w-10 fill-primary-dark "; + const xmarkIconClass = "h-10 w-10 fill-danger "; + const loadiIconClass = "h-10 w-10 stroke-disabled"; + + return ( +
+

+ + Internet +
+ connection +
+

+ {Object.entries(data).map(([key, value]) => { + if (key !== "status") { + return ( +
+ {value.working === null ? ( + + ) : value.working ? ( + + ) : ( + + )} +
+ {key} +
+
+ ); + } + })} +
+ ); +}; diff --git a/plugins/lime-plugin-rx/src/components/signalColor.tsx b/plugins/lime-plugin-rx/src/components/signalColor.tsx new file mode 100644 index 000000000..9b7090410 --- /dev/null +++ b/plugins/lime-plugin-rx/src/components/signalColor.tsx @@ -0,0 +1,34 @@ +import { useEffect } from "preact/hooks"; +import colorScale from "simple-color-scale"; + +import { useCommunitySettings } from "utils/queries"; + +export const SignalColor = ({ + signal, + className, +}: { + signal: number; + className: string; +}) => { + const { data: communitySettings } = useCommunitySettings(); + + useEffect(() => { + colorScale.setConfig({ + outputStart: 1, + outputEnd: Number(communitySettings?.bad_signal) * -1, + inputStart: Number(communitySettings?.good_signal) * -1, + inputEnd: Number(communitySettings?.bad_signal) * -1 + 10, + }); + }, [communitySettings]); + + return ( + + {signal} + + ); +}; diff --git a/plugins/lime-plugin-rx/src/icons/alignIcon.tsx b/plugins/lime-plugin-rx/src/icons/alignIcon.tsx new file mode 100644 index 000000000..e71916c0d --- /dev/null +++ b/plugins/lime-plugin-rx/src/icons/alignIcon.tsx @@ -0,0 +1,7 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const AlignIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/plugins/lime-plugin-rx/src/icons/pathIcon.tsx b/plugins/lime-plugin-rx/src/icons/pathIcon.tsx new file mode 100644 index 000000000..44a7cef06 --- /dev/null +++ b/plugins/lime-plugin-rx/src/icons/pathIcon.tsx @@ -0,0 +1,7 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const PathIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/plugins/lime-plugin-rx/src/icons/portsIcon.tsx b/plugins/lime-plugin-rx/src/icons/portsIcon.tsx new file mode 100644 index 000000000..bc237cc25 --- /dev/null +++ b/plugins/lime-plugin-rx/src/icons/portsIcon.tsx @@ -0,0 +1,7 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const PortsIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/plugins/lime-plugin-rx/src/rxApi.js b/plugins/lime-plugin-rx/src/rxApi.js deleted file mode 100644 index b9252e5c7..000000000 --- a/plugins/lime-plugin-rx/src/rxApi.js +++ /dev/null @@ -1,8 +0,0 @@ -import api from "utils/uhttpd.service"; - -export const getNodeStatus = () => { - return api.call("lime-utils", "get_node_status", {}); -}; - -export const getInternetStatus = () => - api.call("lime-metrics", "get_internet_status", {}); diff --git a/plugins/lime-plugin-rx/src/rxApi.ts b/plugins/lime-plugin-rx/src/rxApi.ts new file mode 100644 index 000000000..b53fc4f0b --- /dev/null +++ b/plugins/lime-plugin-rx/src/rxApi.ts @@ -0,0 +1,12 @@ +import { + IGetInternetStatus, + StatusResponse, +} from "plugins/lime-plugin-rx/src/rxTypes"; + +import api from "utils/uhttpd.service"; + +export const getNodeStatus = (): Promise => + api.call("lime-utils", "get_node_status", {}); + +export const getInternetStatus = (): Promise => + api.call("lime-metrics", "get_internet_status", {}); diff --git a/plugins/lime-plugin-rx/src/rxEpics.js b/plugins/lime-plugin-rx/src/rxEpics.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/plugins/lime-plugin-rx/src/rxPage.js b/plugins/lime-plugin-rx/src/rxPage.js deleted file mode 100644 index 710c066ac..000000000 --- a/plugins/lime-plugin-rx/src/rxPage.js +++ /dev/null @@ -1,217 +0,0 @@ -import { Trans, plural } from "@lingui/macro"; - -import { Box } from "components/box"; - -import { useBatHost, useBoardData } from "utils/queries"; - -import { useInternetStatus, useNodeStatus } from "./rxQueries"; - -function stripIface(hostIface) { - return hostIface.split("_wlan")[0].replace("_", "-"); -} - -const toHHMMSS = (seconds, plus) => { - let secNum = parseInt(seconds, 10) + plus; - let days = Math.floor(secNum / 86400); - let hours = Math.floor(secNum / 3600) % 24; - let mins = Math.floor(secNum / 60) % 60; - let secs = secNum % 60; - const daysText = days - ? plural(days, { one: "# day", other: "# days" }) - : null; - const hoursText = hours - ? plural(hours, { one: "# hour", other: "# hours" }) - : null; - const minsText = mins - ? plural(mins, { one: "# minute", other: "# minutes" }) - : null; - const secsText = secs - ? plural(secs, { one: "# second", other: "# seconds" }) - : null; - const allTexts = [daysText, hoursText, minsText, secsText]; - return allTexts.filter((x) => x !== null).join(", "); -}; - -const SystemBox = ({ uptime, firmwareVersion, boardModel }) => { - // The plus was used because the refetch interval was every two seconds for trying to not refetch timer every two sec. - // But, this is buggie and advance the timer more that what is needed. At my opinion (kon) is better to refetch every - // two seconds and check a more elegant way to resolve this - let actualUptime = toHHMMSS(uptime, 0); - - return ( - System}> - - - Uptime - {" "} - {actualUptime}
-
- - - Device - {" "} - {boardModel} -
-
- - - Firmware{" "} - - {firmwareVersion} -
-
-
- ); -}; - -const MostActiveBox = ({ node, changeNode }) => { - const use_most_active = !!node.most_active?.iface; - const { data: bathost } = useBatHost( - node.most_active?.station_mac, - node.most_active?.iface, - { enabled: !!node.most_active } - ); - - if (!use_most_active) { - return ; - } - - return ( - Most Active}> - - {node.most_active.signal} - - {bathost && bathost.hostname ? ( - changeNode(bathost.hostname)} - > - {stripIface(bathost.hostname)} - - ) : ( - - Fetching name - - )} -
- - Interface{" "} - - {node.most_active.iface.split("-")[0]} -
- - Traffic{" "} - {" "} - {Math.round( - (node.most_active.rx_bytes + node.most_active.tx_bytes) / - 1024 / - 1024 - )} - MB -
- - ); -}; - -const Page = ({}) => { - const { data: boardData, isLoading: loadingBoardData } = useBoardData(); - - const { data: nodeStatusData, isLoading } = useNodeStatus({}); - const { data: internet } = useInternetStatus(); - - function loading(option, nodeData) { - if (!option && !loadingBoardData) { - return nodeStatus(nodeData); - } - return ( -

- Loading node status... -

- ); - } - - function _changeNode(hostname) { - window.location.href = `http://${hostname}`; - } - - function nodeStatus(node) { - if (node.hostname) { - return ( -
- - - - - Internet connection}> - - - {" "} - {internet.IPv4.working === true ? ( - - ) : ( - - )}{" "} - IPv4{" "} - - - {" "} - {internet.IPv6.working === true ? ( - - ) : ( - - )}{" "} - IPv6{" "} - - - {" "} - {internet.DNS.working === true ? ( - - ) : ( - - )}{" "} - DNS{" "} - - - - - IP Addresses}> - {node.ips.map((ip, key) => ( - - IPv{ip.version} {ip.address} -
-
- ))} -
-
- ); - } - } - - return ( -
- {loading(isLoading, nodeStatusData)} -
- ); -}; - -export default Page; - -// export const mapStateToProps = (state) => ({ -// nodeData: getNodeData(state), -// isLoading: isLoading(state), -// }); -// -// export const mapDispatchToProps = (dispatch) => ({ -// getNodeStatusTimer: bindActionCreators(getNodeStatusTimer, dispatch), -// getNodeStatus: bindActionCreators(getNodeStatus, dispatch), -// stopTimer: bindActionCreators(stopTimer, dispatch), -// }); -// -// export default connect(mapStateToProps, mapDispatchToProps)(Page); diff --git a/plugins/lime-plugin-rx/src/rxPage.tsx b/plugins/lime-plugin-rx/src/rxPage.tsx new file mode 100644 index 000000000..355243d25 --- /dev/null +++ b/plugins/lime-plugin-rx/src/rxPage.tsx @@ -0,0 +1,25 @@ +import { Fragment } from "preact"; + +import { Footer } from "plugins/lime-plugin-rx/src/components/footer"; +import { Alignment } from "plugins/lime-plugin-rx/src/sections/alignment"; +import { InternetPath } from "plugins/lime-plugin-rx/src/sections/internetPath"; +import { Wired } from "plugins/lime-plugin-rx/src/sections/wired"; + +const Page = ({}) => { + return ( + +
+ + + +
+
+
+ ); +}; + +export default Page; diff --git a/plugins/lime-plugin-rx/src/rxQueries.js b/plugins/lime-plugin-rx/src/rxQueries.ts similarity index 87% rename from plugins/lime-plugin-rx/src/rxQueries.js rename to plugins/lime-plugin-rx/src/rxQueries.ts index 6a94a9b52..41a3b298a 100644 --- a/plugins/lime-plugin-rx/src/rxQueries.js +++ b/plugins/lime-plugin-rx/src/rxQueries.ts @@ -4,7 +4,7 @@ import { getInternetStatus, getNodeStatus } from "./rxApi"; const refetchInterval = 2000; -export function useNodeStatus(params) { +export function useNodeStatus(params?) { return useQuery(["lime-rx", "node-status"], getNodeStatus, { enabled: true, refetchInterval, @@ -12,7 +12,7 @@ export function useNodeStatus(params) { }); } -export function useInternetStatus(params) { +export function useInternetStatus(params?) { return useQuery(["lime-rx", "internet-status"], getInternetStatus, { placeholderData: { IPv4: { working: null }, diff --git a/plugins/lime-plugin-rx/src/rxTypes.ts b/plugins/lime-plugin-rx/src/rxTypes.ts new file mode 100644 index 000000000..6a5ff82a2 --- /dev/null +++ b/plugins/lime-plugin-rx/src/rxTypes.ts @@ -0,0 +1,55 @@ +interface DeviceStatus { + version: string; + address: string; +} + +export interface SwitchStatus { + device: string; + num: number; + role: string; + link: string; +} + +interface MostActive { + rx_short_gi: boolean; + station_mac: string; + tx_bytes: number; + rx_vht: boolean; + rx_mhz: number; + rx_40mhz: boolean; + tx_packets: number; + tx_mhz: number; + rx_packets: number; + rx_ht: boolean; + tx_mcs: number; + noise: number; + rx_mcs: number; + chains: number[]; + rx_bytes: number; + tx_ht: boolean; + iface: string; + tx_rate: number; + inactive: number; + tx_short_gi: boolean; + tx_40mhz: boolean; + expected_throughput: number; + tx_vht: boolean; + rx_rate: number; + signal: number; +} + +export interface StatusResponse { + ips: DeviceStatus[]; + hostname: string; + switch_status: SwitchStatus[]; + status: string; + uptime: string; + most_active: MostActive; +} + +export interface IGetInternetStatus { + DNS: { working: boolean }; + IPv6: { working: boolean }; + IPv4: { working: boolean }; + status: string; +} diff --git a/plugins/lime-plugin-rx/src/sections/alignment.spec.tsx b/plugins/lime-plugin-rx/src/sections/alignment.spec.tsx new file mode 100644 index 000000000..e630d89a6 --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/alignment.spec.tsx @@ -0,0 +1,51 @@ +import "@testing-library/jest-dom/extend-expect"; +import { screen } from "@testing-library/preact"; + +import { getNodeStatus } from "plugins/lime-plugin-rx/src/rxApi"; +import { Alignment } from "plugins/lime-plugin-rx/src/sections/alignment"; +import { mock_node_status } from "plugins/lime-plugin-rx/src/sections/wired.spec"; + +import { render } from "utils/test_utils"; + +jest.mock("plugins/lime-plugin-rx/src/rxApi"); +const mockedFoo = jest.mocked(getNodeStatus); + +describe("align page", () => { + beforeEach(() => { + mockedFoo.mockImplementation(async () => mock_node_status); + }); + + it("Shows two alignment button", async () => { + render(); + const button = await screen.findByText(/^Check/i); + expect(button).toBeInTheDocument(); + }); + + it("Shows signal and chains", async () => { + render(); + const signal = mock_node_status.most_active.signal; + const signalDiv = await screen.findByText(signal); + expect(signalDiv).toBeInTheDocument(); + const chain = mock_node_status.most_active.chains; + for (const c of chain) { + const chain = await screen.findByText(c); + expect(chain).toBeInTheDocument(); + } + }); + + it("shows most active iface information", async () => { + render(); + const traffic = Math.round( + (mock_node_status.most_active.rx_bytes + + mock_node_status.most_active.tx_bytes) / + 1024 / + 1024 + ); + const speed = await screen.findByText(new RegExp(`^${traffic}`, "i")); + expect(speed).toBeInTheDocument(); + const iface = await screen.findByText( + mock_node_status.most_active.iface + ); + expect(iface).toBeInTheDocument(); + }); +}); diff --git a/plugins/lime-plugin-rx/src/sections/alignment.tsx b/plugins/lime-plugin-rx/src/sections/alignment.tsx new file mode 100644 index 000000000..ffaa09fe0 --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/alignment.tsx @@ -0,0 +1,125 @@ +import { Trans } from "@lingui/macro"; + +import { Button } from "components/elements/button"; + +import { + IconsClassName, + Section, + SectionTitle, +} from "plugins/lime-plugin-rx/src/components/components"; +import { SignalColor } from "plugins/lime-plugin-rx/src/components/signalColor"; +import { AlignIcon } from "plugins/lime-plugin-rx/src/icons/alignIcon"; +import { useNodeStatus } from "plugins/lime-plugin-rx/src/rxQueries"; +import { StatusResponse } from "plugins/lime-plugin-rx/src/rxTypes"; + +import { useBatHost } from "utils/queries"; + +function stripIface(hostIface) { + return hostIface.split("_wlan")[0].replace("_", "-"); +} + +export const AlignmentCard = ({ status }: { status: StatusResponse }) => { + const hasMostActive = !!status.most_active?.iface; + const { data: bathost } = useBatHost( + status.most_active && status.most_active.station_mac, + status.most_active && status.most_active.iface, + { enabled: hasMostActive } + ); + + const traffic = Math.round( + (status.most_active.rx_bytes + status.most_active.tx_bytes) / + 1024 / + 1024 + ); + return ( +
+ {hasMostActive && ( + <> +
+ +
+ {status.most_active?.chains && + status.most_active.chains.map((chain, i) => ( + + + {i !== + status.most_active.chains.length - + 1 && " / "} + + ))} +
+
+
+
+ Most active link +
+
+ {bathost && bathost.hostname ? ( + {stripIface(bathost.hostname)} + ) : ( + + Fetching name + + )} +
+
+ Interface: + + {status.most_active.iface} + +
+
+ Traffic: + {traffic}MB/s +
+
+ + )} + {!hasMostActive && ( +
+ No most active iface +
+ )} +
+ +
+
+ ); +}; + +export const Alignment = () => { + const { data: status, isLoading } = useNodeStatus(); + + return ( +
+
+ }> + Your Alignment + + {isLoading ? ( +
+ Loading... +
+ ) : ( + + )} +
+
+ ); +}; diff --git a/plugins/lime-plugin-rx/src/sections/internetPath.spec.tsx b/plugins/lime-plugin-rx/src/sections/internetPath.spec.tsx new file mode 100644 index 000000000..b7defc1e1 --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/internetPath.spec.tsx @@ -0,0 +1,87 @@ +import "@testing-library/jest-dom/extend-expect"; +import { screen, waitFor, within } from "@testing-library/preact"; + +import { getPath } from "plugins/lime-plugin-metrics/src/metricsApi"; +import { + getInternetStatus, + getNodeStatus, +} from "plugins/lime-plugin-rx/src/rxApi"; +import { IGetInternetStatus } from "plugins/lime-plugin-rx/src/rxTypes"; +import { InternetPath } from "plugins/lime-plugin-rx/src/sections/internetPath"; +import { mock_node_status } from "plugins/lime-plugin-rx/src/sections/wired.spec"; + +import { render } from "utils/test_utils"; + +jest.mock("plugins/lime-plugin-rx/src/rxApi"); +jest.mock("plugins/lime-plugin-metrics/src/metricsApi.js"); +const mockedNodeStatus = jest.mocked(getNodeStatus); +const mockedInternetStatus = jest.mocked(getInternetStatus); +const mockedPath = jest.mocked(getPath); + +describe("align page", () => { + beforeEach(() => { + mockedNodeStatus.mockImplementation(async () => mock_node_status); + mockedInternetStatus.mockImplementation( + async () => get_internet_status_mock + ); + mockedPath.mockImplementation(async () => last_internet_path_mock); + }); + + it("Shows diagnose and map buttons", async () => { + render(); + const diagnoseBtn = await screen.findByText(/Diagnose/i); + expect(diagnoseBtn).toBeInTheDocument(); + const mapBtn = await screen.findByText(/Map/i); + expect(mapBtn).toBeInTheDocument(); + }); + + it("search every internet status label and check if the icon is correct", async () => { + render(); + const status = get_internet_status_mock; + for (const [key, value] of Object.entries(status)) { + if (key === "status") return; + const stat = within(await screen.findByTestId(`internet-${key}`)); + const label = stat.getByText(key); + expect(label).toBeInTheDocument(); + await waitFor(() => + expect( + screen.queryByTestId(`internet-status-${key}`) + ).not.toHaveClass("stroke-disabled") + ); + const icon = await stat.findByTestId(`internet-status-${key}`); + const color = value.working ? "fill-primary-dark" : "fill-danger"; + expect(icon).toHaveClass(color); + } + }); + + it("look that every node is painted on the path", async () => { + render(); + await waitFor(() => expect(mockedPath).toHaveBeenCalledTimes(1)); + + for (const node of last_internet_path_mock) { + const nodeText = node.hostname ? node.hostname : node.ip; + const txt = await screen.findByText(nodeText); + expect(txt).toBeInTheDocument(); + } + }); +}); + +const get_internet_status_mock: IGetInternetStatus = { + DNS: { + working: false, + }, + IPv6: { + working: true, + }, + status: "ok", + IPv4: { + working: false, + }, +}; + +const last_internet_path_mock = [ + { ip: "10.219.105.28", hostname: "nodo1" }, + { ip: "10.1.61.3", hostname: "" }, + { ip: "10.1.61.2", hostname: "" }, + { ip: "10.75.0.1", hostname: "GW" }, +]; diff --git a/plugins/lime-plugin-rx/src/sections/internetPath.tsx b/plugins/lime-plugin-rx/src/sections/internetPath.tsx new file mode 100644 index 000000000..559872961 --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/internetPath.tsx @@ -0,0 +1,135 @@ +import { Trans } from "@lingui/macro"; +import { useCallback } from "react"; + +import { Button } from "components/elements/button"; +import { GlobeIcon } from "components/icons/globeIcon"; +import Loading from "components/loading"; + +import { + usePath, + usePathLoss, +} from "plugins/lime-plugin-metrics/src/metricsQueries"; +import { + IconsClassName, + Section, + SectionTitle, +} from "plugins/lime-plugin-rx/src/components/components"; +import LineChart from "plugins/lime-plugin-rx/src/components/internetPathChart"; +import { InternetStatus } from "plugins/lime-plugin-rx/src/components/internetStatus"; +import { PathIcon } from "plugins/lime-plugin-rx/src/icons/pathIcon"; +import { useInternetStatus } from "plugins/lime-plugin-rx/src/rxQueries"; +import { IGetInternetStatus } from "plugins/lime-plugin-rx/src/rxTypes"; + +export const InternetPath = () => { + const { + data: path, + isLoading: pathIsLoading, + isError: pathError, + } = usePath({ + refetchOnWindowFocus: false, + enabled: true, + }); + + const pathLoss = + path + ?.map((station) => { + return { ip: station.ip }; + }) + .slice() + .reverse() ?? []; + + const { refetch: refetchLosses } = usePathLoss(pathLoss, { + refetchOnWindowFocus: false, + enabled: false, + initialData: [], + }); + + const { data: internet, isLoading: internetStatusLoading } = + useInternetStatus({ + structuralSharing: ( + oldData: IGetInternetStatus, + newData: IGetInternetStatus + ) => { + if ( + // If is the first execution and there are no internet + (!oldData && + !(newData.IPv4.working || newData.IPv6.working)) || + // If the old data and new data are different + (oldData && + (oldData.IPv4.working || oldData.IPv6.working) !== + (newData.IPv4.working || newData.IPv6.working)) + ) { + if (refetchLosses) refetchLosses(); + } + return newData; + }, + }); + + const checkLosses = useCallback(async () => { + refetchLosses(); + }, [refetchLosses]); + + const workingInternet = + !internetStatusLoading && + (internet.IPv4.working || internet.IPv6.working); + + // Conditional rendering for las known path + let pathComponent = ( +
+ + + Loading
+ last internet path... +
+
+ ); + if (pathError) { + pathComponent = ( +
+ + + Error retrieving +
+ last internet path +
+
+ ); + } else if (!pathIsLoading && path) { + pathComponent = ( + + + + ); + } + + return ( +
+ }> + Path to Internet + +
+ {pathComponent} +
+ + +
+
+ +
+ ); +}; diff --git a/plugins/lime-plugin-rx/src/sections/wired.spec.tsx b/plugins/lime-plugin-rx/src/sections/wired.spec.tsx new file mode 100644 index 000000000..89c28114f --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/wired.spec.tsx @@ -0,0 +1,139 @@ +import "@testing-library/jest-dom/extend-expect"; +import { screen } from "@testing-library/preact"; + +import { getNodeStatus } from "plugins/lime-plugin-rx/src/rxApi"; +import { StatusResponse } from "plugins/lime-plugin-rx/src/rxTypes"; +import { Wired } from "plugins/lime-plugin-rx/src/sections/wired"; + +import { render } from "utils/test_utils"; + +jest.mock("plugins/lime-plugin-rx/src/rxApi"); +const mockedFoo = jest.mocked(getNodeStatus); + +describe("align page", () => { + beforeEach(() => { + mockedFoo.mockImplementation(async () => mock_node_status); + }); + + it("Shows a wan and a lan interface with the interface name", async () => { + render(); + expect(await screen.findByText("LAN")).toBeInTheDocument(); + expect(await screen.findByText("WAN")).toBeInTheDocument(); + expect(await screen.findByText("eth0.1")).toBeInTheDocument(); + expect(await screen.findByText("eth0.2")).toBeInTheDocument(); + }); + + it("Shows the correct number of disabled and enabled icons", async () => { + render(); + const portsDiv = await screen.findByTestId("ports-container"); + // eslint-disable-next-line testing-library/no-node-access + const portsIcons = portsDiv.querySelectorAll("svg"); + const ports = mock_node_status.switch_status.filter( + (item) => item.role !== "cpu" + ); + expect(portsIcons.length).toBe(ports.length); + // eslint-disable-next-line testing-library/no-node-access + const activeIcons = portsDiv.querySelectorAll("svg.fill-disabled"); + const activePorts = ports.filter((item) => item.link !== "up"); + expect(activeIcons.length).toBe(activePorts.length); + // eslint-disable-next-line testing-library/no-node-access + const disabledIcons = portsDiv.querySelectorAll( + "svg.fill-primary-dark" + ); + const disabledPorts = ports.filter((item) => item.link !== "down"); + expect(disabledIcons.length).toBe(disabledPorts.length); + }); +}); + +// Used on other tests +// eslint-disable-next-line jest/no-export +export const mock_node_status: StatusResponse = { + ips: [ + { + version: "4", + address: "10.219.123.10/16", + }, + { + version: "6", + address: "fddb:f81c:47ba::a7b:be00/64", + }, + { + version: "6", + address: "fe80::c24a:ff:febe:7b0a/64", + }, + ], + hostname: "lapastoramesh-c", + switch_status: [ + { + device: "eth0.1", + num: 2, + role: "lan", + link: "up", + }, + { + device: "eth0.1", + num: 3, + role: "lan", + link: "down", + }, + { + device: "eth0.1", + num: 4, + role: "lan", + link: "down", + }, + { + device: "eth0.1", + num: 5, + role: "lan", + link: "down", + }, + { + device: "eth0.1", + num: 0, + role: "cpu", + link: "up", + }, + { + device: "eth0.2", + num: 1, + role: "wan", + link: "down", + }, + { + device: "eth0.2", + num: 0, + role: "cpu", + link: "up", + }, + ], + status: "ok", + uptime: "3186.15", + most_active: { + rx_short_gi: true, + station_mac: "C0:4A:00:DD:69:1C", + tx_bytes: 13809119, + rx_vht: false, + rx_mhz: 40, + rx_40mhz: true, + tx_packets: 31706, + tx_mhz: 40, + rx_packets: 97813, + rx_ht: true, + tx_mcs: 15, + noise: -90, + rx_mcs: 15, + chains: [-17, -16], + rx_bytes: 19464143, + tx_ht: true, + iface: "wlan1-mesh", + tx_rate: 300000, + inactive: 30, + tx_short_gi: true, + tx_40mhz: true, + expected_throughput: 59437, + tx_vht: false, + rx_rate: 300000, + signal: -14, + }, +}; diff --git a/plugins/lime-plugin-rx/src/sections/wired.tsx b/plugins/lime-plugin-rx/src/sections/wired.tsx new file mode 100644 index 000000000..32ea13c16 --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/wired.tsx @@ -0,0 +1,77 @@ +import { Trans } from "@lingui/macro"; + +import { + IconsClassName, + Section, + SectionTitle, +} from "plugins/lime-plugin-rx/src/components/components"; +import { PortsIcon } from "plugins/lime-plugin-rx/src/icons/portsIcon"; +import { useNodeStatus } from "plugins/lime-plugin-rx/src/rxQueries"; +import { SwitchStatus } from "plugins/lime-plugin-rx/src/rxTypes"; + +const Ports = ({ switches }: { switches: SwitchStatus[] }) => { + const ports = switches.reduce((acc, obj) => { + const { role } = obj; + if (!acc[role]) { + acc[role] = []; + } + acc[role].push(obj); + return acc; + }, {}); + return ( +
+ {Object.keys(ports).map((role) => { + if (role.toLowerCase() === "cpu") return null; + return ( +
+

{role.toUpperCase()}

+

{ports[role][0].device.toLowerCase()}

+
+ {ports[role].map((port) => { + const link = + port.link.toLowerCase() === "up" + ? "fill-primary-dark" + : "fill-disabled"; + return ( +
+ +
+ ); + })} +
+
+ ); + })} +
+ ); +}; + +export const Wired = () => { + const { data: status, isLoading } = useNodeStatus(); + + const switches = status?.switch_status; + + return ( +
+ }> + Wired connections + +
+ {isLoading ? ( + Loading... + ) : switches.length ? ( + + ) : ( +
+ No wired connections found +
+ )} +
+
+ ); +}; diff --git a/src/assets/icons/AlterMundiLogo.svg b/src/assets/icons/AlterMundiLogo.svg new file mode 100644 index 000000000..667c8e5b5 --- /dev/null +++ b/src/assets/icons/AlterMundiLogo.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/LibreRouterLogo.svg b/src/assets/icons/LibreRouterLogo.svg new file mode 100644 index 000000000..c7a25a0e0 --- /dev/null +++ b/src/assets/icons/LibreRouterLogo.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/elements/button.tsx b/src/components/elements/button.tsx new file mode 100644 index 000000000..1e1a871b7 --- /dev/null +++ b/src/components/elements/button.tsx @@ -0,0 +1,57 @@ +interface ButtonProps { + onClick?: () => void; + children?: any; // type error with Trans component + size?: "sm" | "md" | "lg"; + color?: "primary" | "secondary"; + href?: string; +} + +export const Button = ({ + size = "md", + color = "primary", + onClick, + children, + href, + ...props +}: ButtonProps) => { + let sizeClasses = "", + colorClasses = ""; + switch (size) { + case "sm": + sizeClasses = "py-2 px-4 text-sm"; + break; + case "md": + sizeClasses = "py-4 px-6 min-w-[theme('spacing[52]')]"; + break; + case "lg": + sizeClasses = "py-6 px-8"; + break; + } + + switch (color) { + case "primary": + colorClasses = "bg-button-primary"; + break; + case "secondary": + colorClasses = "bg-button-secondary"; + break; + } + + const cls = `cursor-pointer text-white font-semibold rounded-xl text-center place-content-center + justify-center border-0 ${sizeClasses} ${colorClasses}`; + + if (href) { + return ( + +
+ {children} +
+
+ ); + } + return ( +
+ {children} +
+ ); +}; diff --git a/src/components/icons/circle.tsx b/src/components/icons/circle.tsx new file mode 100644 index 000000000..957615a74 --- /dev/null +++ b/src/components/icons/circle.tsx @@ -0,0 +1,7 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const Circle = ({ ...props }: IconProps) => ( + + + +); diff --git a/src/components/icons/circlecheckIcon.tsx b/src/components/icons/circlecheckIcon.tsx new file mode 100644 index 000000000..3532da8f6 --- /dev/null +++ b/src/components/icons/circlecheckIcon.tsx @@ -0,0 +1,7 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const CirclecheckIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/src/components/icons/globeIcon.tsx b/src/components/icons/globeIcon.tsx new file mode 100644 index 000000000..9e4b71a63 --- /dev/null +++ b/src/components/icons/globeIcon.tsx @@ -0,0 +1,25 @@ +export const GlobeIcon = ({ + size = "100%", + x = 0, + y = 0, + className = "", +}: { + size?: number | string; + x?: number; + y?: number; + className?: string; +}) => { + return ( + + + + ); +}; diff --git a/src/components/icons/xmarkIcon.tsx b/src/components/icons/xmarkIcon.tsx new file mode 100644 index 000000000..4c8cd828e --- /dev/null +++ b/src/components/icons/xmarkIcon.tsx @@ -0,0 +1,7 @@ +import { IconProps, SvgIcon } from "components/icons/SvgIcon"; + +export const XmarkIcon = ({ ...props }: IconProps) => ( + + + +); diff --git a/src/components/loading/loading-dots.tsx b/src/components/loading/loading-dots.tsx new file mode 100644 index 000000000..6d550de6e --- /dev/null +++ b/src/components/loading/loading-dots.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from "preact/hooks"; + +const LoadingDots = ({ + dotsLength = 3, + delay = 500, +}: { + delay?: number; + dotsLength?: number; +}) => { + const [dots, setDots] = useState("."); + + useEffect(() => { + const intervalId = setInterval(() => { + setDots((prevDots) => { + if (prevDots.length === dotsLength) { + return "."; + } + return `${prevDots}.`; + }); + }, delay); + + return () => clearInterval(intervalId); + }, [delay, dotsLength]); + + return <>{dots}; +}; + +export default LoadingDots; diff --git a/src/utils/test_utils.js b/src/utils/test_utils.js index ce859c3ba..dc6e08461 100644 --- a/src/utils/test_utils.js +++ b/src/utils/test_utils.js @@ -1,3 +1,4 @@ +// @ts-nocheck import { i18n } from "@lingui/core"; // import i18n, { dynamicActivate } from '../i18n'; import { I18nProvider } from "@lingui/react"; diff --git a/tailwind.config.js b/tailwind.config.js index 9773ed829..2a41c5a44 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -25,6 +25,10 @@ module.exports = { info: "#00ADEE", disabled: "#BABABA", }, + button: { + primary: "#1BC47D", + secondary: "#6BC3AE", + }, danger: "#EB7575", info: "#EAAB7E", success: "#76BD7D", From 5c497f7ae9e6a1c60856c3d6f9a64ba6c5654528 Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 9 May 2024 12:06:53 +0200 Subject: [PATCH 05/22] chore(meshwide): minor fixes --- .../lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx | 2 +- .../src/lib/links/getLinksCoordinates.ts | 4 ++-- plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx | 2 +- src/config.ts | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx index cf72d4423..e04ca9f8e 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx @@ -57,7 +57,7 @@ const NodeMarker = ({ }, }} > - {name} + {name} ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts index 57f76ec89..615183566 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts @@ -37,7 +37,7 @@ export const mergeLinksAndCoordinates = ( // Is possible that the destination node is not on the list of links, // just ignore it - if (!dstNodeName) continue; + if (!dstNodeName || !links[dstNodeName]) continue; if ( dstNodeName && @@ -47,7 +47,7 @@ export const mergeLinksAndCoordinates = ( // Generate a unique id of the point to point link based on the coordinates const linkKey = PontToPointLink.generateId( nodes[linkNodeName].coordinates, - nodes[dstNodeName!].coordinates + nodes[dstNodeName].coordinates ); // If this point to point link no exists, instantiate it diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index 62b6887d2..8c6787845 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -14,7 +14,7 @@ import { import { useSharedData } from "utils/useSharedData"; -const refetchInterval = 5000; +const refetchInterval = 10000; export function useMeshWideLinksReference(params) { const dataType: DataTypes = "wifi_links_info"; diff --git a/src/config.ts b/src/config.ts index c77a6ab9a..8560587f9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -24,7 +24,6 @@ export const plugins: LimePlugin[] = [ NodeAdmin, NetworkAdmin, Firmware, - MeshWide, MeshUpgrade, ChangeNode, RemoteSupport, From 917feb11ea00ad93027d8c2c0f522c82b774dc29 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 03:39:56 -0500 Subject: [PATCH 06/22] chore(meshwide): implement mesh node safe reboot (#417) * chore(meshwide): refactor to implement generic callToRemoteNode * chore(meshwide): implement remote reboot --- .../upgradeState/ParallelErrors.tsx | 4 +- .../src/meshUpgradeApi.tsx | 34 ++++- .../src/utils/api.ts | 85 +++++------- .../components/FeatureDetail/NodeDetail.tsx | 6 +- .../FeatureDetail/RebootNodeBtn.tsx | 124 ++++++++++++++++++ src/components/Modal/Modal.tsx | 2 +- src/components/app.tsx | 2 +- src/utils/meshWideSyncCall.ts | 12 +- 8 files changed, 201 insertions(+), 68 deletions(-) create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx index 3f5f12387..ce30e1035 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx @@ -2,7 +2,7 @@ import { Trans } from "@lingui/macro"; import { StatusMessage } from "components/status/statusMessage"; -import { ParallelMutationError, SyncCallErrors } from "utils/meshWideSyncCall"; +import { RemoteNodeCallError, SyncCallErrors } from "utils/meshWideSyncCall"; export const ParallelErrors = ({ errors }: { errors: SyncCallErrors }) => { return ( @@ -13,7 +13,7 @@ export const ParallelErrors = ({ errors }: { errors: SyncCallErrors }) => {
{errors.map((error, key) => { - if (error instanceof ParallelMutationError) { + if (error instanceof RemoteNodeCallError) { return (
{error.ip}: {error.message} diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx index aa913fc96..4704d3410 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx @@ -1,13 +1,14 @@ import { + MeshWideRPCReturnTypes, MeshWideUpgradeInfo, NodeMeshUpgradeInfo, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; import { + MeshUpgradeApiError, callToRemoteNode, - meshUpgradeApiCall, } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; -import api from "utils/uhttpd.service"; +import api, { UhttpdService } from "utils/uhttpd.service"; export const getMeshWideUpgradeInfo = async () => { const res = await api.call("shared-state-async", "get", { @@ -42,11 +43,34 @@ export const setAbort = async () => { }; // Remote API calls - export async function remoteScheduleUpgrade({ ip }: { ip: string }) { - return await callToRemoteNode({ ip, apiMethod: "start_safe_upgrade" }); + return await callToRemoteNode({ + ip, + apiCall: (customApi) => + meshUpgradeApiCall("start_safe_upgrade", customApi), + }); } export async function remoteConfirmUpgrade({ ip }: { ip: string }) { - return await callToRemoteNode({ ip, apiMethod: "confirm_boot_partition" }); + return await callToRemoteNode({ + ip, + apiCall: (customApi) => + meshUpgradeApiCall("confirm_boot_partition", customApi), + }); } + +const meshUpgradeApiCall = async ( + method: string, + customApi?: UhttpdService +) => { + const httpService = customApi || api; + const res = (await httpService.call( + "lime-mesh-upgrade", + method, + {} + )) as MeshWideRPCReturnTypes; + if (res.error) { + throw new MeshUpgradeApiError(res.error, res.code); + } + return res.code; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts index 8b23f3edf..64c6e5ab3 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts @@ -1,29 +1,12 @@ import { MeshUpgradeApiErrorTypes, - MeshWideRPCReturnTypes, MeshWideUpgradeInfo, UpgradeStatusType, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; -import { ParallelMutationError } from "utils/meshWideSyncCall"; +import { RemoteNodeCallError } from "utils/meshWideSyncCall"; import { login } from "utils/queries"; -import api, { UhttpdService } from "utils/uhttpd.service"; - -export const meshUpgradeApiCall = async ( - method: string, - customApi?: UhttpdService -) => { - const httpService = customApi || api; - const res = (await httpService.call( - "lime-mesh-upgrade", - method, - {} - )) as MeshWideRPCReturnTypes; - if (res.error) { - throw new MeshUpgradeApiError(res.error, res.code); - } - return res.code; -}; +import { UhttpdService } from "utils/uhttpd.service"; export class MeshUpgradeApiError extends Error { message: string; @@ -38,61 +21,65 @@ export class MeshUpgradeApiError extends Error { } /** - * Wrapper that tries to call a remote node and returns the result or throws an error + * From a MeshWideUpgradeInfo nodes it returns the ips of the nodes that are in certain status provided + * @param nodes the nodes to check + * @param status the status to check the criteria + */ +export const getNodeIpsByStatus = ( + nodes: MeshWideUpgradeInfo, + status: UpgradeStatusType +) => { + if (!nodes) return []; + return Object.values(nodes) + .filter( + (node) => + node.node_ip !== null && + node.node_ip !== undefined && + node.node_ip.trim() !== "" && + node.upgrade_state === status + ) + .map((node) => node.node_ip as string); // 'as string' is safe here due to the filter condition +}; + +/** + * Wrapper to do calls to a remote node and returns the result or throws an error * * First it tries to login and if success do a specific call to the remote node * @param ip * @param apiMethod */ -export async function callToRemoteNode({ +export async function callToRemoteNode({ ip, - apiMethod, + apiCall, + username = "lime-app", + password = "generic", }: { ip: string; - apiMethod: string; + apiCall: (customApi: UhttpdService) => Promise; + username?: string; + password?: string; }) { const customApi = new UhttpdService(ip); try { - await login({ username: "lime-app", password: "generic", customApi }); + await login({ username, password, customApi }); } catch (error) { - throw new ParallelMutationError( + throw new RemoteNodeCallError( `Cannot login`, customApi.customIp, error ); } try { - return await meshUpgradeApiCall(apiMethod, customApi); + return await apiCall(customApi); } catch (error) { let additionalInfo = ""; if (error instanceof MeshUpgradeApiError) { additionalInfo = `: ${error.message}`; } - throw new ParallelMutationError( - `Cannot startSafeUpgrade${additionalInfo}`, + throw new RemoteNodeCallError( + `Cannot do remote call${additionalInfo}`, ip, error ); } } - -/** - * From a MeshWideUpgradeInfo nodes it returns the ips of the nodes that are in certain status provided - * @param nodes the nodes to check - * @param status the status to check the criteria - */ -export const getNodeIpsByStatus = ( - nodes: MeshWideUpgradeInfo, - status: UpgradeStatusType -) => { - if (!nodes) return []; - return Object.values(nodes) - .filter( - (node) => - node.node_ip !== null && - node.node_ip !== undefined && - node.node_ip.trim() !== "" && - node.upgrade_state === status - ) - .map((node) => node.node_ip as string); // 'as string' is safe here due to the filter condition -}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index 25ab29ec3..0d81296f9 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -1,6 +1,7 @@ import { Trans } from "@lingui/macro"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; +import RemoteRebootBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn"; import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; import { Row, @@ -39,10 +40,7 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => {
{name}
- {/*todo(kon): implement safe_reboot*/} - {/**/} +
{!isDown ? ( diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx new file mode 100644 index 000000000..8704c8b3e --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx @@ -0,0 +1,124 @@ +import { Trans } from "@lingui/macro"; +import { useMutation } from "@tanstack/react-query"; +import { useEffect, useState } from "preact/hooks"; +import { useCallback } from "react"; + +import { useModal } from "components/Modal/Modal"; +import { Button } from "components/buttons/button"; +import { ErrorMsg } from "components/form"; +import Loading from "components/loading"; + +import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; +import { PowerIcon } from "plugins/lime-plugin-mesh-wide/src/icons/power"; +import { INodeInfo } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +interface IRemoteRebotProps { + ip: string; + password: string; +} + +export async function remoteReboot({ ip, password }: IRemoteRebotProps) { + return await callToRemoteNode({ + ip, + apiCall: (customApi) => + customApi.call("system", "reboot", {}).then(() => true), + username: "root", + password, + }); +} + +const useRemoteReboot = (opts?) => { + return useMutation((props: IRemoteRebotProps) => remoteReboot(props), { + mutationKey: ["system", "reboot"], + ...opts, + }); +}; + +const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { + const { toggleModal, setModalState, isModalOpen } = useModal(); + const [password, setPassword] = useState(""); + const { mutate, isLoading, error } = useRemoteReboot({ + onSuccess: () => { + toggleModal(); + }, + }); + + function changePassword(e) { + setPassword(e.target.value || ""); + } + + const doLogin = useCallback(() => { + mutate({ ip: node.ipv4, password }); + }, [mutate, node.ipv4, password]); + + const updateModalState = useCallback(() => { + setModalState({ + title: Reboot node {node.hostname}, + content: ( +
+ + Are you sure you want to reboot this node? This action + will disconnect the node from the network for a few + minutes.
+ Add shared password or let it empty if no password is + set. +
+ {isLoading && } + {!isLoading && ( +
+ + + {error && ( + + + Error performing reboot: {error} + + + )} +
+ )} +
+ ), + successCb: doLogin, + successBtnText: Reboot, + }); + }, [doLogin, error, isLoading, node.hostname, password, setModalState]); + + const rebootModal = useCallback(() => { + updateModalState(); + toggleModal(); + }, [toggleModal, updateModalState]); + + // Update modal state with mutation result + useEffect(() => { + if (isModalOpen) { + updateModalState(); + } + }, [isLoading, error, isModalOpen, updateModalState]); + + return { rebootModal, toggleModal, isModalOpen }; +}; + +const RemoteRebootBtn = ({ node }: { node: INodeInfo }) => { + const { rebootModal, isModalOpen } = useRebootNodeModal({ + node, + }); + + return ( + + ); +}; + +export default RemoteRebootBtn; diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index f2a5f54af..bc067e600 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -146,7 +146,7 @@ const Modal = ({
diff --git a/src/components/app.tsx b/src/components/app.tsx index ddde55816..a45d4bbca 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -88,7 +88,7 @@ const App = () => { }, [session, login]); if (!session?.username || !boardData) { - return
"Loading..."
; + return
Loading...
; } return ( diff --git a/src/utils/meshWideSyncCall.ts b/src/utils/meshWideSyncCall.ts index 130841147..6e945a1a3 100644 --- a/src/utils/meshWideSyncCall.ts +++ b/src/utils/meshWideSyncCall.ts @@ -5,7 +5,7 @@ import { useCallback } from "react"; import queryCache from "utils/queryCache"; import { useSharedData } from "utils/useSharedData"; -export class ParallelMutationError extends Error { +export class RemoteNodeCallError extends Error { ip: string; error: Error; constructor(message: string, ip: string, error: Error) { @@ -15,7 +15,7 @@ export class ParallelMutationError extends Error { this.error = error; // Set the prototype explicitly. - Object.setPrototypeOf(this, ParallelMutationError.prototype); + Object.setPrototypeOf(this, RemoteNodeCallError.prototype); } } @@ -24,7 +24,7 @@ interface IMutationFnVariables { variables?: TVariables; } -export type SyncCallErrors = Array; +export type SyncCallErrors = Array; type SyncCallResults = TResult[]; /** * This object is used to store the results and errors of all the mutations calls. @@ -49,7 +49,7 @@ interface IMeshWideSyncCall { variables?: TVariables; options?: UseMutationOptions< TResult, - ParallelMutationError, + RemoteNodeCallError, IMutationFnVariables >; } @@ -60,7 +60,7 @@ interface IMeshWideSyncCall { * In order to reuse the data on different parts, it implements caches using the queryCache. The results and errors for * all the calls are stored using useSharedData query. * - * In addition, is possible to acces to every single call accesing to the [...mutationKey, ip] key on the queryCache. + * In addition, is possible to access to every single call accessing to the [...mutationKey, ip] key on the queryCache. * * @param mutationKey Mutation key to store the results and errors * @param mutationFn Function that will be called for every ip @@ -81,7 +81,7 @@ export const useMeshWideSyncCall = ({ const { mutateAsync } = useMutation< TResult, - ParallelMutationError, + RemoteNodeCallError, IMutationFnVariables >({ mutationFn, mutationKey, ...options }); From 30f821d0f53d61e9763ad79338373fbffda44f38 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 11:11:59 -0500 Subject: [PATCH 07/22] chore(meshwide): hotfixes (#420) * chore(meshwide): increase queries timeout * chore(meshwide): show new links errors * chore(meshwide): add node errors instructions --- .../src/components/Map/LinkLine.tsx | 7 ++-- .../src/hooks/useLocatedLinks.tsx | 39 ++++++++++--------- .../src/lib/links/processLinkErrors.ts | 12 +++--- .../src/lib/nodes/processErrors.ts | 8 +++- .../src/meshWideQueries.tsx | 2 +- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx index 2a3d50f59..7d1b44b80 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx @@ -15,6 +15,7 @@ export const LinkLine = ({ referenceLink, actualLink }: ILinkLineProps) => { useSelectedMapFeature(); const linkToShow = referenceLink ?? actualLink; + const linkId = linkToShow.id; let isNewNode = false; if (!referenceLink) { isNewNode = true; @@ -28,9 +29,9 @@ export const LinkLine = ({ referenceLink, actualLink }: ILinkLineProps) => { let hasError = false; let linkUp = true; - if (!isNewNode && linksErrors && linksErrors[referenceLink.id]) { - hasError = linksErrors[referenceLink.id].hasErrors; - linkUp = linksErrors[referenceLink.id].linkUp; + if (linksErrors && linksErrors[linkId]) { + hasError = linksErrors[linkId].hasErrors; + linkUp = linksErrors[linkId].linkUp; } const _setSelectedFeature = () => { diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx index d0168821d..4be5cb176 100644 --- a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx @@ -92,25 +92,28 @@ const useCalculateLocatedLinks = ({ const linksLoaded = !!locatedLinksReference && !!locatedLinks; const linksErrors: ILinkErrors = useMemo(() => { - // If there are no links reference just drop no errors (because there are no links to compare with) - if (locatedLinksReference && !isEmpty(locatedLinksReference)) { - const errors: ILinkErrors = {}; - Object.entries(locatedLinksReference).forEach( - ([k, referenceLink]) => { - let actualLink: PontToPointLink; - if (locatedLinks) { - actualLink = Object.values(locatedLinks).find( - (value) => value.id === referenceLink.id - ); - } - errors[referenceLink.id] = compareLinks({ - referenceLink, - actualLink, - }); - } - ); - return errors; + if (!locatedLinks) return; + let _locatedLinksReference = locatedLinksReference; + // If there are no links reference we set the reference to the actual links + // On this way the errors between the actual links and the reference links wont be shown but + // errors on the links will. + if (!_locatedLinksReference || isEmpty(_locatedLinksReference)) { + _locatedLinksReference = locatedLinks; } + const errors: ILinkErrors = {}; + Object.entries(_locatedLinksReference).forEach(([k, referenceLink]) => { + let actualLink: PontToPointLink; + if (locatedLinks) { + actualLink = Object.values(locatedLinks).find( + (value) => value.id === referenceLink.id + ); + } + errors[referenceLink.id] = compareLinks({ + referenceLink, + actualLink, + }); + }); + return errors; }, [locatedLinksReference, locatedLinks]); // This links are valid and not exists on the reference state diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts index 655f8e6e1..e1fde0920 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts @@ -86,11 +86,13 @@ export const compareLinks = ({ const isUp = !!actualLink; if (!isUp) setLinkIsDown(); - ptoPErrors.macToMacErrors[macToMacReference.id] = { - hasErrors: false, - linkErrors: {}, - linkUp: isUp, - }; + if (!ptoPErrors.macToMacErrors[macToMacReference.id]) { + ptoPErrors.macToMacErrors[macToMacReference.id] = { + hasErrors: false, + linkErrors: {}, + linkUp: isUp, + }; + } Object.entries(macToMacReference.data).forEach( ([nodeNameReference, wifiDataReference]) => { const wifiDataActual = macToMacActual?.data[nodeNameReference]; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts b/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts index 8c562143f..0022fe3e7 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/nodes/processErrors.ts @@ -9,11 +9,15 @@ export const processNodeErrors = ( ) => { const errors: NodeErrorCodes[] = []; - // If not reference is a new node - if (!reference) return errors; + // Here the errors related to the actual node state if (!actual) return [NodeErrorCodes.NODE_DOWN]; + // Down here put errors related to the comparassion with reference state + + // If not reference is a new node + if (!reference) return errors; + // Check mac list are equal if (reference.macs.length !== actual.macs.length) { errors.push(NodeErrorCodes.MACS_MISSMATCH); diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index 8c6787845..50570c3b6 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -14,7 +14,7 @@ import { import { useSharedData } from "utils/useSharedData"; -const refetchInterval = 10000; +const refetchInterval = 60000; export function useMeshWideLinksReference(params) { const dataType: DataTypes = "wifi_links_info"; From f431351ef140578d3a86a2d9b17f1312703b1ef0 Mon Sep 17 00:00:00 2001 From: selankon Date: Sat, 11 May 2024 01:38:07 -0500 Subject: [PATCH 08/22] chore(meshwide): implement sync with remote node (#419) It implements the flow to perform publish all of a node, and get the syncronization from the node you are visiting. On this way, when a user browses the map, it always have the updated version of the node It depends on libremesh/lime-packages#1108 --- .../components/FeatureDetail/NodeDetail.tsx | 6 +- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 99 +++++++++++++++++++ .../src/components/Map/FloatingAlert.tsx | 16 +-- .../src/containers/Map.tsx | 34 +++---- .../lime-plugin-mesh-wide/src/meshWideApi.ts | 44 +++++++++ .../src/meshWideQueries.tsx | 42 +++++++- .../src/meshWideQueriesKeys.tsx | 9 ++ .../src/meshWideTypes.tsx | 7 ++ src/components/icons/teenny/refresh.jsx | 16 +++ 9 files changed, 245 insertions(+), 28 deletions(-) create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx create mode 100644 src/components/icons/teenny/refresh.jsx diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index 0d81296f9..06596cf91 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -3,6 +3,7 @@ import { Trans } from "@lingui/macro"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; import RemoteRebootBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn"; import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; +import UpdateNodeInfoBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn"; import { Row, TitleAndText, @@ -40,7 +41,10 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => {
{name}
- +
+ + +
{!isDown ? ( diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx new file mode 100644 index 000000000..b8a8b9dbc --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -0,0 +1,99 @@ +import { Trans } from "@lingui/macro"; +import { useEffect, useState } from "preact/hooks"; +import { useCallback } from "react"; + +import { Button } from "components/buttons/button"; +import { RefreshIcon } from "components/icons/teenny/refresh"; +import { useToast } from "components/toast/toastProvider"; + +import { + usePublishOnRemoteNode, + useSyncDataTypes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; +import { + DataTypes, + INodeInfo, + completeDataTypeKeys, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import queryCache from "utils/queryCache"; + +const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { + const ip = node.ipv4; + + const [isLoading, setIsLoading] = useState(false); + const { showToast, hideToast } = useToast(); + + const { mutateAsync: localNodeSync } = useSyncDataTypes({ + ip, + }); + const { mutateAsync: publishOnRemoteNode } = usePublishOnRemoteNode({ + ip, + }); + + const invalidateQueries = useCallback(() => { + for (const dataType of Object.keys( + completeDataTypeKeys + ) as DataTypes[]) { + queryCache.invalidateQueries({ + queryKey: + getFromSharedStateKeys.getFromSharedStateAsync(dataType), + }); + } + }, []); + + // useCallback to sync the node data + const syncNode = useCallback(async () => { + if (isLoading) return; + setIsLoading(true); + publishOnRemoteNode({ ip }) + .catch((e) => { + showToast({ + text: ( + + Error connecting with {node.hostname}, is node up? + + ), + duration: 5000, + }); + throw e; + }) + .then(async () => { + await localNodeSync({ ip }); + await invalidateQueries(); + }) + .finally(() => { + setIsLoading(false); + }); + }, [ + invalidateQueries, + ip, + isLoading, + localNodeSync, + node.hostname, + publishOnRemoteNode, + showToast, + ]); + + // Use effect to sync the node data on mount + useEffect(() => { + (async () => { + await syncNode(); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [node.ipv4]); + + return ( + + ); +}; + +export default UpdateNodeInfoBtn; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx index 30600437b..33ddb97ce 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx @@ -48,13 +48,15 @@ export const FloatingAlert = () => { ]); return hasErrors ? ( -
-
- +
+
+
+ +
) : null; diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx index d261ed688..b4d9f1907 100644 --- a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx +++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx @@ -1,5 +1,5 @@ -import { t } from "@lingui/macro"; import L from "leaflet"; +import { ComponentChildren } from "preact"; import { useEffect, useRef } from "preact/hooks"; import { LayerGroup, @@ -12,13 +12,13 @@ import { useLoadLeaflet, useLocation, } from "plugins/lime-plugin-locate/src/locateQueries"; -import { FloatingAlert } from "plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert"; import { BatmanLinksLayer, WifiLinksLayer, } from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers"; import NodesLayer from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer"; import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { DataTypes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; const openStreetMapTileString = "https://{s}.tile.osm.org/{z}/{x}/{y}.png"; const openStreetMapAttribution = @@ -77,6 +77,15 @@ export const MeshWideMap = ({ } }, [loading, nodeLocation]); + const mapSupportedLayers: Record< + DataTypes, + { name: string; layer: ComponentChildren } + > = { + node_info: { name: "Nodes", layer: }, + wifi_links_info: { name: "Wifi Links", layer: }, + bat_links_info: { name: "Batman", layer: }, + }; + return ( - - - - - - - - - - - - - - - - + {Object.values(mapSupportedLayers).map(({ name, layer }, k) => ( + + {layer} + + ))} ); diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts b/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts index c8470df9e..682de5691 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts +++ b/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts @@ -1,9 +1,15 @@ import { QueryKey } from "@tanstack/react-query"; +import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; +import { + getFromSharedStateKeys, + publishAllFromSharedStateAsyncKey, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { DataTypeMap, DataTypes, SharedStateReturnType, + completeDataTypeKeys, } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; import api from "utils/uhttpd.service"; @@ -19,3 +25,41 @@ export const doSharedStateApiCall = async ( } return res.data; }; + +/** + * Sync all data types from shared state from remote node + */ + +interface ISyncWithIpProps { + ip: string; +} + +export async function publishOnRemoteNode({ ip }: ISyncWithIpProps) { + return await callToRemoteNode({ + ip, + apiCall: (customApi) => + customApi + .call(...publishAllFromSharedStateAsyncKey, {}) + .then(() => true), + }); +} + +export async function syncDataType({ + dataType, + ip, +}: { + dataType: DataTypes; + ip: string; +}) { + const queryKey = getFromSharedStateKeys.syncFromSharedStateAsync(dataType, [ + ip, + ]); + return doSharedStateApiCall(queryKey); +} + +export async function syncAllDataTypes({ ip }: { ip: string }) { + const promises = (Object.keys(completeDataTypeKeys) as DataTypes[]).map( + (dataType) => syncDataType({ dataType, ip }) + ); + return await Promise.all(promises); +} diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index 50570c3b6..f1d57c9a3 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -1,8 +1,16 @@ import { useMutation, useQuery } from "@tanstack/react-query"; -import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; +import { + doSharedStateApiCall, + publishOnRemoteNode, + syncAllDataTypes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; -import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; +import { + getFromSharedStateKeys, + publishAllFromSharedStateAsyncKey, + syncFromSharedStateAsyncKey, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { DataTypes, IBatmanLinks, @@ -152,6 +160,36 @@ export const useSetBatmanLinksInfoReferenceState = (params) => { ); }; +/** + * Sync all data types from shared state from remote node + * */ + +export const usePublishOnRemoteNode = ({ + ip, + ...opts +}: { + ip: string; + opts?: any; +}) => { + return useMutation(publishOnRemoteNode, { + mutationKey: [publishAllFromSharedStateAsyncKey, ip], + ...opts, + }); +}; + +export const useSyncDataTypes = ({ + ip, + ...opts +}: { + ip: string; + opts?: any; +}) => { + return useMutation(syncAllDataTypes, { + mutationKey: [syncFromSharedStateAsyncKey, ip], + ...opts, + }); +}; + /** * Set mesh wide config */ diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx index 237afe239..dc8138fcb 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx @@ -8,6 +8,11 @@ export const getFromSharedStateMultiWriterKey = [ "getFromSharedStateMultiWriter", ]; export const getFromSharedStateAsyncKey = ["shared-state-async", "get"]; +export const syncFromSharedStateAsyncKey = ["shared-state-async", "sync"]; +export const publishAllFromSharedStateAsyncKey = [ + "shared-state-async", + "publish_all", +]; export const insertIntoSharedStateKey = [ "shared-state", @@ -19,6 +24,10 @@ export const getFromSharedStateKeys = { ...getFromSharedStateAsyncKey, { data_type: dataType }, ], + syncFromSharedStateAsync: ( + dataType: T, + peers_ip: string[] + ) => [...syncFromSharedStateAsyncKey, { data_type: dataType, peers_ip }], getFromSharedStateMultiWriter: (dataType: DataTypes) => [ ...getFromSharedStateMultiWriterKey, { data_type: dataType }, diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx index a73fcd179..014bb7955 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx @@ -198,3 +198,10 @@ export type SharedStateReturnType = { data: T; error: number; }; +// Util in order to iterate over the keys of the DataTypeMap +export type CompleteDataTypeKeys = { [K in DataTypes]: true }; +export const completeDataTypeKeys: CompleteDataTypeKeys = { + node_info: true, + wifi_links_info: true, + bat_links_info: true, +}; diff --git a/src/components/icons/teenny/refresh.jsx b/src/components/icons/teenny/refresh.jsx new file mode 100644 index 000000000..2b443694a --- /dev/null +++ b/src/components/icons/teenny/refresh.jsx @@ -0,0 +1,16 @@ +export const RefreshIcon = () => { + return ( + + + + ); +}; From f956ced9d2cbd836cc4f7fed9335c098bc2d59e0 Mon Sep 17 00:00:00 2001 From: selankon Date: Sun, 12 May 2024 05:07:24 -0500 Subject: [PATCH 09/22] chore(meshwideupgrade): improve mesh wide stepper (#418) It improves the screens of the mesh wide stepper steps Implements parallel abort (sync call to abort on multiples nodes) Add button to sync with specific node --- .../src/components/modals.tsx | 107 +++++++++------- .../src/components/nodeUpgradeInfo.tsx | 9 +- .../upgradeState/ConfirmationPending.tsx | 25 ++-- .../src/components/upgradeState/Confirmed.tsx | 29 +++++ .../components/upgradeState/ErrorState.tsx | 20 +-- .../components/upgradeState/LoadingPage.tsx | 10 +- .../upgradeState/NewVersionAvailable.tsx | 88 +++++++++---- .../components/upgradeState/NoNewVersion.tsx | 20 ++- .../upgradeState/TransactionStarted.tsx | 20 ++- .../upgradeState/UpgradeScheduled.tsx | 20 +-- .../{ParallelErrors.tsx => UpgradeState.tsx} | 31 +++++ .../src/containers/meshWideUpgradeStatus.tsx | 3 +- .../src/hooks/meshWideUpgradeProvider.tsx | 53 ++++---- .../src/hooks/useStepper.tsx | 20 +-- .../src/meshUpgradeApi.tsx | 7 ++ .../src/meshUpgradeQueries.tsx | 40 ++++-- .../src/meshUpgradeQueriesKeys.tsx | 2 + .../src/utils/api.ts | 13 +- .../components/FeatureDetail/NodeDetail.tsx | 5 +- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 29 +++-- src/components/PathChart/index.tsx | 119 ++++++++++++++++++ src/components/buttons/button.tsx | 24 +++- src/components/icons/status.tsx | 14 ++- 23 files changed, 523 insertions(+), 185 deletions(-) create mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx rename plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/{ParallelErrors.tsx => UpgradeState.tsx} (54%) create mode 100644 src/components/PathChart/index.tsx diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx index f21e54a44..3357844d0 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx @@ -4,15 +4,58 @@ import { useCallback } from "react"; import { useModal } from "components/Modal/Modal"; +interface IUseParallelQueriesModalProps { + useSuccessBtn?: boolean; + cb?: (e) => void; + title?: VNode; + content?: VNode; + btnTxt?: VNode; +} + +const useParallelQueriesModal = ({ + useSuccessBtn, + cb, + title, + content, + btnTxt = Schedule, +}: IUseParallelQueriesModalProps) => { + const { toggleModal, setModalState } = useModal(); + const runAndClose = useCallback(() => { + cb(null); + toggleModal(); + }, [cb, toggleModal]); + + const showModal = useCallback(() => { + setModalState({ + content, + title, + successCb: useSuccessBtn ? runAndClose : undefined, + deleteCb: !useSuccessBtn ? runAndClose : undefined, + successBtnText: btnTxt, + deleteBtnText: btnTxt, + }); + toggleModal(); + }, [ + setModalState, + content, + title, + useSuccessBtn, + runAndClose, + btnTxt, + toggleModal, + ]); + return { showModal, toggleModal }; +}; + export const useScheduleUpgradeModal = ({ - allNodesReady, + useSuccessBtn, cb, }: IUseParallelQueriesModalProps) => { let title = All nodes are ready; let content = ( Schedule a firmware upgrade for all nodes on the network ); - if (!allNodesReady) { + if (!useSuccessBtn) { title = Some nodes are not ready; content = ( @@ -23,7 +66,7 @@ export const useScheduleUpgradeModal = ({ } return useParallelQueriesModal({ - allNodesReady, + useSuccessBtn, cb, title, content, @@ -31,14 +74,14 @@ export const useScheduleUpgradeModal = ({ }; export const useConfirmModal = ({ - allNodesReady, + useSuccessBtn, cb, }: IUseParallelQueriesModalProps) => { let title = All nodes are upgraded successfully; let content = ( Confirm mesh wide upgrade for all nodes on the network ); - if (!allNodesReady) { + if (!useSuccessBtn) { title = Some nodes don't upgraded properly; content = ( @@ -48,49 +91,27 @@ export const useConfirmModal = ({ ); } return useParallelQueriesModal({ - allNodesReady, + useSuccessBtn, cb, title, content, }); }; -interface IUseParallelQueriesModalProps { - allNodesReady: boolean; - cb?: (e) => void; - title?: VNode; - content?: VNode; -} - -const useParallelQueriesModal = ({ - allNodesReady, - cb, - title, - content, -}: IUseParallelQueriesModalProps) => { - const { toggleModal, setModalState } = useModal(); - const runAndClose = useCallback(() => { - cb(null); - toggleModal(); - }, [cb, toggleModal]); - - const showModal = useCallback(() => { - setModalState({ - content, - title, - successCb: allNodesReady ? runAndClose : undefined, - deleteCb: !allNodesReady ? runAndClose : undefined, - successBtnText: Schedule, - deleteBtnText: Schedule, - }); - toggleModal(); - }, [ - setModalState, - content, +export const useAbortModal = ({ cb }: IUseParallelQueriesModalProps) => { + const title = Abort current mesh wide upgrade?; + const content = ( + + This will the abort current upgrade process on all nodes. Are you + sure you want to proceed? + + ); + const btnTxt = Abort; + return useParallelQueriesModal({ + useSuccessBtn: false, + cb, title, - allNodesReady, - runAndClose, - toggleModal, - ]); - return { showModal, toggleModal }; + content, + btnTxt, + }); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx index 775754693..644909dea 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx @@ -10,6 +10,7 @@ import { detailedInfoStatusMessageMap, mainNodeStatusMessageMap, } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages"; +import UpdateNodeInfoBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn"; export interface INodeInfoBodyItemProps { title: ComponentChildren; @@ -49,7 +50,13 @@ const NodeUpgradeInfoItem = ({ title={name} description={descriptionMsg} leftComponent={} - rightText={"Info"} + rightText={ + + } > {mainNodeStatusInfo && } diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx index 2bc4e62c7..6e10cb934 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx @@ -1,25 +1,32 @@ import { Trans } from "@lingui/macro"; -import { ParallelErrors } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors"; +import { + ParallelErrors, + UpgradeState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; import { useParallelConfirmUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; export const ConfirmationPending = () => { const { errors } = useParallelConfirmUpgrade(); + const title = ( + + Upgraded! +
+ Awaiting confirmation +
+ ); return ( - <> -
- Upgrade done -
-
+ + <> Check if network is working properly and confirm the upgrade
If not confirmed, the upgrade will be rolled back after a while
-
- {errors?.length > 0 && } - + {errors?.length > 0 && } + + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx new file mode 100644 index 000000000..a8e22df13 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx @@ -0,0 +1,29 @@ +import { Trans } from "@lingui/macro"; + +import { + MeshUpgradeErrorIcon, + MeshUpgradeSuccessIcon, + ParallelErrors, + UpgradeState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; +import { useParallelConfirmUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; + +export const Confirmed = () => { + const { errors } = useParallelConfirmUpgrade(); + // let icon =
; + let icon = ; + let title = Confirmed!; + let desc = Mesh upgrade confirmed successfully; + if (errors?.length > 0) { + icon = ; + title = Confirmed with some errors; + desc = Mesh upgrade confirmed with some errors; + } + + return ( + + {desc} + {errors?.length > 0 && } + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx index 186be2212..bb8391712 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx @@ -1,16 +1,18 @@ import { Trans } from "@lingui/macro"; import { VNode } from "preact"; +import { + MeshUpgradeErrorIcon, + UpgradeState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + export const ErrorState = ({ msg }: { msg: string | VNode }) => { return ( -
-
- ! -
-
- Error! -
-
{msg}
-
+ Error!
} + icon={} + > + {msg} + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx index d46b30670..c17078fe4 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx @@ -2,6 +2,8 @@ import { VNode } from "preact"; import Loading from "components/loading"; +import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + export const LoadingPage = ({ title, description, @@ -10,10 +12,8 @@ export const LoadingPage = ({ description?: VNode; }) => { return ( -
- -
{title}
- {description &&
{description}
} -
+ }> + {description} + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx index 2031f2aa5..1fa267cc4 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx @@ -1,6 +1,9 @@ import { Trans } from "@lingui/macro"; +import LineChart, { LineChartStep } from "components/PathChart"; + import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; +import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; import { useBoardData } from "utils/queries"; @@ -12,31 +15,68 @@ export const NewVersionAvailable = ({ const { data: boardData } = useBoardData(); const { data: newVersion } = useNewVersion(); - return ( -
-
- {readyForUpgrade ? ( - Start Mesh Wide Transaction - ) : ( - New version available! - )} -
-
- This node version: -
- {boardData && boardData.release.description} -
-
- New available version: + let steps: LineChartStep[] = [ + { + text: ( + + This node version +
+ {boardData && boardData.release.version} +
+ ), + status: "SUCCESS", + }, + ]; + + if (!readyForUpgrade) { + steps = [ + ...steps, + { + text: ( + + New available version: +
+ {newVersion && newVersion.version} +
+ ), + status: "SUCCESS", + }, + ]; + } else { + steps = [ + ...steps, + { + text: ( + + Downloaded version +
+ {newVersion && newVersion.version} +
+ ), + status: "SUCCESS", + }, + { + text: Start mesh wide upgrade, + status: "SUCCESS", + }, + ]; + } + let title = New version available!; + if (readyForUpgrade) { + title = ( + + Ready to start mesh wide
- {newVersion && newVersion.version} + firmware upgrade +
+ ); + } + + return ( + +
+
- {readyForUpgrade && ( -
- Is ready for upgrade! -
-
- )} -
+ ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx index ed09442ee..4b1638b4c 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx @@ -1,19 +1,15 @@ import { Trans } from "@lingui/macro"; -import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; - -import { useBoardData } from "utils/queries"; +import { + MeshUpgradeSuccessIcon, + UpgradeState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; export const NoNewVersionAvailable = () => { - const { data: boardData } = useBoardData(); - const { data: newVersion } = useNewVersion(); - return ( -
-
-
- No new version available! -
-
+ No new version available!} + icon={} + /> ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx index 63de80451..50d72f2fb 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx @@ -1,17 +1,27 @@ +import { Trans } from "@lingui/macro"; + +import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; export const TransactionStarted = () => { const { someNodeDownloading } = useMeshUpgrade(); + const title = ( +
+ Mesh wide upgrade started! +
+ ); return ( -
- Transaction started! + {someNodeDownloading && (
- Some nodes seems to be downloading, check network page for - more information + + Some nodes are still downloading the firmware +
+ check network page for more information +
)} -
+
); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx index ac2a9a1f6..ed9d15efb 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx @@ -1,25 +1,25 @@ import { Trans } from "@lingui/macro"; -import { ParallelErrors } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors"; +import { + ParallelErrors, + UpgradeState, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; import { useParallelScheduleUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; export const UpgradeScheduled = () => { const { totalNodes } = useMeshUpgrade(); const { errors, results } = useParallelScheduleUpgrade(); - const nodesToBeUpgraded = results.length; + const nodesToBeUpgraded = results?.length; return ( - <> -
- Upgrade is scheduled! -
-
+ Upgrade is scheduled!}> + <> {nodesToBeUpgraded} of {totalNodes} will be upgraded -
- {errors?.length > 0 && } - + {errors?.length > 0 && } + + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx similarity index 54% rename from plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx rename to plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx index ce30e1035..3e98c37e9 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ParallelErrors.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx @@ -1,9 +1,32 @@ import { Trans } from "@lingui/macro"; +import { ComponentChildren } from "preact"; +import { GlobeIcon } from "components/icons/globeIcon"; +import { Tick, Warning } from "components/icons/status"; import { StatusMessage } from "components/status/statusMessage"; import { RemoteNodeCallError, SyncCallErrors } from "utils/meshWideSyncCall"; +interface UpgradeStateProps { + icon?: ComponentChildren; + title: ComponentChildren; + children?: ComponentChildren; +} + +export const UpgradeState = ({ + icon = , + title, + children, +}: UpgradeStateProps) => { + return ( +
+ {icon} +
{title}
+ {children &&
{children}
} +
+ ); +}; + export const ParallelErrors = ({ errors }: { errors: SyncCallErrors }) => { return ( // Important to not add any style to this fragment because could add errors on growing on long lists @@ -26,3 +49,11 @@ export const ParallelErrors = ({ errors }: { errors: SyncCallErrors }) => { ); }; + +export const MeshUpgradeSuccessIcon = () => { + return ; +}; + +export const MeshUpgradeErrorIcon = () => { + return ; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx index 036ab60cf..8588d8d16 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx @@ -1,6 +1,7 @@ import { Trans } from "@lingui/macro"; import { ConfirmationPending } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending"; +import { Confirmed } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed"; import { ErrorState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState"; import { LoadingPage } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage"; import { NewVersionAvailable } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable"; @@ -65,7 +66,7 @@ const MeshWideUpgradeStatusState = () => { case "CONFIRMATION_PENDING": return ; case "CONFIRMED": - return <>Confirmed!; + return ; default: return ; } diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx index 3c52b1224..9692e98f2 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx @@ -1,15 +1,15 @@ import { ComponentChildren, createContext } from "preact"; import { useMemo } from "preact/compat"; -import { useEffect } from "preact/hooks"; +import { useEffect, useState } from "preact/hooks"; import { useCallback, useContext } from "react"; import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; import { getStepperStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper"; import { - useAbort, useBecomeMainNode, useMeshUpgradeNodeStatus, useMeshWideUpgradeInfo, + useParallelAbort, useParallelConfirmUpgrade, useParallelScheduleUpgrade, useStartFirmwareUpgradeTransaction, @@ -70,7 +70,7 @@ export const MeshWideUpgradeProvider = ({ }) => { // UseCallback to invalidate queries const invalidateQueries = useCallback(() => { - queryCache.invalidateQueries({ + return queryCache.invalidateQueries({ queryKey: meshUpgradeQueryKeys.getMeshUpgradeNodeStatus(), }); }, []); @@ -90,21 +90,15 @@ export const MeshWideUpgradeProvider = ({ refetchInterval: NODE_STATUS_REFETCH_INTERVAL, }); - const { mutate: becomeMainNodeMutation } = useBecomeMainNode({ - onSuccess: () => { - invalidateQueries(); - }, - }); + const { mutateAsync: becomeMainNodeMutation } = useBecomeMainNode({}); - const { mutate: fwUpgradeTransaction } = useStartFirmwareUpgradeTransaction( - { - onSuccess: () => { - invalidateQueries(); - }, - } - ); + const { mutateAsync: fwUpgradeTransaction } = + useStartFirmwareUpgradeTransaction({}); - const { mutate: abort, isLoading: isAborting } = useAbort({}); + // Inner state to control is aborting callback awaiting until query invalidation + const [isAborting, setIsAborting] = useState(false); + // const { mutateAsync: abortMutation } = useAbort({}); + const { callMutations: abortMutation } = useParallelAbort(); const { data: session } = useSession(); const { data: newVersionData } = useNewVersion({ @@ -161,13 +155,26 @@ export const MeshWideUpgradeProvider = ({ const meshWideError = getMeshWideError(thisNode); - const becomeMainNode = useCallback(() => { - becomeMainNodeMutation({}); - }, [becomeMainNodeMutation]); - - const startFwUpgradeTransaction = useCallback(() => { - fwUpgradeTransaction({}); - }, [fwUpgradeTransaction]); + const becomeMainNode = useCallback(async () => { + await becomeMainNodeMutation({}); + await invalidateQueries(); + }, [becomeMainNodeMutation, invalidateQueries]); + + const startFwUpgradeTransaction = useCallback(async () => { + await fwUpgradeTransaction({}); + await invalidateQueries(); + }, [fwUpgradeTransaction, invalidateQueries]); + + const abort = useCallback(async () => { + setIsAborting(true); + abortMutation() + .then(() => { + return invalidateQueries(); + }) + .finally(() => { + setIsAborting(false); + }); + }, [abortMutation, invalidateQueries]); const isLoading = meshWideInfoLoading || thisNodeLoading; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx index 8b8a351de..65e376640 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx @@ -4,6 +4,7 @@ import { useMemo } from "react"; import { IStatusAndButton } from "components/status/statusAndButton"; import { + useAbortModal, useConfirmModal, useScheduleUpgradeModal, } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; @@ -144,21 +145,26 @@ export const useStep = () => { const { callMutations: startScheduleMeshUpgrade, errors: scheduleErrors } = useParallelScheduleUpgrade(); - const { callMutations: confirmMeshUpgrade, errors: confirmErrors } = - useParallelConfirmUpgrade(); + const { callMutations: confirmMeshUpgrade } = useParallelConfirmUpgrade(); const { showModal: showScheduleModal } = useScheduleUpgradeModal({ - allNodesReady: allNodesReadyForUpgrade, + useSuccessBtn: allNodesReadyForUpgrade, cb: () => { - startScheduleMeshUpgrade(); + return startScheduleMeshUpgrade(); }, }); const { showModal: showConfirmationModal } = useConfirmModal({ // Ideally we have to implement some kind of state before run the upgrade to check if all nodes are up again. - allNodesReady: true, + useSuccessBtn: true, cb: () => { - confirmMeshUpgrade(); + return confirmMeshUpgrade(); + }, + }); + + const { showModal: showAbortModal } = useAbortModal({ + cb: () => { + return abort(); }, }); @@ -249,7 +255,7 @@ export const useStep = () => { > = { btnCancel: Abort, onClickCancel: async () => { - await abort(); + showAbortModal(); }, }; step = { ...step, ...showAbort }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx index 4704d3410..ca55bd97f 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx @@ -59,6 +59,13 @@ export async function remoteConfirmUpgrade({ ip }: { ip: string }) { }); } +export async function remoteAbort({ ip }: { ip: string }) { + return await callToRemoteNode({ + ip, + apiCall: (customApi) => meshUpgradeApiCall("abort", customApi), + }); +} + const meshUpgradeApiCall = async ( method: string, customApi?: UhttpdService diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx index 1a0894e6d..d31e86aba 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries.tsx @@ -3,9 +3,9 @@ import { useMutation, useQuery } from "@tanstack/react-query"; import { getMeshUpgradeNodeStatus, getMeshWideUpgradeInfo, + remoteAbort, remoteConfirmUpgrade, remoteScheduleUpgrade, - setAbort, setBecomeMainNode, setStartFirmwareUpgradeTransaction, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi"; @@ -14,7 +14,7 @@ import { MeshWideUpgradeInfo, NodeMeshUpgradeInfo, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; -import { getNodeIpsByStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; +import { getNodeIpsByCondition } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; import { useMeshWideSyncCall } from "utils/meshWideSyncCall"; @@ -56,13 +56,6 @@ export function useStartFirmwareUpgradeTransaction(params) { }); } -export function useAbort(params) { - return useMutation({ - mutationFn: setAbort, - ...params, - }); -} - // Parallel queries/mutations export type UseScheduleMeshSafeUpgradeType = ReturnType< @@ -71,7 +64,10 @@ export type UseScheduleMeshSafeUpgradeType = ReturnType< export const useParallelScheduleUpgrade = (opts?) => { // State to store the errors const { data: nodes } = useMeshWideUpgradeInfo({}); - const ips = getNodeIpsByStatus(nodes, "READY_FOR_UPGRADE"); + const ips = getNodeIpsByCondition( + nodes, + (node) => node.upgrade_state === "READY_FOR_UPGRADE" + ); // localStorage.setItem("hideReleaseBannerPlease", value); return useMeshWideSyncCall({ mutationKey: meshUpgradeQueryKeys.remoteScheduleUpgrade(), @@ -87,7 +83,10 @@ export type UseConfirmUpgradeType = ReturnType< export const useParallelConfirmUpgrade = (opts?) => { // State to store the errors const { data: nodes } = useMeshWideUpgradeInfo({}); - const ips = getNodeIpsByStatus(nodes, "CONFIRMATION_PENDING"); + const ips = getNodeIpsByCondition( + nodes, + (node) => node.upgrade_state === "CONFIRMATION_PENDING" + ); return useMeshWideSyncCall({ mutationKey: meshUpgradeQueryKeys.remoteConfirmUpgrade(), mutationFn: remoteConfirmUpgrade, @@ -95,3 +94,22 @@ export const useParallelConfirmUpgrade = (opts?) => { options: opts, }); }; + +export const useParallelAbort = (opts?) => { + // State to store the errors + const { data: nodes } = useMeshWideUpgradeInfo({}); + const ips = getNodeIpsByCondition(nodes, (node) => + [ + "READY_FOR_UPGRADE", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(node.upgrade_state) + ); + return useMeshWideSyncCall({ + mutationKey: meshUpgradeQueryKeys.remoteAbort(), + mutationFn: remoteAbort, + ips, + options: opts, + }); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx index dc947d179..fc54018d5 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx @@ -9,6 +9,7 @@ const MeshUpgradeQueryKeys: MeshUpgradeQueryKeysProps = { getMeshUpgradeNodeStatus: ["lime-mesh-upgrade", "get_node_status"], remoteScheduleUpgrade: ["lime-mesh-upgrade", "schedule_upgrade"], remoteConfirmUpgrade: ["lime-mesh-upgrade", "confirm_boot_partition"], + remoteAbort: ["lime-mesh-upgrade", "abort"], }; export const meshUpgradeQueryKeys = { @@ -20,4 +21,5 @@ export const meshUpgradeQueryKeys = { MeshUpgradeQueryKeys.remoteScheduleUpgrade, remoteConfirmUpgrade: (): QueryKey => MeshUpgradeQueryKeys.remoteConfirmUpgrade, + remoteAbort: (): QueryKey => MeshUpgradeQueryKeys.remoteConfirmUpgrade, }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts index 64c6e5ab3..76c7d267a 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts @@ -1,7 +1,7 @@ import { MeshUpgradeApiErrorTypes, MeshWideUpgradeInfo, - UpgradeStatusType, + NodeMeshUpgradeInfo, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; import { RemoteNodeCallError } from "utils/meshWideSyncCall"; @@ -21,13 +21,14 @@ export class MeshUpgradeApiError extends Error { } /** - * From a MeshWideUpgradeInfo nodes it returns the ips of the nodes that are in certain status provided + * From a MeshWideUpgradeInfo nodes it returns the ips of the nodes that match the condition defined on the function * @param nodes the nodes to check - * @param status the status to check the criteria + * @param condition function that receives a NodeMeshUpgradeInfo and returns a boolean */ -export const getNodeIpsByStatus = ( +export const getNodeIpsByCondition = ( nodes: MeshWideUpgradeInfo, - status: UpgradeStatusType + // status: UpgradeStatusType + condition: (node: NodeMeshUpgradeInfo) => boolean ) => { if (!nodes) return []; return Object.values(nodes) @@ -36,7 +37,7 @@ export const getNodeIpsByStatus = ( node.node_ip !== null && node.node_ip !== undefined && node.node_ip.trim() !== "" && - node.upgrade_state === status + condition(node) ) .map((node) => node.node_ip as string); // 'as string' is safe here due to the filter condition }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index 06596cf91..0357bc4f9 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -42,7 +42,10 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => {
{name}
- +
diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx index b8a8b9dbc..3d3e80e32 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -13,17 +13,25 @@ import { import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { DataTypes, - INodeInfo, completeDataTypeKeys, } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; import queryCache from "utils/queryCache"; -const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { - const ip = node.ipv4; +interface INodeInfoProps { + ip: string; + nodeName: string; +} +const UpdateNodeInfoBtn = ({ + ip, + nodeName, + updateOnMount = true, +}: { + updateOnMount?: boolean; +} & INodeInfoProps) => { const [isLoading, setIsLoading] = useState(false); - const { showToast, hideToast } = useToast(); + const { showToast } = useToast(); const { mutateAsync: localNodeSync } = useSyncDataTypes({ ip, @@ -52,7 +60,7 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { showToast({ text: ( - Error connecting with {node.hostname}, is node up? + Error connecting with {nodeName}, is node up? ), duration: 5000, @@ -71,25 +79,30 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { ip, isLoading, localNodeSync, - node.hostname, + nodeName, publishOnRemoteNode, showToast, ]); // Use effect to sync the node data on mount useEffect(() => { + if (!updateOnMount) return; (async () => { await syncNode(); })(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [node.ipv4]); + }, [ip]); return ( diff --git a/src/components/PathChart/index.tsx b/src/components/PathChart/index.tsx new file mode 100644 index 000000000..c88351717 --- /dev/null +++ b/src/components/PathChart/index.tsx @@ -0,0 +1,119 @@ +import { ComponentChildren } from "preact"; +import React from "react"; + +import { GlobeIcon } from "components/icons/globeIcon"; +import LoadingDots from "components/loading/loading-dots"; + +type StepStatus = "SUCCESS" | "ERROR" | "DISABLED"; + +export type LineChartStep = { + text: ComponentChildren; + isLoading?: boolean; + status: StepStatus; +}; + +type CircleProps = { + index: number; + color?: string; + className?: string; + isLast?: boolean; + nextStep?: CircleProps; // Used to get the correct color of the line +} & LineChartStep; + +const getColorByStatus = (step?: CircleProps) => { + let color = "gray-400"; + let lineColor = `bg-gray-400`; + if (step?.status === "SUCCESS") { + if (step.isLast) { + color = "internet"; + lineColor = `bg-internet`; + } else { + color = "primary-dark"; + lineColor = `bg-primary-dark`; + } + } else if (step?.status === "ERROR") { + if (step.isLast) { + color = "danger"; + } else { + color = "danger"; + lineColor = `bg-danger`; + } + } + return { color, lineColor }; +}; + +const LineBall = ({ ...step }: CircleProps) => { + const { color } = getColorByStatus(step); + const { lineColor } = getColorByStatus(step.nextStep); + + const linePart = "h-14"; + + return ( +
+
+ {step.isLast ? ( + + ) : ( +
+ )} +
+
+
+ ); +}; + +const Step = ({ index, ...step }: CircleProps) => { + let color = "gray-400"; + if (step.isLast) { + color = "text-internet"; + } else if (step.status === "SUCCESS") { + color = "text-primary-dark"; + } else if (step.status === "ERROR") { + color = "text-danger"; + } + + const loadingIndicator = step.isLoading ? : null; + + return ( +
+ + + {step.text} {loadingIndicator} + +
+ ); +}; + +function LineChart({ steps }: { steps: LineChartStep[] }) { + if (!steps) return null; + return ( +
+ {steps.map((step, index) => { + const nextStep = steps[index + 1] ?? null; + return ( + + ); + })} +
+ ); +} + +export default LineChart; diff --git a/src/components/buttons/button.tsx b/src/components/buttons/button.tsx index c57255d52..319a674cc 100644 --- a/src/components/buttons/button.tsx +++ b/src/components/buttons/button.tsx @@ -1,7 +1,7 @@ -import React from "react"; +import React, { useCallback } from "react"; export interface ButtonProps { - onClick?: (e) => void; + onClick?: ((e) => void) | ((e) => Promise); children?: any; // type error with Trans component size?: "sm" | "md" | "lg"; color?: "primary" | "secondary" | "danger" | "info" | "disabled"; @@ -20,6 +20,9 @@ export const Button = ({ outline = false, ...props }: ButtonProps) => { + // button internal state to set loading state + const [isLoading, setIsLoading] = React.useState(false); + let sizeClasses = "", colorClasses = ""; switch (size) { @@ -34,7 +37,7 @@ export const Button = ({ break; } - color = disabled ? "disabled" : color; + color = disabled || isLoading ? "disabled" : color; switch (color) { case "secondary": @@ -55,7 +58,7 @@ export const Button = ({ case "disabled": colorClasses = outline ? "border-2 border-button-disabled text-button-disabled hover:bg-button-disabled hover:text-white" - : "bg-button-disabled text-white border-2 border-button-disabled hover:text-button-disabled hover:bg-white"; + : "bg-button-disabled border-2 border-button-disabled hover:text-button-disabled hover:bg-white"; break; case "primary": default: @@ -67,10 +70,21 @@ export const Button = ({ const cls = `cursor-pointer font-semibold rounded-xl text-center place-content-center transition-all duration-300 justify-center border-0 ${sizeClasses} ${colorClasses}`; + + // useCallback for button click + const handleClick = useCallback( + async (e) => { + if (isLoading || disabled) return; + setIsLoading(true); + await onClick(e); + setIsLoading(false); + }, + [disabled, isLoading, onClick] + ); const Btn = () => (
(!disabled ? onClick(e) : null)} + onClick={(e) => handleClick(e)} className={cls} {...props} > diff --git a/src/components/icons/status.tsx b/src/components/icons/status.tsx index 684d146de..82ca516f5 100644 --- a/src/components/icons/status.tsx +++ b/src/components/icons/status.tsx @@ -14,13 +14,17 @@ export const StatusIcon = ({ status }: { status: StatusIcons }) => { } }; -export const Tick = () => ; +interface IconsProps { + className?: string; +} -export const Warning = () => ( +export const Tick = ({ className }: IconsProps) => ( + +); + +export const Warning = ({ className = "w-8 h-8" }: IconsProps) => ( ! From 390936723c7b35d7dcf582602b9f1c59be659e25 Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 13 Jun 2024 02:29:46 -0500 Subject: [PATCH 10/22] Use shared state async to store reference state (#422) * chore(meshwide): refactor link datatype * chore(meshwide): implement reference state using async * chore(meshwide): disable set reference state from errors types * chore(components): update toast default duration * chore(meshwide): implement set reference state * chore(meshwide): implement modal key * chore(meshwide): use correct link keys * chore(meshwide): implement connection error toast * chore(components): fix isLoading state onError * chore(meshwide): split sync to node logic * chore(meshwide): fix node is really down * chore(meshwide): sync after set reference * chore(meshwide): implement channel * chore(meshwide): add new node to mocks * chore(meshwide): change representation of new nodes * chore(meshwide): add channel to mocks * chore(meshwide): prevent show stored errors * chore(meshwide): increase timer * chore(meshwide): fix reference is not set * chore(meshwide): fix link is not new * chore(meshwide): add new node label * chore(meshwide): show actual state on node info --- .../src/hooks/meshWideUpgradeProvider.tsx | 2 +- .../components/FeatureDetail/LinkDetail.tsx | 69 +- .../components/FeatureDetail/NodeDetail.tsx | 75 +- .../FeatureDetail/RebootNodeBtn.tsx | 17 +- .../FeatureDetail/SetReferenceStateBtn.tsx | 69 -- .../FeatureDetail/ShowErrorsDetail.tsx | 25 +- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 88 +- .../src/components/Map/LinkLine.tsx | 18 +- .../src/components/Map/NodeMarker.tsx | 16 +- .../src/components/Map/style.less | 16 + .../components/configPage/ConfigSection.tsx | 3 - .../src/components/configPage/MeshStatus.tsx | 1 - .../src/components/configPage/OptionForm.tsx | 2 - .../src/components/configPage/modals.tsx | 75 +- .../src/hooks/useLocatedLinks.tsx | 21 +- .../src/hooks/useMeshWideDataErrors.tsx | 39 +- .../src/hooks/useSyncWithNode.tsx | 78 ++ .../src/lib/links/PointToPointLink.ts | 57 +- .../src/lib/links/getLinksCoordinates.ts | 45 +- .../src/lib/links/processLinkErrors.ts | 28 +- .../lime-plugin-mesh-wide/src/meshWideApi.ts | 52 +- .../src/meshWideMocks.tsx | 944 ++---------------- .../src/meshWideQueries.tsx | 159 +-- .../src/meshWideQueriesKeys.tsx | 40 +- .../src/meshWideTypes.tsx | 14 +- src/components/Modal/Modal.tsx | 11 +- src/components/buttons/button.tsx | 21 +- src/components/toast/index.tsx | 2 +- src/components/toast/toasts.tsx | 20 + 29 files changed, 728 insertions(+), 1279 deletions(-) delete mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx create mode 100644 plugins/lime-plugin-mesh-wide/src/hooks/useSyncWithNode.tsx create mode 100644 src/components/toast/toasts.tsx diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx index 9692e98f2..9814a4b7b 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider.tsx @@ -26,7 +26,7 @@ import { getMeshWideError } from "plugins/lime-plugin-mesh-wide-upgrade/src/util import { useSession } from "utils/queries"; import queryCache from "utils/queryCache"; -const NODE_STATUS_REFETCH_INTERVAL = 2000; +const NODE_STATUS_REFETCH_INTERVAL = 5000; interface MeshWideUpgradeContextProps { data?: MeshWideUpgradeInfo; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index 7436f2ebf..79b994fca 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -1,17 +1,20 @@ import { Trans } from "@lingui/macro"; import { useState } from "preact/hooks"; +import { useCallback } from "react"; import { Warning } from "components/icons/status"; import Tabs from "components/tabs"; +import { useToast } from "components/toast/toastProvider"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; -import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; +import { useSetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; import { getQueryByLinkType, usePointToPointErrors, } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; import { MacToMacLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; import { readableBytes } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; +import { useSetLinkReferenceState } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; import { BaseMacToMacLink, BatmanLinkErrorCodes, @@ -99,6 +102,9 @@ const WifiDetail = ({ > {node?.chains?.toString() ?? "0/0"} + Channel}> + {node?.channel?.toString() ?? "0"} + TxRate}> @@ -221,6 +227,8 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { type: reference.type, }); + const isDown = !errors.linkUp; + // Check if there are errors of global reference state to shown const { reference: fetchDataReference } = getQueryByLinkType( reference.type @@ -232,8 +240,63 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { referenceError = true; } + const { toggleModal, confirmModal, isModalOpen } = + useSetLinkReferenceStateModal(); + const { showToast } = useToast(); + // Mutation to update the reference state - const { mutate, btnText } = useSetReferenceState(reference.type); + const nodesToUpdate = reference.nodes.reduce((acc, node) => { + acc[node.ipv4] = node.hostname; + return acc; + }, {}); + const { callMutations } = useSetLinkReferenceState({ + linkType: reference.type, + linkToUpdate: reference, + isDown, + nodesToUpdate, + params: { + onSuccess: () => { + showToast({ + text: New reference state set!, + }); + }, + onError: () => { + showToast({ + text: Error setting new reference state!, + }); + }, + onSettled: () => { + if (isModalOpen) toggleModal(); + }, + }, + }); + + const setReferenceState = useCallback(async () => { + confirmModal( + reference.type, + Object.values(nodesToUpdate), + isDown, + async () => { + await callMutations(); + } + ); + }, [callMutations, confirmModal, isDown, nodesToUpdate, reference.type]); + + let btnText = ( + + Set reference state for this +
{reference.type} link +
+ ); + if (isDown) { + btnText = ( + + Delete this {reference.type} link +
+ from reference state +
+ ); + } let errorMessage = Same status as in the reference state; if (referenceError) { @@ -252,7 +315,7 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { {errorMessage} diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index 0357bc4f9..a742a3f66 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -1,16 +1,23 @@ import { Trans } from "@lingui/macro"; +import { useCallback } from "react"; + +import { useToast } from "components/toast/toastProvider"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; import RemoteRebootBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn"; -import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; import UpdateNodeInfoBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn"; import { Row, TitleAndText, } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; +import { useSetNoeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors"; +import useSyncWithNode from "plugins/lime-plugin-mesh-wide/src/hooks/useSyncWithNode"; import { getArrayDifference } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; -import { useMeshWideNodesReference } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { + useMeshWideNodesReference, + useSetNodeInfoReferenceState, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; import { NodeErrorCodes, NodeMapFeature, @@ -19,14 +26,6 @@ import { import { isEmpty } from "utils/utils"; const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => { - // If node no reference is set, is a new node - const nodeToShow = reference ?? actual; - - const uptime = nodeToShow.uptime; - const firmware = nodeToShow.firmware_version; - const ipv6 = nodeToShow.ipv6; - const ipv4 = nodeToShow.ipv4; - const device = nodeToShow.device; const { errors, isDown } = useSingleNodeErrors({ actual, reference, @@ -35,6 +34,12 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => { if (isDown) { return This node seems down; } + + const uptime = actual.uptime; + const firmware = actual.firmware_version; + const ipv6 = actual.ipv6; + const ipv4 = actual.ipv4; + const device = actual.device; const macs = actual.macs; return ( @@ -43,10 +48,11 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => {
{name}
- +
@@ -111,12 +117,51 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { reference, }); + const hostname = isDown ? reference.hostname : actual.hostname; + const ip = isDown ? reference.ipv4 : actual.ipv4; + // Check if there are errors of global reference state to shown const { data: meshWideNodesReference, isError: isReferenceError } = useMeshWideNodesReference({}); + const { toggleModal, confirmModal, isModalOpen } = + useSetNoeInfoReferenceStateModal(); + const { showToast } = useToast(); + const { syncNode } = useSyncWithNode({ ip, nodeName: hostname }); + // Mutation to update the reference state - const { mutate, btnText } = useSetReferenceState("node_info"); + const { mutateAsync } = useSetNodeInfoReferenceState({ + ip, + hostname, + isDown, + params: { + onSuccess: async () => { + await syncNode(); + showToast({ + text: New reference state set!, + }); + }, + onError: () => { + showToast({ + text: Error setting new reference state!, + }); + }, + onSettled: () => { + if (isModalOpen) toggleModal(); + }, + }, + }); + + const setReferenceState = useCallback(async () => { + confirmModal(hostname, isDown, async () => { + await mutateAsync(); + }); + }, [confirmModal, hostname, isDown, mutateAsync]); + + let btnText = Set reference state for this node; + if (isDown) { + btnText = Delete this this node from reference state; + } let referenceError = false; if ( @@ -144,7 +189,7 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { {errorMessage} diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx index 8704c8b3e..c35db8f40 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx @@ -7,6 +7,7 @@ import { useModal } from "components/Modal/Modal"; import { Button } from "components/buttons/button"; import { ErrorMsg } from "components/form"; import Loading from "components/loading"; +import { useErrrorConnectionToast } from "components/toast/toasts"; import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; import { PowerIcon } from "plugins/lime-plugin-mesh-wide/src/icons/power"; @@ -28,18 +29,24 @@ export async function remoteReboot({ ip, password }: IRemoteRebotProps) { } const useRemoteReboot = (opts?) => { + const { show } = useErrrorConnectionToast(); return useMutation((props: IRemoteRebotProps) => remoteReboot(props), { mutationKey: ["system", "reboot"], + onError: (error, variables) => { + show(variables.ip); + }, ...opts, }); }; const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { - const { toggleModal, setModalState, isModalOpen } = useModal(); + const modalKey = "rebootNodeModal"; + const { toggleModal, setModalState, isModalOpen, openModalKey } = + useModal(); const [password, setPassword] = useState(""); const { mutate, isLoading, error } = useRemoteReboot({ onSuccess: () => { - toggleModal(); + toggleModal(modalKey); }, }); @@ -91,15 +98,15 @@ const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { const rebootModal = useCallback(() => { updateModalState(); - toggleModal(); + toggleModal(modalKey); }, [toggleModal, updateModalState]); // Update modal state with mutation result useEffect(() => { - if (isModalOpen) { + if (isModalOpen && openModalKey === modalKey) { updateModalState(); } - }, [isLoading, error, isModalOpen, updateModalState]); + }, [isLoading, error, isModalOpen, updateModalState, openModalKey]); return { rebootModal, toggleModal, isModalOpen }; }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx deleted file mode 100644 index fda447598..000000000 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Trans } from "@lingui/macro"; -import { useCallback } from "react"; - -import { useToast } from "components/toast/toastProvider"; - -import { useSetReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; -import { - useSetBatmanLinksInfoReferenceState, - useSetNodeInfoReferenceState, - useSetWifiLinksInfoReferenceState, -} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; -import { DataTypes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; - -const toastDuration = 5000; - -export const useSetReferenceState = (dataType: T) => { - const { toggleModal, confirmModal, isModalOpen } = - useSetReferenceStateModal(); - const { showToast } = useToast(); - - const mutationOpts = { - onSuccess: () => { - showToast({ - text: New reference state set!, - duration: toastDuration, - }); - }, - onError: () => { - showToast({ - text: Error setting new reference state!, - duration: toastDuration, - }); - }, - onSettled: () => { - if (isModalOpen) toggleModal(); - }, - }; - - const { mutateAsync: nodesMutation } = - useSetNodeInfoReferenceState(mutationOpts); - const { mutateAsync: wifiMutation } = - useSetWifiLinksInfoReferenceState(mutationOpts); - const { mutateAsync: batmanMutation } = - useSetBatmanLinksInfoReferenceState(mutationOpts); - - const btnText = Set {dataType} reference state; - - const mutate = useCallback(async () => { - switch (dataType) { - case "node_info": - await confirmModal(dataType, async () => { - await nodesMutation(); - }); - break; - case "wifi_links_info": - confirmModal(dataType, async () => { - await wifiMutation(); - }); - break; - case "bat_links_info": - confirmModal(dataType, async () => { - await batmanMutation(); - }); - break; - } - }, [batmanMutation, confirmModal, dataType, nodesMutation, wifiMutation]); - - return { mutate, btnText }; -}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx index 50e727333..47ff61d68 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx @@ -1,23 +1,7 @@ import { Trans } from "@lingui/macro"; -import { Button } from "components/buttons/button"; - -import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; import { Row } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; -import { - DataTypes, - ErrorsDetails, -} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; - -const SetDataTypeBtn = ({ dataType }: { dataType: T }) => { - const { mutate, btnText } = useSetReferenceState(dataType); - return ( -
-
{dataType}
- -
- ); -}; +import { ErrorsDetails } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; export const ShowErrorsDetail = ({ errors }: { errors: ErrorsDetails }) => { return ( @@ -70,7 +54,12 @@ export const ShowErrorsDetail = ({ errors }: { errors: ErrorsDetails }) => { ); } return ( - +
+ + Reference state is not set for{" "} + {dataType} + +
); })}
diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx index 3d3e80e32..3f3fd41cd 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -1,27 +1,11 @@ -import { Trans } from "@lingui/macro"; -import { useEffect, useState } from "preact/hooks"; -import { useCallback } from "react"; +import { useEffect } from "preact/hooks"; import { Button } from "components/buttons/button"; import { RefreshIcon } from "components/icons/teenny/refresh"; -import { useToast } from "components/toast/toastProvider"; -import { - usePublishOnRemoteNode, - useSyncDataTypes, -} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; -import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; -import { - DataTypes, - completeDataTypeKeys, -} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; - -import queryCache from "utils/queryCache"; - -interface INodeInfoProps { - ip: string; - nodeName: string; -} +import useSyncWithNode, { + ISyncWithNodeProps, +} from "plugins/lime-plugin-mesh-wide/src/hooks/useSyncWithNode"; const UpdateNodeInfoBtn = ({ ip, @@ -29,60 +13,8 @@ const UpdateNodeInfoBtn = ({ updateOnMount = true, }: { updateOnMount?: boolean; -} & INodeInfoProps) => { - const [isLoading, setIsLoading] = useState(false); - const { showToast } = useToast(); - - const { mutateAsync: localNodeSync } = useSyncDataTypes({ - ip, - }); - const { mutateAsync: publishOnRemoteNode } = usePublishOnRemoteNode({ - ip, - }); - - const invalidateQueries = useCallback(() => { - for (const dataType of Object.keys( - completeDataTypeKeys - ) as DataTypes[]) { - queryCache.invalidateQueries({ - queryKey: - getFromSharedStateKeys.getFromSharedStateAsync(dataType), - }); - } - }, []); - - // useCallback to sync the node data - const syncNode = useCallback(async () => { - if (isLoading) return; - setIsLoading(true); - publishOnRemoteNode({ ip }) - .catch((e) => { - showToast({ - text: ( - - Error connecting with {nodeName}, is node up? - - ), - duration: 5000, - }); - throw e; - }) - .then(async () => { - await localNodeSync({ ip }); - await invalidateQueries(); - }) - .finally(() => { - setIsLoading(false); - }); - }, [ - invalidateQueries, - ip, - isLoading, - localNodeSync, - nodeName, - publishOnRemoteNode, - showToast, - ]); +} & ISyncWithNodeProps) => { + const { syncNode, isLoading } = useSyncWithNode({ ip, nodeName }); // Use effect to sync the node data on mount useEffect(() => { @@ -90,18 +22,20 @@ const UpdateNodeInfoBtn = ({ (async () => { await syncNode(); })(); + // Avoid executing the effect on updateOnMount change // eslint-disable-next-line react-hooks/exhaustive-deps }, [ip]); return (
diff --git a/plugins/lime-plugin-rx/src/sections/system.tsx b/plugins/lime-plugin-rx/src/sections/system.tsx new file mode 100644 index 000000000..25315e304 --- /dev/null +++ b/plugins/lime-plugin-rx/src/sections/system.tsx @@ -0,0 +1,85 @@ +import { Trans, plural, t } from "@lingui/macro"; +import { Fragment } from "preact"; + +import { + IconsClassName, + Section, + SectionTitle, +} from "plugins/lime-plugin-rx/src/components/components"; +import { GearIcon } from "plugins/lime-plugin-rx/src/icons/gearIcon"; +import { useNodeStatus } from "plugins/lime-plugin-rx/src/rxQueries"; + +import { useBoardData } from "utils/queries"; +import { IGetBoardDataResponse } from "utils/types"; + +const toHHMMSS = (seconds: string, plus: number) => { + const secNum = parseInt(seconds, 10) + plus; + const days = Math.floor(secNum / 86400); + const hours = Math.floor(secNum / 3600) % 24; + const mins = Math.floor(secNum / 60) % 60; + const secs = secNum % 60; + const daysText = days + ? plural(days, { one: "# day", other: "# days" }) + : null; + const hoursText = hours + ? plural(hours, { one: "# hour", other: "# hours" }) + : null; + const minsText = mins + ? plural(mins, { one: "# minute", other: "# minutes" }) + : null; + const secsText = secs + ? plural(secs, { one: "# second", other: "# seconds" }) + : null; + const allTexts = [daysText, hoursText, minsText, secsText]; + return allTexts.filter((x) => x !== null).join(", "); +}; + +const SystemInfo = () => { + const { data: node } = useNodeStatus(); + const { data: bd } = useBoardData(); + + const boardData = bd as IGetBoardDataResponse; + const secNum = parseInt(node?.uptime, 10); + const attributes = [ + { + label: t`Uptime`, + value: toHHMMSS(node?.uptime, 0), + }, + { label: t`Device`, value: boardData.board_name }, + { label: t`Firmware`, value: boardData.release.description }, + ]; + return ( +
+
+ {attributes.map((attribute, i) => ( + +
+ {attribute.label}: +
+
+ {attribute.value} +
+
+ ))} +
+
+ ); +}; + +export const System = () => { + const { isLoading: isLoadingNodeStatus } = useNodeStatus(); + const { isLoading: isLoadingBoardData } = useBoardData(); + + const isLoading = isLoadingBoardData || isLoadingNodeStatus; + + return ( +
+ }> + System + +
+ {isLoading ? Loading... : } +
+
+ ); +}; diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 000000000..3e9094aa7 --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,15 @@ +export interface IGetBoardDataResponse { + kernel: string; + hostname: string; + system: string; + model: string; + board_name: string; + rootfs_type: string; + release: { + distribution: string; + version: string; + revision: string; + target: string; + description: string; + }; +} From 75c87fc7c0b379cbb3c73b1b6755ebd907f8dfb7 Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 4 Sep 2024 10:15:57 -0500 Subject: [PATCH 14/22] Hotfix mesh map (#448) * chore(mesh-wide): prevent empty objects * chore(mesh-wide): prevent undefined * chore(mesh-wide): improve isEmpty --- .../src/lib/links/getLinksCoordinates.ts | 14 +++++++++----- src/utils/utils.tsx | 7 ++++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts index 26e3de9fb..19ad7d694 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts @@ -34,11 +34,15 @@ export const mergeLinksAndCoordinates = ( // Find destination link info from shared state let dest: IBaseLink; for (const destNodeKey in links) { - const link = Object.entries(links[destNodeKey].links).find( - ([key]) => key === linkKey && destNodeKey !== actualNodeName - ); - if (link) { - dest = { [destNodeKey]: link[1] }; + // Prevent empty objects crashing from shared state + if (links[destNodeKey] && !isEmpty(links[destNodeKey]?.links)) { + const link = Object.entries(links[destNodeKey].links).find( + ([key]) => + key === linkKey && destNodeKey !== actualNodeName + ); + if (link) { + dest = { [destNodeKey]: link[1] }; + } } } diff --git a/src/utils/utils.tsx b/src/utils/utils.tsx index 68b889a4a..4e5ecab2a 100644 --- a/src/utils/utils.tsx +++ b/src/utils/utils.tsx @@ -1,3 +1,8 @@ -export function isEmpty(obj: object): boolean { +export function isEmpty(obj: object | null | undefined): boolean { + // Check if the input is null, undefined, or not an object + if (obj == null || typeof obj !== "object") { + return true; + } + // Return true if the object has no own properties return Object.keys(obj).length === 0; } From 3aaab3ec7749a42ac6b746bb5732f226b49c9a15 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 17 Sep 2024 07:59:53 -0500 Subject: [PATCH 15/22] Hotfix mesh map empty objects (#450) * chore(mesh-wide): fix set ref state for new links * chore(mesh-wide): fix reference state is not set * chore(mesh-wide): wrap links and coordinates on a try catch * chore(mesh-wide): fix links inside links * chore(mesh-wide): prevent deleted node on reference * chore(mesh-wide): fix new link is down * chore(mesh-wide): prevent FIXME coords --- .../components/FeatureDetail/LinkDetail.tsx | 99 +++++----- .../src/components/Map/LinkLine.tsx | 6 +- .../src/components/configPage/modals.tsx | 17 +- .../src/lib/links/getLinksCoordinates.ts | 169 ++++++++++-------- .../src/meshWideQueries.tsx | 18 +- .../src/meshWideTypes.tsx | 3 +- 6 files changed, 180 insertions(+), 132 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index 07104a692..4ae5478ce 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -175,8 +175,8 @@ const SelectedLink = ({ ); }; -const LinkFeatureDetail = ({ actual, reference }: LinkMapFeature) => { - const linkToShow = reference ?? actual; +const LinkFeatureDetail = ({ linkToShow, actual }: LinkMapFeature) => { + // const linkToShow = reference ?? actual; const [selectedLink, setSelectedLink] = useState(0); const { errors } = usePointToPointErrors({ id: linkToShow.id, @@ -224,12 +224,15 @@ const LinkFeatureDetail = ({ actual, reference }: LinkMapFeature) => { ); }; -export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { +export const LinkReferenceStatus = ({ + linkToShow, + reference, +}: LinkMapFeature) => { const isNewLink = !reference; const { errors } = usePointToPointErrors({ - id: reference.id, - type: reference.type, + id: linkToShow.id, + type: linkToShow.type, }); const { @@ -240,7 +243,7 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { // Check if there are errors of global reference state to shown const { reference: fetchDataReference } = getQueryByLinkType( - reference.type + linkToShow.type ); const { data: referenceData, isError: isReferenceError } = fetchDataReference({}); @@ -263,68 +266,56 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { }; if (!allNodes) return {}; // Then reduce the nodes to update - return reference.nodes.reduce((acc, node) => { + return linkToShow.nodes.reduce((acc, node) => { // If the node with node name exist get the ipv4 and hostname if (allNodes[node]) { acc[allNodes[node].ipv4] = allNodes[node].hostname; } return acc; }, {}); - }, [meshWideNodesReference, meshWideNodesActual, reference.nodes]); + }, [meshWideNodesReference, meshWideNodesActual, linkToShow.nodes]); // Mutation to update the reference state const { callMutations } = useSetLinkReferenceState({ - linkType: reference.type, - linkToUpdate: reference, + linkType: linkToShow.type, + linkToUpdate: linkToShow, isDown, + isNewLink, nodesToUpdate, }); // Show confirmation modal before run mutations const setReferenceState = useCallback(async () => { - confirmModal( - reference.type, - Object.values(nodesToUpdate), - isDown, - async () => { - try { - const res = await callMutations(); - if (res.errors.length) { - console.log("Errors"); - throw new Error("Error setting new reference state!"); - } - showToast({ - text: New reference state set!, - }); - } catch (error) { - showToast({ - text: Error setting new reference state!, - }); - } finally { - closeModal(); - } + try { + const res = await callMutations(); + if (res.errors.length) { + console.log("Errors"); + throw new Error("Error setting new reference state!"); } - ); - }, [ - callMutations, - closeModal, - confirmModal, - isDown, - nodesToUpdate, - reference.type, - showToast, - ]); + showToast({ + text: New reference state set!, + }); + } catch (error) { + showToast({ + text: Error setting new reference state!, + }); + } finally { + closeModal(); + } + }, [callMutations, closeModal, showToast]); let btnText = ( Set reference state for this -
{dataTypeNameMapping(reference.type)} +
{dataTypeNameMapping(linkToShow.type)}
); - if (isDown) { + // If is down and not a new link. + // Could happen that one of the links is not on the state yet and the other is not + if (isDown && !isNewLink) { btnText = ( - Delete this {dataTypeNameMapping(reference.type)} + Delete this {dataTypeNameMapping(linkToShow.type)}
from reference state
@@ -332,14 +323,15 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { } let errorMessage = Same status as in the reference state; - if (referenceError) { - errorMessage = Reference is not set or has errors; - } else if (errors?.hasErrors) { - errorMessage = This link has errors; - } else if (isNewLink) { + + if (isNewLink) { errorMessage = ( This Link is not registered on the reference state ); + } else if (referenceError) { + errorMessage = Reference is not set or has errors; + } else if (errors?.hasErrors) { + errorMessage = This link has errors; } const hasError = errors?.hasErrors || referenceError; @@ -350,7 +342,14 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { + confirmModal({ + dataType: linkToShow.type, + nodes: Object.values(nodesToUpdate), + isDown, + cb: setReferenceState, + }) + } > {errorMessage} diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx index 8833242ed..d078c5251 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx @@ -38,7 +38,11 @@ export const LinkLine = ({ referenceLink, actualLink }: ILinkLineProps) => { const _setSelectedFeature = () => { setSelectedMapFeature({ id: linkToShow.id, - feature: { reference: linkToShow, actual: actualLink }, + feature: { + reference: referenceLink, + actual: actualLink, + linkToShow, + }, type: "link", }); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx index a0c1beb17..4fde5161b 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx @@ -120,12 +120,17 @@ export const useSetNodeInfoReferenceStateModal = () => { export const useSetLinkReferenceStateModal = () => { const { toggleModal, setModalState, isModalOpen, closeModal } = useModal(); - const confirmModal = ( - dataType: MeshWideMapDataTypeKeys, - nodes: string[], - isDown: boolean, - cb: () => Promise - ) => { + const confirmModal = ({ + dataType, + nodes, + isDown, + cb, + }: { + dataType: MeshWideMapDataTypeKeys; + nodes: string[]; + isDown: boolean; + cb: () => Promise; + }) => { let title = ( Set reference state for this {dataTypeNameMapping(dataType)}? diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts index 19ad7d694..5338aa46d 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts @@ -2,6 +2,7 @@ import { MacToMacLink, PontToPointLink, } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; +import { isValidCoordinate } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { IBaseLink, ILinks, @@ -18,91 +19,119 @@ export const mergeLinksAndCoordinates = ( nodes?: INodes ): LocatedLinkData => { if (!links || isEmpty(links)) return {}; - const result: LocatedLinkData = {}; - // for every node check all links - for (const actualNodeName in links) { - if ( - isEmpty(links[actualNodeName]) || - typeof links[actualNodeName].links !== "object" // todo(kon): this is an error from the backend - ) - continue; - const srcLoc = links[actualNodeName].src_loc; - for (const [linkKey, linkData] of Object.entries( - links[actualNodeName].links - )) { - // Find destination link info from shared state - let dest: IBaseLink; - for (const destNodeKey in links) { - // Prevent empty objects crashing from shared state - if (links[destNodeKey] && !isEmpty(links[destNodeKey]?.links)) { - const link = Object.entries(links[destNodeKey].links).find( - ([key]) => - key === linkKey && destNodeKey !== actualNodeName - ); - if (link) { - dest = { [destNodeKey]: link[1] }; + + try { + // for every node check all links + for (const actualNodeName in links) { + if ( + isEmpty(links[actualNodeName]) || + typeof links[actualNodeName].links !== "object" // todo(kon): this is an error from the backend + ) { + continue; + } + const srcLoc = links[actualNodeName].src_loc; + // If the source location is not valid (FIXME coords), continue + if (!isValidCoordinate(srcLoc.lat, srcLoc.long)) { + continue; + } + + for (const [linkKey, linkData] of Object.entries( + links[actualNodeName].links + )) { + // Find destination link info from shared state + let dest: IBaseLink = {}; + for (const destNodeKey in links) { + // Prevent empty objects crashing from shared state + if ( + links[destNodeKey] && + !isEmpty(links[destNodeKey]?.links) + ) { + const link = Object.entries( + links[destNodeKey].links + ).find( + ([key]) => + key === linkKey && + destNodeKey !== actualNodeName + ); + if (link) { + dest = { [destNodeKey]: link[1] }; + } } } - } - let destLoc = linkData?.dst_loc; - // If destination coords are undefined, try to find it on other ways. - if (!destLoc) { - if (dest && links[Object.keys(dest)[0]].src_loc) { - // If we have destination link info, try to find the src_loc - destLoc = links[Object.keys(dest)[0]].src_loc; - } else { - // Find the destination MAC between existing located nodes to get the position - const dstNode = Object.values(nodes).find((node) => { - return node.macs.find((mac) => { - return ( - mac.toLowerCase() === - linkData.dst_mac.toLowerCase() - ); + let destLoc = linkData?.dst_loc; + // If destination coords are undefined, try to find it on other ways. + if (!destLoc) { + if ( + dest && + !isEmpty(dest) && + links[Object.keys(dest)[0]]?.src_loc + ) { + // If we have destination link info, try to find the src_loc + destLoc = links[Object.keys(dest)[0]].src_loc; + } else { + // Find the destination MAC between existing located nodes to get the position + const dstNode = Object.values(nodes).find((node) => { + return node.macs.find((mac) => { + return ( + mac.toLowerCase() === + linkData?.dst_mac?.toLowerCase() + ); + }); }); - }); - if (dstNode) { - destLoc = dstNode.coordinates; + if (dstNode) { + destLoc = dstNode.coordinates; + } } } - } - // What happen if the destination link or location is undefined? - // Maybe drawing somehow to the map and show the user that the link is not complete - // For the moment lets ignore the link - if (!destLoc) { - continue; - } + // What happen if the destination link or location is undefined? + // Maybe drawing somehow to the map and show the user that the link is not complete + // For the moment lets ignore the link + if ( + !destLoc || + (destLoc && !isValidCoordinate(destLoc.lat, destLoc.long)) // FIXME coords + ) { + continue; + } - // Get Geolink key to check if is already added - const geoLinkKey = PontToPointLink.generateId(srcLoc, destLoc); + // Get Geolink key to check if is already added + const geoLinkKey = PontToPointLink.generateId(srcLoc, destLoc); - // If the link PontToPointLink already exists and the link is already added, ignore it - if (result[geoLinkKey] && result[geoLinkKey].linkExists(linkKey)) { - continue; - } + // If the link PontToPointLink already exists and the link is already added, ignore it + if ( + result[geoLinkKey] && + result[geoLinkKey].linkExists(linkKey) + ) { + continue; + } - // Instantiate new point to point link on the results array - if (!result[geoLinkKey]) { - result[geoLinkKey] = new PontToPointLink(srcLoc, destLoc); - } + // Instantiate new point to point link on the results array + if (!result[geoLinkKey]) { + result[geoLinkKey] = new PontToPointLink(srcLoc, destLoc); + } - // Add node names to the link data - result[geoLinkKey].addNodes([ - actualNodeName, - ...Object.keys(dest ?? ""), // If destination node is down, ignore node name - ]); + // Add node names to the link data + result[geoLinkKey].addNodes([ + actualNodeName, + ...Object.keys(dest ?? ""), // If destination node is down, ignore node name + ]); - const entry = { - [actualNodeName]: { - ...linkData, - }, - ...dest, - } as IBaseLink; + const entry = { + [actualNodeName]: { + ...linkData, + }, + ...dest, + } as IBaseLink; - result[geoLinkKey].addLink(new MacToMacLink(linkKey, entry, type)); + result[geoLinkKey].addLink( + new MacToMacLink(linkKey, entry, type) + ); + } } + } catch (e) { + console.error("Error merging links and coordinates", e); } return result; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index 9aab0ae3d..f3bd9713e 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -23,6 +23,7 @@ import { import { useMeshWideSyncCall } from "utils/meshWideSyncCall"; import { useSharedData } from "utils/useSharedData"; +import { isEmpty } from "utils/utils"; const refetchInterval = 60000; @@ -149,12 +150,14 @@ interface IUseSetLinkReferenceState { nodesToUpdate: { [ip: string]: string }; // { ip: hostname } params?: any; isDown: boolean; + isNewLink: boolean; } export const useSetLinkReferenceState = ({ linkType, linkToUpdate, isDown, + isNewLink, nodesToUpdate, params, }: IUseSetLinkReferenceState) => { @@ -167,13 +170,14 @@ export const useSetLinkReferenceState = ({ mutationFn: ({ ip }) => { const hostname = nodesToUpdate[ip]; - let newReferenceLinks = (referenceData[hostname] ?? + let newReferenceLinks = (referenceData[hostname].links ?? {}) as IBaseLink; - // This is a hotfix because backend returns an empty string somtimes - if (typeof newReferenceLinks !== "object") newReferenceLinks = {}; + + // This is a hotfix because backend returns an empty array sometimes + if (isEmpty(newReferenceLinks)) newReferenceLinks = {}; for (const mactomac of linkToUpdate.links) { - if (isDown) { + if (isDown && newReferenceLinks[mactomac.id] && !isNewLink) { delete newReferenceLinks[mactomac.id]; continue; } @@ -194,6 +198,12 @@ export const useSetLinkReferenceState = ({ }, } as ILinks ); + console.log("linkToUpdate", linkToUpdate); + console.log("newReferenceLinks", newReferenceLinks); + console.log("referenceData", referenceData); + console.log("data[hostname]", data[hostname]); + console.log("hostname", hostname); + console.log("queryKey", queryKey); return doSharedStateApiCall(queryKey, ip); }, ips: Object.keys(nodesToUpdate), diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx index 71a3d6f38..ba5b5999f 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx @@ -96,7 +96,8 @@ export type INodes = { [key: string]: INodeInfo }; export type LinkMapFeature = { actual: PontToPointLink; - reference: PontToPointLink; + reference?: PontToPointLink; + linkToShow: PontToPointLink; }; export type NodeMapFeature = { From 9430a4b48733ef5d035d5943399ff3b74d970131 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 24 Sep 2024 08:44:35 -0500 Subject: [PATCH 16/22] Implement babel links (#456) Implement babel links map layer --- .../components/FeatureDetail/LinkDetail.tsx | 85 +++++++++++++++---- .../src/containers/Map.tsx | 8 ++ .../src/containers/MapLayers/LinksLayers.tsx | 20 +++++ .../src/hooks/useLocatedLinks.tsx | 32 ++++++- .../src/hooks/useMeshWideDataErrors.tsx | 22 ++++- .../src/lib/links/processLinkErrors.ts | 54 ++++++++---- .../lime-plugin-mesh-wide/src/lib/utils.ts | 4 + .../src/meshWidePage.tsx | 9 +- .../src/meshWideQueries.tsx | 33 +++++-- .../src/meshWideTypes.tsx | 20 ++++- .../shared-state/SharedStateTypes.ts | 2 + 11 files changed, 242 insertions(+), 47 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index 4ae5478ce..92dc3d695 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -21,8 +21,10 @@ import { } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { useSetLinkReferenceState } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; import { + BabelLinkErrorCodes, BaseMacToMacLink, BatmanLinkErrorCodes, + IBabelLinkData, IBatManLinkData, ILinkMtoMErrors, IWifiLinkData, @@ -63,6 +65,37 @@ const BatmanDetail = ({ ); }; +const BabelDetail = ({ + name, + errorsArray, + node, +}: { + name: string; + errorsArray: BabelLinkErrorCodes[] | undefined; + node: IBabelLinkData; +}) => { + return ( + <> + +
+ {name} + {errorsArray?.length > 0 && } +
+
+ + Iface
}> + {node?.iface} + + + + Source IP}> + {node?.src_ip} + + + + ); +}; + const WifiDetail = ({ name, errorsArray, @@ -155,21 +188,43 @@ const SelectedLink = ({ {names.map((name, i) => { const node = linkDetail.linkByName(name); const errorsArray = errors?.linkErrors[name] ?? []; - return linkType === "wifi_links_info" ? ( - - ) : ( - - ); + switch (linkType) { + case "wifi_links_info": + return ( + + ); + case "babel_links_info": + return ( + + ); + case "bat_links_info": + return ( + + ); + default: + return Unknown link type; + } })} ); diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx index d382b2e2e..2da02c117 100644 --- a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx +++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx @@ -15,6 +15,7 @@ import { useLocation, } from "plugins/lime-plugin-locate/src/locateQueries"; import { + BabelLinksLayer, BatmanLinksLayer, WifiLinksLayer, } from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers"; @@ -29,12 +30,14 @@ interface ILayersChecked { nodes?: boolean; wifiLinks?: boolean; batmanLinks?: boolean; + babelLinks?: boolean; } export const MeshWideMap = ({ nodes = true, wifiLinks = true, batmanLinks = false, + babelLinks = false, }: ILayersChecked) => { const { data: selectedMapFeature, setData: setSelectedMapFeature } = useSelectedMapFeature(); @@ -94,6 +97,11 @@ export const MeshWideMap = ({ layer: , checked: batmanLinks, }, + babel_links_info: { + name: "Babel", + layer: , + checked: babelLinks, + }, }; return ( diff --git a/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx b/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx index 35f426b4e..921f1603d 100644 --- a/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx +++ b/plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers.tsx @@ -81,3 +81,23 @@ export const BatmanLinksLayer = () => {
); }; + +export const BabelLinksLayer = () => { + const { + locatedNewLinks: newLinks, + locatedLinks, + locatedLinksReference, + linksLoaded, + } = useLocatedLinks({ type: "babel_links_info" }); + + return ( +
+ +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx index d9a0c14f8..e27cacf19 100644 --- a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx @@ -8,6 +8,8 @@ import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/Poi import { mergeLinksAndCoordinates } from "plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates"; import { compareLinks } from "plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors"; import { + useMeshWideBabel, + useMeshWideBabelReference, useMeshWideBatman, useMeshWideBatmanReference, useMeshWideLinks, @@ -41,6 +43,11 @@ export const getQueryByLinkType = ( state: useMeshWideBatman, reference: useMeshWideBatmanReference, } as getQueryByLinkTypeReturnType; + case "babel_links_info": + return { + state: useMeshWideBabel, + reference: useMeshWideBabelReference, + } as getQueryByLinkTypeReturnType; case "wifi_links_info": default: return { @@ -166,18 +173,25 @@ export const usePointToPointErrors = ({ // Define separate contexts for each type of link const BatmanLinksContext = createContext(null); const MeshWideLinksContext = createContext(null); +const BabelLinksContext = createContext(null); // Export a hook that return the proper context based on the type of link export const useLocatedLinks = ({ type }: { type: LinkType }) => { + // By default use wifi links let requestedContext = MeshWideLinksContext; - if (type === "bat_links_info") { - requestedContext = BatmanLinksContext; + switch (type) { + case "bat_links_info": + requestedContext = BatmanLinksContext; + break; + case "babel_links_info": + requestedContext = BabelLinksContext; + break; } const context = useContext(requestedContext); if (context === null) { throw new Error( - `useLocatedLinks must be used within a provider for ${requestedContext} links` + `useLocatedLinks must be used within a provider for ${type} links` ); } return context; @@ -206,3 +220,15 @@ export const MeshWideLinksProvider = ({ children }) => { ); }; + +export const BabelLinksProvider = ({ children }) => { + const babelLinksData = useCalculateLocatedLinks({ + type: "babel_links_info", + }); + + return ( + + {children} + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx index 003eb16b3..426f46c36 100644 --- a/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx +++ b/plugins/lime-plugin-mesh-wide/src/hooks/useMeshWideDataErrors.tsx @@ -3,6 +3,8 @@ import { QueryKey } from "@tanstack/react-query"; import { sharedStateQueries } from "components/shared-state/SharedStateQueriesKeys"; import { + useMeshWideBabel, + useMeshWideBabelReference, useMeshWideBatman, useMeshWideBatmanReference, useMeshWideLinks, @@ -11,6 +13,7 @@ import { useMeshWideNodesReference, } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; import { + IBabelLinks, IBatmanLinks, INodes, IWifiLinks, @@ -37,7 +40,7 @@ export const useMeshWideDataErrors = () => { const addError = ( queryKey: QueryKey, error?: unknown, - data?: IWifiLinks | IBatmanLinks | INodes + data?: IWifiLinks | IBatmanLinks | INodes | IBabelLinks ) => { if (data) { // Check also node by node if reference state is empty @@ -80,6 +83,23 @@ export const useMeshWideDataErrors = () => { batmanReferenceData ); + const { error: babelError } = useMeshWideBabel({}); + addError( + sharedStateQueries.getFromSharedState("babel_links_info"), + babelError + ); + + const { + data: babelReferenceData, + error: babelReferenceError, + isError: babelReferenceIsError, + } = useMeshWideBabelReference({}); + addError( + sharedStateQueries.getFromSharedState("babel_links_info_ref"), + babelReferenceIsError ? babelReferenceError : null, + babelReferenceData + ); + const { error: batmanError } = useMeshWideBatman({}); addError( sharedStateQueries.getFromSharedState("bat_links_info"), diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts index ecc7f9aa3..418922645 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/links/processLinkErrors.ts @@ -1,9 +1,12 @@ import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; import { + BabelLinkErrorCodes, BatmanLinkErrorCodes, + IBabelLinkData, IBatManLinkData, ILinkPtoPErrors, IWifiLinkData, + LinksErrorCodesTypes, WifiLinkErrorCodes, } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; @@ -49,6 +52,17 @@ const compareBatmanData = ( return errors; }; +const compareBabelData = ( + reference: IBabelLinkData, + actual: IBabelLinkData +) => { + const errors: BabelLinkErrorCodes[] = []; + if (actual === undefined) { + return [BabelLinkErrorCodes.LINK_DOWN]; + } + return errors; +}; + /** * Function that receive 2 PontToPointLink and iterate over every mac to mac link and its data executing a function * to compare the wifi data. @@ -94,16 +108,27 @@ export const compareLinks = ({ Object.entries(macToMacReference.data).forEach( ([nodeNameReference, wifiDataReference]) => { const wifiDataActual = macToMacActual?.data[nodeNameReference]; - const errors = - referenceLink.type === "wifi_links_info" - ? compareWifiData( - wifiDataReference as IWifiLinkData, - wifiDataActual as IWifiLinkData - ) - : compareBatmanData( - wifiDataReference as IBatManLinkData, - wifiDataActual as IBatManLinkData - ); + let errors: LinksErrorCodesTypes[] = []; + switch (referenceLink.type) { + case "wifi_links_info": + errors = compareWifiData( + wifiDataReference as IWifiLinkData, + wifiDataActual as IWifiLinkData + ); + break; + case "bat_links_info": + errors = compareBatmanData( + wifiDataReference as IBatManLinkData, + wifiDataActual as IBatManLinkData + ); + break; + case "babel_links_info": + errors = compareBabelData( + wifiDataReference as IBabelLinkData, + wifiDataActual as IBabelLinkData + ); + break; + } ptoPErrors.macToMacErrors[macToMacReference.id].linkErrors[ nodeNameReference ] = errors; @@ -112,14 +137,7 @@ export const compareLinks = ({ true; ptoPErrors.hasErrors = true; - if ( - (errors as WifiLinkErrorCodes[]).includes( - WifiLinkErrorCodes.LINK_DOWN - ) || - (errors as BatmanLinkErrorCodes[]).includes( - BatmanLinkErrorCodes.LINK_DOWN - ) - ) { + if (errors.includes(WifiLinkErrorCodes.LINK_DOWN)) { ptoPErrors.macToMacErrors[macToMacReference.id].linkUp = false; downCounter++; diff --git a/plugins/lime-plugin-mesh-wide/src/lib/utils.ts b/plugins/lime-plugin-mesh-wide/src/lib/utils.ts index 030a6a2eb..0a9799026 100644 --- a/plugins/lime-plugin-mesh-wide/src/lib/utils.ts +++ b/plugins/lime-plugin-mesh-wide/src/lib/utils.ts @@ -82,6 +82,10 @@ export const dataTypeNameMapping = (dataType: SharedStateDataTypeKeys) => { return t`Batman Links`; case "bat_links_info_ref": return t`Batman Links Reference`; + case "babel_links_info": + return t`Babel Links`; + case "babel_links_info_ref": + return t`Babel Links Reference`; default: return dataType; } diff --git a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx index 45f0ab488..66a7fc564 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx @@ -8,6 +8,7 @@ import { FloatingAlert } from "plugins/lime-plugin-mesh-wide/src/components/Map/ import { MeshWideMap } from "plugins/lime-plugin-mesh-wide/src/containers/Map"; import { SelectedFeatureBottomSheet } from "plugins/lime-plugin-mesh-wide/src/containers/SelectedFeatureBottomSheet"; import { + BabelLinksProvider, BatmanLinksProvider, MeshWideLinksProvider, } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; @@ -54,9 +55,11 @@ const MeshWidePage = () => { return ( - - - + + + + + ); diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index f3bd9713e..6bb9bf610 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -10,6 +10,7 @@ import { getQueryByLinkType } from "plugins/lime-plugin-mesh-wide/src/hooks/useL import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; import { + IBabelLinks, IBaseLink, IBatmanLinks, ILinks, @@ -79,6 +80,32 @@ export function useMeshWideBatman(params) { ); } +export function useMeshWideBabelReference(params) { + const dataType: MeshWideMapDataTypeKeys = "babel_links_info_ref"; + const queryKey = sharedStateQueries.getFromSharedState(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + +export function useMeshWideBabel(params) { + const dataType: MeshWideMapDataTypeKeys = "babel_links_info"; + const queryKey = sharedStateQueries.getFromSharedState(dataType); + return useQuery( + queryKey, + () => doSharedStateApiCall(queryKey), + { + refetchInterval, + ...params, + } + ); +} + export function useMeshWideNodesReference(params) { const dataType: MeshWideMapDataTypeKeys = "node_info_ref"; const queryKey = sharedStateQueries.getFromSharedState(dataType); @@ -198,12 +225,6 @@ export const useSetLinkReferenceState = ({ }, } as ILinks ); - console.log("linkToUpdate", linkToUpdate); - console.log("newReferenceLinks", newReferenceLinks); - console.log("referenceData", referenceData); - console.log("data[hostname]", data[hostname]); - console.log("hostname", hostname); - console.log("queryKey", queryKey); return doSharedStateApiCall(queryKey, ip); }, ips: Object.keys(nodesToUpdate), diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx index ba5b5999f..b8d0ca7c4 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx @@ -17,6 +17,7 @@ import { export type LinkDataTypes = { wifi_links_info: IWifiLinkData; bat_links_info: IBatManLinkData; + babel_links_info: IBabelLinkData; }; export type LinkType = keyof LinkDataTypes; export type IBaseLink = { @@ -60,6 +61,11 @@ export type IBatManLinkData = { iface: string; }; +export type IBabelLinkData = { + src_ip: string; + iface: string; +}; + /** * List of Link info retrieved from the API */ @@ -72,6 +78,7 @@ export interface ILinks { export type IWifiLinks = ILinks<"wifi_links_info">; export type IBatmanLinks = ILinks<"bat_links_info">; +export type IBabelLinks = ILinks<"bat_links_info">; export type Coordinates = { lat: string; @@ -152,6 +159,15 @@ export enum BatmanLinkErrorCodes { LINK_DOWN = "LINK_DOWN", } +export enum BabelLinkErrorCodes { + LINK_DOWN = "LINK_DOWN", +} + +export type LinksErrorCodesTypes = + | WifiLinkErrorCodes + | BatmanLinkErrorCodes + | BabelLinkErrorCodes; + export enum NodeErrorCodes { NODE_DOWN = "NODE_DOWN", MACS_MISSMATCH = "MACS_MISSMATCH", @@ -162,7 +178,7 @@ export enum NodeErrorCodes { */ export type ILinkMtoMErrors = { linkErrors: { - [nodeName: string]: WifiLinkErrorCodes[] | BatmanLinkErrorCodes[]; + [nodeName: string]: LinksErrorCodesTypes[]; }; hasErrors: boolean; linkUp: boolean; @@ -202,9 +218,11 @@ const completeDataTypeKeys: CompleteDataTypeKeys = { node_info: true, wifi_links_info: true, bat_links_info: true, + babel_links_info: true, node_info_ref: true, wifi_links_info_ref: true, bat_links_info_ref: true, + babel_links_info_ref: true, }; export const getMeshWideMapTypes = () => { return Object.keys(completeDataTypeKeys) as MeshWideMapDataTypeKeys[]; diff --git a/src/components/shared-state/SharedStateTypes.ts b/src/components/shared-state/SharedStateTypes.ts index 79db7ffcd..6f2496666 100644 --- a/src/components/shared-state/SharedStateTypes.ts +++ b/src/components/shared-state/SharedStateTypes.ts @@ -1,5 +1,6 @@ import { MeshWideUpgradeInfo } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; import { + IBabelLinks, IBatmanLinks, INodes, IWifiLinks, @@ -13,6 +14,7 @@ export type MeshWideMapTypes = { node_info: INodes; wifi_links_info: IWifiLinks; bat_links_info: IBatmanLinks; + babel_links_info: IBabelLinks; }; // Reference state types From 5f97a092b52a63d6594a98604d675ff9e3546486 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 24 Sep 2024 10:24:04 -0500 Subject: [PATCH 17/22] Implement mesh wide config plugin (#457) move config to new package implements the EditConfiguration modal --- plugins/lime-plugin-mesh-wide-config/index.ts | 8 ++ .../src/components/Components.tsx | 61 +++++++++++++ .../src/components}/ConfigSection.tsx | 8 +- .../src/components}/MeshStatus.tsx | 0 .../src/components}/OptionForm.tsx | 4 +- .../src/components/modals.tsx | 87 +++++++++++++++++++ .../src/containers/EditConfiguration.tsx | 39 +++++++++ .../src/meshConfigApi.ts | 31 +++++++ .../src/meshConfigPage.tsx | 19 ++++ .../src/meshConfigQueries.tsx | 14 +++ .../src/meshConfigTypes.tsx | 6 ++ plugins/lime-plugin-mesh-wide/index.ts | 2 - .../components/FeatureDetail/LinkDetail.tsx | 2 +- .../components/FeatureDetail/NodeDetail.tsx | 2 +- .../components/{configPage => }/modals.tsx | 77 ---------------- .../src/meshWideMocks.tsx | 31 ------- .../src/meshWidePage.tsx | 4 +- .../src/meshWideQueries.tsx | 16 ---- .../src/meshWideTypes.tsx | 7 -- .../src/screens/configPage.tsx | 40 --------- plugins/lime-plugin-rx/src/sections/wired.tsx | 2 +- src/components/Modal/FullScreenModal.tsx | 17 ++-- src/config.ts | 4 +- 23 files changed, 289 insertions(+), 192 deletions(-) create mode 100644 plugins/lime-plugin-mesh-wide-config/index.ts create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx rename plugins/{lime-plugin-mesh-wide/src/components/configPage => lime-plugin-mesh-wide-config/src/components}/ConfigSection.tsx (92%) rename plugins/{lime-plugin-mesh-wide/src/components/configPage => lime-plugin-mesh-wide-config/src/components}/MeshStatus.tsx (100%) rename plugins/{lime-plugin-mesh-wide/src/components/configPage => lime-plugin-mesh-wide-config/src/components}/OptionForm.tsx (98%) create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts create mode 100644 plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx rename plugins/lime-plugin-mesh-wide/src/components/{configPage => }/modals.tsx (58%) delete mode 100644 plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx diff --git a/plugins/lime-plugin-mesh-wide-config/index.ts b/plugins/lime-plugin-mesh-wide-config/index.ts new file mode 100644 index 000000000..7dcc9afc7 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/index.ts @@ -0,0 +1,8 @@ +import MeshConfigPage from "./src/meshConfigPage"; + +export default { + name: "meshwide/config", + page: MeshConfigPage, + isCommunityProtected: true, + additionalRoutes: [["/meshwide/config", MeshConfigPage]], +} as LimePlugin; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx new file mode 100644 index 000000000..9c802d2be --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx @@ -0,0 +1,61 @@ +import { VNode } from "preact"; + +import { Button } from "components/buttons/button"; +import { BinIcon } from "components/icons/bin"; +import { EditIcon } from "components/icons/edit"; +import { StatusIcon } from "components/icons/status"; + +interface IStatusMessage { + isError: boolean; + children: VNode | string; +} + +// todo(kon): merge with src/components/status/statusAndButton.tsx +export const StatusAndButton = ({ + isError, + children, + btn, + onClick, +}: { btn?: VNode | string; onClick?: () => void } & IStatusMessage) => { + const containerClasses = + "flex flex-col items-center justify-center text-center bg-white py-5 gap-3"; + + return ( +
+ {children} + {btn && } +
+ ); +}; + +export const StatusMessage = ({ + isError, + children, + classes, +}: { + classes?: string; +} & IStatusMessage) => ( +
+ {isError ? ( + + ) : ( + + )} + {children} +
+); + +export const EditOrDelete = ({ + onEdit, + onDelete, +}: { + onEdit: (e) => void; + onDelete: (e) => void; +}) => ( +
+ + +
+); diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx similarity index 92% rename from plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx rename to plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx index 95f64665b..0acd58bbe 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx @@ -4,14 +4,14 @@ import { Button } from "components/buttons/button"; import { Collapsible } from "components/collapsible"; import { useToast } from "components/toast/toastProvider"; -import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; -import { OptionContainer } from "plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm"; +import { OptionContainer } from "plugins/lime-plugin-mesh-wide-config/src/components/OptionForm"; import { useAddNewSectionModal, useDeletePropModal, useEditPropModal, -} from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; -import { IMeshWideSection } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; +} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; +import { IMeshWideSection } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; export const ConfigSection = ({ dropdown }: { dropdown: IMeshWideSection }) => { return ( diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx similarity index 100% rename from plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus.tsx rename to plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx similarity index 98% rename from plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx rename to plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx index 7f93c1dc3..df5dbb9fe 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/configPage/OptionForm.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx @@ -7,11 +7,11 @@ import Divider from "components/divider"; import InputField from "components/inputs/InputField"; import { useToast } from "components/toast/toastProvider"; -import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; import { useDeletePropModal, useEditPropModal, -} from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; +} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; const EditOptionForm = ({ keyString, diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx new file mode 100644 index 000000000..bd0ec9257 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx @@ -0,0 +1,87 @@ +import { Trans } from "@lingui/macro"; +import { ComponentChildren } from "preact"; +import { useCallback } from "preact/compat"; +import { useForm } from "react-hook-form"; + +import { ModalActions, useModal } from "components/Modal/Modal"; +import InputField from "components/inputs/InputField"; + +import { dataTypeNameMapping } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; +import { MeshWideMapDataTypeKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +const useActionModal = ( + title: ComponentChildren, + btnText: ComponentChildren, + actionName: ModalActions +) => { + const { toggleModal, setModalState } = useModal(); + + const actionModal = useCallback( + (prop: string, actionCb: () => void) => { + setModalState({ + content: ( +
+ + Are you sure you want to {title} the{" "} + {prop} property? + +
+ ), + title, + [`${actionName}Cb`]: actionCb, + [`${actionName}BtnText`]: btnText, + }); + toggleModal(); + }, + [actionName, btnText, setModalState, title, toggleModal] + ); + return { actionModal, toggleModal }; +}; + +export const useDeletePropModal = () => + useActionModal( + Delete property, + Delete, + "delete" + ); + +export const useEditPropModal = () => + useActionModal( + Edit property, + Edit, + "success" + ); + +export const useAddNewSectionModal = () => { + const { toggleModal, setModalState } = useModal(); + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + defaultValues: { name: "" }, + }); + + const actionModal = useCallback( + (actionCb: (data) => void) => { + setModalState({ + content: ( +
+ Name} + register={register} + /> +
+ ), + title: Add new section, + successCb: handleSubmit(actionCb), + successBtnText: Add, + }); + toggleModal(); + }, + [handleSubmit, register, setModalState, toggleModal] + ); + return { actionModal, toggleModal }; +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx b/plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx new file mode 100644 index 000000000..d922c7233 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx @@ -0,0 +1,39 @@ +import { Trans } from "@lingui/macro"; + +import { + FullScreenModal, + IFullScreenModalProps, +} from "components/Modal/FullScreenModal"; + +import { + AddNewSectionBtn, + ConfigSection, +} from "plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection"; +import { MeshStatus } from "plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus"; +import { useMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; + +const EditConfiguration = (props: Partial) => { + const { data: meshWideConfig, isLoading } = useMeshWideConfig({}); + + return ( + Mesh wide config} + isLoading={isLoading} + {...props} + > + {meshWideConfig && ( + <> +
+ {meshWideConfig.map((dropdown, index) => ( + + ))} + +
+ + + )} +
+ ); +}; + +export default EditConfiguration; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts b/plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts new file mode 100644 index 000000000..fc92ad20c --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts @@ -0,0 +1,31 @@ +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +export const getMeshWideConfig = async () => meshWideConfig; + +const options = { + primary_interface: "eth0", + main_ipv4_address: "10.170.128.0/16/17", +}; + +const meshWideConfig: IMeshWideConfig = [ + { + name: "lime system", + options, + }, + { + name: "lime network", + options, + }, + { + name: "lime wifi", + options, + }, + { + name: "generic_uci_config prometheus", + options, + }, + { + name: "run_asset prometheus_enable", + options, + }, +]; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx new file mode 100644 index 000000000..e77b07a37 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx @@ -0,0 +1,19 @@ +import { useState } from "preact/hooks"; +import React from "react"; + +import { Button } from "components/elements/button"; + +import EditConfiguration from "plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration"; + +const MeshConfigPage = () => { + // State to show modal + const [showEditConfig, setShowEditConfig] = useState(false); + + if (showEditConfig) { + return setShowEditConfig(false)} />; + } + + return ; +}; + +export default MeshConfigPage; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx new file mode 100644 index 000000000..396d49afd --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx @@ -0,0 +1,14 @@ +import { useQuery } from "@tanstack/react-query"; + +import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigApi"; +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +export function useMeshWideConfig(params) { + return useQuery( + ["lime-meshwide", "get_mesh_config"], + getMeshWideConfig, + { + ...params, + } + ); +} diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx new file mode 100644 index 000000000..d6e35770f --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx @@ -0,0 +1,6 @@ +export interface IMeshWideSection { + name: string; + options: { [key: string]: string }; +} + +export type IMeshWideConfig = IMeshWideSection[]; diff --git a/plugins/lime-plugin-mesh-wide/index.ts b/plugins/lime-plugin-mesh-wide/index.ts index 3ea2bc26a..1837c2c72 100644 --- a/plugins/lime-plugin-mesh-wide/index.ts +++ b/plugins/lime-plugin-mesh-wide/index.ts @@ -1,10 +1,8 @@ import { MeshWideMenu } from "./src/meshWideMenu"; import MeshWidePage from "./src/meshWidePage"; -import MeshWideConfigPage from "./src/screens/configPage"; export default { name: "MeshWide", page: MeshWidePage, menu: MeshWideMenu, - additionalRoutes: [["/meshwide/config", MeshWideConfigPage]], } as LimePlugin; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index 92dc3d695..44e07459e 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -8,7 +8,7 @@ import Tabs from "components/tabs"; import { useToast } from "components/toast/toastProvider"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; -import { useSetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; +import { useSetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; import { getQueryByLinkType, usePointToPointErrors, diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index d667ba754..3208f9b98 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -11,7 +11,7 @@ import { Row, TitleAndText, } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; -import { useSetNodeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals"; +import { useSetNodeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors"; import { getArrayDifference } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx b/plugins/lime-plugin-mesh-wide/src/components/modals.tsx similarity index 58% rename from plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx rename to plugins/lime-plugin-mesh-wide/src/components/modals.tsx index 4fde5161b..ab7ce6a00 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/modals.tsx @@ -9,83 +9,6 @@ import InputField from "components/inputs/InputField"; import { dataTypeNameMapping } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { MeshWideMapDataTypeKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; -const useActionModal = ( - title: ComponentChildren, - btnText: ComponentChildren, - actionName: ModalActions -) => { - const { toggleModal, setModalState } = useModal(); - - const actionModal = useCallback( - (prop: string, actionCb: () => void) => { - setModalState({ - content: ( -
- - Are you sure you want to {title} the{" "} - {prop} property? - -
- ), - title, - [`${actionName}Cb`]: actionCb, - [`${actionName}BtnText`]: btnText, - }); - toggleModal(); - }, - [actionName, btnText, setModalState, title, toggleModal] - ); - return { actionModal, toggleModal }; -}; - -export const useDeletePropModal = () => - useActionModal( - Delete property, - Delete, - "delete" - ); - -export const useEditPropModal = () => - useActionModal( - Edit property, - Edit, - "success" - ); - -export const useAddNewSectionModal = () => { - const { toggleModal, setModalState } = useModal(); - - const { - register, - handleSubmit, - formState: { errors }, - } = useForm({ - defaultValues: { name: "" }, - }); - - const actionModal = useCallback( - (actionCb: (data) => void) => { - setModalState({ - content: ( -
- Name} - register={register} - /> -
- ), - title: Add new section, - successCb: handleSubmit(actionCb), - successBtnText: Add, - }); - toggleModal(); - }, - [handleSubmit, register, setModalState, toggleModal] - ); - return { actionModal, toggleModal }; -}; - export const useSetNodeInfoReferenceStateModal = () => { const { toggleModal, setModalState, isModalOpen } = useModal(); diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx index 26b0f7c23..790924e4f 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideMocks.tsx @@ -2,7 +2,6 @@ import { IBaseLink, IBatmanLinks, ILinks, - IMeshWideConfig, INodes, IWifiLinks, LinkType, @@ -438,33 +437,3 @@ export const nodes = (): INodes => { return { ...newState, ...newNode }; }; - -export const getMeshWideConfig = async () => meshWideConfig; -// -const options = { - primary_interface: "eth0", - main_ipv4_address: "10.170.128.0/16/17", -}; - -const meshWideConfig: IMeshWideConfig = [ - { - name: "lime system", - options, - }, - { - name: "lime network", - options, - }, - { - name: "lime wifi", - options, - }, - { - name: "generic_uci_config prometheus", - options, - }, - { - name: "run_asset prometheus_enable", - options, - }, -]; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx index 66a7fc564..bf2fb0a90 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx @@ -1,6 +1,8 @@ import { Trans } from "@lingui/macro"; +import { route } from "preact-router"; import React from "react"; +import FloatingButton from "components/buttons/floatting-button"; import Loading from "components/loading"; import { useLoadLeaflet } from "plugins/lime-plugin-locate/src/locateQueries"; @@ -46,7 +48,7 @@ const MeshWide = () => { - {/* route("/meshwide/config")} />*/} + route("/meshwide/config")} /> ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index 6bb9bf610..80ed989e4 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -8,13 +8,11 @@ import { useErrrorConnectionToast } from "components/toast/toasts"; import { meshUpgradeQueryKeys } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys"; import { getQueryByLinkType } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; -import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; import { IBabelLinks, IBaseLink, IBatmanLinks, ILinks, - IMeshWideConfig, INodes, IWifiLinks, LinkType, @@ -232,20 +230,6 @@ export const useSetLinkReferenceState = ({ }); }; -/** - * Set mesh wide config - */ - -export function useMeshWideConfig(params) { - return useQuery( - ["lime-meshwide", "get_mesh_config"], - getMeshWideConfig, - { - ...params, - } - ); -} - /** * This query is used to store the selected feature on the map. * diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx index b8d0ca7c4..18ca9ad59 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx @@ -142,13 +142,6 @@ export type SelectedMapFeature = { }; }[FeatureType]; -export interface IMeshWideSection { - name: string; - options: { [key: string]: string }; -} - -export type IMeshWideConfig = IMeshWideSection[]; - export enum WifiLinkErrorCodes { LINK_DOWN = "LINK_DOWN", SIGNAL_LOSS = "SIGNAL_LOSS", diff --git a/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx b/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx deleted file mode 100644 index 8da449a5f..000000000 --- a/plugins/lime-plugin-mesh-wide/src/screens/configPage.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Trans } from "@lingui/macro"; - -import { FullScreenModal } from "components/Modal/FullScreenModal"; - -import { - AddNewSectionBtn, - ConfigSection, -} from "plugins/lime-plugin-mesh-wide/src/components/configPage/ConfigSection"; -import { MeshStatus } from "plugins/lime-plugin-mesh-wide/src/components/configPage/MeshStatus"; -import { useMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; - -const MeshWideConfigPage = () => { - const { data: meshWideConfig, isLoading } = useMeshWideConfig({}); - - return ( - <> - Mesh wide config} - isLoading={isLoading} - > - {meshWideConfig && ( - <> -
- {meshWideConfig.map((dropdown, index) => ( - - ))} - -
- - - )} -
- - ); -}; - -export default MeshWideConfigPage; diff --git a/plugins/lime-plugin-rx/src/sections/wired.tsx b/plugins/lime-plugin-rx/src/sections/wired.tsx index 32ea13c16..26b66da07 100644 --- a/plugins/lime-plugin-rx/src/sections/wired.tsx +++ b/plugins/lime-plugin-rx/src/sections/wired.tsx @@ -32,7 +32,7 @@ const Ports = ({ switches }: { switches: SwitchStatus[] }) => {
{ports[role].map((port) => { const link = - port.link.toLowerCase() === "up" + port.link?.toLowerCase() === "up" ? "fill-primary-dark" : "fill-disabled"; return ( diff --git a/src/components/Modal/FullScreenModal.tsx b/src/components/Modal/FullScreenModal.tsx index 7dec9c634..31a1a4ce5 100644 --- a/src/components/Modal/FullScreenModal.tsx +++ b/src/components/Modal/FullScreenModal.tsx @@ -3,6 +3,12 @@ import { route } from "preact-router"; import Loading from "components/loading"; +export interface IFullScreenModalProps { + title: ComponentChildren; + children: ComponentChildren; + isLoading?: boolean; + onClose?: () => void; +} /** * Used to show a new view with a close button that return to the backUrl param. Is placed over * the navbar creating a modal like effect. @@ -11,19 +17,14 @@ export const FullScreenModal = ({ title, children, isLoading, - backUrl = "/meshwide", -}: { - title: ComponentChildren; - children: ComponentChildren; - isLoading?: boolean; - backUrl?: string; -}) => { + onClose, +}: IFullScreenModalProps) => { return (
route(backUrl)} + onClick={onClose} > X
diff --git a/src/config.ts b/src/config.ts index 8560587f9..fd1219a79 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,6 +4,7 @@ import Fbw from "plugins/lime-plugin-fbw"; import Firmware from "plugins/lime-plugin-firmware"; import Locate from "plugins/lime-plugin-locate"; import MeshWide from "plugins/lime-plugin-mesh-wide"; +import MeshConfigPage from "plugins/lime-plugin-mesh-wide-config"; import MeshUpgrade from "plugins/lime-plugin-mesh-wide-upgrade"; import Metrics from "plugins/lime-plugin-metrics"; import NetworkAdmin from "plugins/lime-plugin-network-admin"; @@ -28,5 +29,6 @@ export const plugins: LimePlugin[] = [ ChangeNode, RemoteSupport, Pirania, - Fbw, // fbw does not have menu item + Fbw, // does not have menu item + MeshConfigPage, // does not have menu item ]; From ecf7b04c90c6fe6ffd5cb444bd5f2e004d7d524d Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 24 Oct 2024 09:41:13 -0500 Subject: [PATCH 18/22] Improve new modal logic (#463) * chore(meshconfig): change modal API * chore(meshconfig): implement stopPropagation * chore(meshconfig): implement new modal logic * chore(meshconfig): refactor to use new modal logic * chore(meshconfig): show modal over all * chore(meshconfig): refactor rest of modal api --- .../src/components/Components.tsx | 24 ++- .../src/components/ConfigSection.tsx | 151 +++++++------ .../src/components/OptionForm.tsx | 69 +++--- .../src/components/modals.tsx | 128 +++++------ .../src/components/modals.tsx | 167 ++++++++------- .../src/components/nextStepFooter.tsx | 198 +++++++++++++++++- .../src/hooks/useStepper.tsx | 184 +--------------- .../src/components/Components.tsx | 13 -- .../components/FeatureDetail/LinkDetail.tsx | 43 ++-- .../components/FeatureDetail/NodeDetail.tsx | 40 ++-- .../FeatureDetail/RebootNodeBtn.tsx | 126 +++++------ .../src/components/modals.tsx | 148 ++++++------- src/components/Modal/Modal.tsx | 195 ++++++++--------- src/components/Modal/useDisclosure.ts | 61 ++++++ src/components/app.tsx | 9 +- 15 files changed, 810 insertions(+), 746 deletions(-) create mode 100644 src/components/Modal/useDisclosure.ts diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx index 9c802d2be..85881c2b5 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx @@ -53,9 +53,21 @@ export const EditOrDelete = ({ }: { onEdit: (e) => void; onDelete: (e) => void; -}) => ( -
- - -
-); +}) => { + const runCb = (e, cb) => { + e.stopPropagation(); + cb(); + }; + return ( +
+ runCb(e, onEdit)} + /> + runCb(e, onDelete)} + /> +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx index 0acd58bbe..0862d8008 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx @@ -1,17 +1,19 @@ import { Trans } from "@lingui/macro"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { Button } from "components/buttons/button"; import { Collapsible } from "components/collapsible"; import { useToast } from "components/toast/toastProvider"; +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; import { OptionContainer } from "plugins/lime-plugin-mesh-wide-config/src/components/OptionForm"; import { - useAddNewSectionModal, - useDeletePropModal, - useEditPropModal, + AddNewSectionFormProps, + AddNewSectionModal, + DeletePropModal, + EditPropModal, } from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; import { IMeshWideSection } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; -import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; export const ConfigSection = ({ dropdown }: { dropdown: IMeshWideSection }) => { return ( @@ -28,77 +30,92 @@ export const ConfigSection = ({ dropdown }: { dropdown: IMeshWideSection }) => { }; export const SectionEditOrDelete = ({ name }) => { - const { toggleModal: toggleDeleteModal, actionModal: deletePropModal } = - useDeletePropModal(); - const { toggleModal: toggleEditModal, actionModal: editPropertyModal } = - useEditPropModal(); - + const { + open: isEditOpen, + onOpen: openEdit, + onClose: onCloseEdit, + } = useDisclosure(); + const { + open: isDeleteModalOpen, + onOpen: openDeleteModal, + onClose: onCloseDeleteModal, + } = useDisclosure(); const { showToast } = useToast(); + const onEdit = async () => { + console.log("edit stuff"); + onCloseEdit(); + showToast({ + text: ( + + Edited {name} - {new Date().toDateString()} + + ), + onAction: () => { + console.log("Undo action"); + }, + }); + }; + + const onDelete = async () => { + console.log("delete stuff"); + onCloseDeleteModal(); + showToast({ + text: ( + + Deleted {name} - {new Date().toDateString()} + + ), + onAction: () => { + console.log("Undo action"); + }, + }); + }; + return ( - { - e.stopPropagation(); - editPropertyModal(name, () => { - console.log("edit stuff"); - toggleEditModal(); - showToast({ - text: ( - - Edited {name} - {new Date().toDateString()} - - ), - onAction: () => { - console.log("Undo action"); - }, - }); - }); - }} - onDelete={(e) => { - e.stopPropagation(); - deletePropModal(name, () => { - console.log("delete stuff"); - toggleDeleteModal(); - showToast({ - text: ( - - Deleted {name} - {new Date().toDateString()} - - ), - onAction: () => { - console.log("Undo action"); - }, - }); - }); - }} - /> + <> + + + + ); }; export const AddNewSectionBtn = () => { - const { toggleModal: toggleNewSectionModal, actionModal: addSectionModal } = - useAddNewSectionModal(); - + const { open, onOpen, onClose } = useDisclosure(); const { showToast } = useToast(); + + const onSuccess = (data: AddNewSectionFormProps) => { + console.log(`Added`, data); + onClose(); + showToast({ + text: ( + + Added section {data.name} - {new Date().toDateString()} + + ), + }); + }; return ( - + <> + + + ); }; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx index df5dbb9fe..5e805fb88 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx @@ -2,16 +2,17 @@ import { Trans } from "@lingui/macro"; import { useState } from "preact/hooks"; import { SubmitHandler, useForm } from "react-hook-form"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { Button } from "components/buttons/button"; import Divider from "components/divider"; import InputField from "components/inputs/InputField"; import { useToast } from "components/toast/toastProvider"; +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; import { - useDeletePropModal, - useEditPropModal, + DeletePropModal, + EditPropModal, } from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; -import { EditOrDelete } from "plugins/lime-plugin-mesh-wide/src/components/Components"; const EditOptionForm = ({ keyString, @@ -63,16 +64,31 @@ export const OptionContainer = ({ keyString: string; value: string; }) => { + const { + open: isDeleteModalOpen, + onOpen: openDeleteModal, + onClose: onCloseDeleteModal, + } = useDisclosure(); + const { showToast } = useToast(); + + const onDelete = async () => { + console.log("delete stuff"); + onCloseDeleteModal(); + showToast({ + text: ( + + Deleted {keyString} - {new Date().toDateString()} + + ), + onAction: () => { + console.log("Undo action"); + }, + }); + }; const [isEditing, setIsEditing] = useState(false); const toggleIsEditing = () => setIsEditing(!isEditing); - const { toggleModal: toggleDeleteModal, actionModal: deletePropModal } = - useDeletePropModal(); - const { toggleModal: toggleEditModal, actionModal: editPropertyModal } = - useEditPropModal(); - const { showToast } = useToast(); - return (
@@ -89,23 +105,7 @@ export const OptionContainer = ({
{keyString}
{ - e.stopPropagation(); - deletePropModal(keyString, () => { - console.log("delete stuff"); - toggleDeleteModal(); - showToast({ - text: ( - - Deleted {keyString} - - ), - onAction: () => { - console.log("Undo action"); - }, - }); - }); - }} + onDelete={openDeleteModal} />
{value}
@@ -115,18 +115,21 @@ export const OptionContainer = ({ keyString={keyString} value={value} onSubmit={(data) => { - editPropertyModal(keyString, () => { - console.log("edited stuff"); - toggleEditModal(); - toggleIsEditing(); - showToast({ - text: Edited {keyString}, - }); + console.log("edited stuff", data); + toggleIsEditing(); + showToast({ + text: Edited {data.key}, }); }} /> )}
+
); }; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx index bd0ec9257..82ee1fd77 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx @@ -1,87 +1,75 @@ import { Trans } from "@lingui/macro"; -import { ComponentChildren } from "preact"; -import { useCallback } from "preact/compat"; import { useForm } from "react-hook-form"; -import { ModalActions, useModal } from "components/Modal/Modal"; +import { Modal, ModalProps } from "components/Modal/Modal"; import InputField from "components/inputs/InputField"; -import { dataTypeNameMapping } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; -import { MeshWideMapDataTypeKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; +export const DeletePropModal = ({ + prop, + ...rest +}: { prop: string } & Pick) => ( + Delete property} {...rest}> +
+ + Are you sure you want to delete the {prop}{" "} + property? + +
+
+); -const useActionModal = ( - title: ComponentChildren, - btnText: ComponentChildren, - actionName: ModalActions -) => { - const { toggleModal, setModalState } = useModal(); +export const EditPropModal = ({ + prop, + ...rest +}: { prop: string } & Pick) => ( + Edit property} + successBtnText={Edit} + {...rest} + cancelBtn + > +
+ + Are you sure you want to edit the {prop}{" "} + property? + +
+
+); - const actionModal = useCallback( - (prop: string, actionCb: () => void) => { - setModalState({ - content: ( -
- - Are you sure you want to {title} the{" "} - {prop} property? - -
- ), - title, - [`${actionName}Cb`]: actionCb, - [`${actionName}BtnText`]: btnText, - }); - toggleModal(); - }, - [actionName, btnText, setModalState, title, toggleModal] - ); - return { actionModal, toggleModal }; -}; - -export const useDeletePropModal = () => - useActionModal( - Delete property, - Delete, - "delete" - ); - -export const useEditPropModal = () => - useActionModal( - Edit property, - Edit, - "success" - ); - -export const useAddNewSectionModal = () => { - const { toggleModal, setModalState } = useModal(); +export interface AddNewSectionFormProps { + name: string; +} +export const AddNewSectionModal = ({ + onSuccess, + ...rest +}: { onSuccess: (data: AddNewSectionFormProps) => void } & Pick< + ModalProps, + "isOpen" | "onClose" +>) => { const { register, handleSubmit, formState: { errors }, - } = useForm({ + } = useForm({ defaultValues: { name: "" }, }); - const actionModal = useCallback( - (actionCb: (data) => void) => { - setModalState({ - content: ( -
- Name} - register={register} - /> -
- ), - title: Add new section, - successCb: handleSubmit(actionCb), - successBtnText: Add, - }); - toggleModal(); - }, - [handleSubmit, register, setModalState, toggleModal] + return ( + Add new section} + successBtnText={Add} + {...rest} + onSuccess={handleSubmit(onSuccess)} + > +
+ Name} + register={register} + /> +
+
); - return { actionModal, toggleModal }; }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx index 3357844d0..efa5464a9 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx @@ -1,61 +1,65 @@ import { Trans } from "@lingui/macro"; -import { VNode } from "preact"; +import { ComponentChildren, VNode } from "preact"; import { useCallback } from "react"; -import { useModal } from "components/Modal/Modal"; +import { + CallbackFn, + Modal, + ModalProps, + useModal, +} from "components/Modal/Modal"; -interface IUseParallelQueriesModalProps { - useSuccessBtn?: boolean; - cb?: (e) => void; - title?: VNode; - content?: VNode; - btnTxt?: VNode; -} +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { + useParallelConfirmUpgrade, + useParallelScheduleUpgrade, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; -const useParallelQueriesModal = ({ - useSuccessBtn, - cb, - title, - content, - btnTxt = Schedule, -}: IUseParallelQueriesModalProps) => { - const { toggleModal, setModalState } = useModal(); - const runAndClose = useCallback(() => { - cb(null); - toggleModal(); - }, [cb, toggleModal]); +type IUseParallelQueriesModalProps = { + isSuccess: boolean; +} & Pick; - const showModal = useCallback(() => { - setModalState({ - content, - title, - successCb: useSuccessBtn ? runAndClose : undefined, - deleteCb: !useSuccessBtn ? runAndClose : undefined, - successBtnText: btnTxt, - deleteBtnText: btnTxt, - }); - toggleModal(); - }, [ - setModalState, - content, - title, - useSuccessBtn, - runAndClose, - btnTxt, - toggleModal, - ]); - return { showModal, toggleModal }; +export const ParallelQueriesModal = ({ + children, + isSuccess, + cb, + ...rest +}: { + cb: CallbackFn; + children: ComponentChildren; +} & IUseParallelQueriesModalProps & + Pick) => { + let props: Partial< + Pick< + ModalProps, + "onSuccess" | "onDelete" | "successBtnText" | "deleteBtnText" + > + > = { + onSuccess: cb, + successBtnText: Schedule, + }; + if (!isSuccess) { + props = { + onDelete: cb, + deleteBtnText: Schedule, + }; + } + return ( + + {children} + + ); }; -export const useScheduleUpgradeModal = ({ - useSuccessBtn, - cb, -}: IUseParallelQueriesModalProps) => { +export const ScheduleUpgradeModal = (props: IUseParallelQueriesModalProps) => { + const { callMutations: startScheduleMeshUpgrade } = + useParallelScheduleUpgrade(); + let title = All nodes are ready; let content = ( Schedule a firmware upgrade for all nodes on the network ); - if (!useSuccessBtn) { + if (!props.isSuccess) { title = Some nodes are not ready; content = ( @@ -65,23 +69,28 @@ export const useScheduleUpgradeModal = ({ ); } - return useParallelQueriesModal({ - useSuccessBtn, - cb, - title, - content, - }); + return ( + { + startScheduleMeshUpgrade(); + props.onClose(); + }} + title={title} + {...props} + > + {content} + + ); }; -export const useConfirmModal = ({ - useSuccessBtn, - cb, -}: IUseParallelQueriesModalProps) => { +export const ConfirmModal = (props: IUseParallelQueriesModalProps) => { + const { callMutations: confirmMeshUpgrade } = useParallelConfirmUpgrade(); + let title = All nodes are upgraded successfully; let content = ( Confirm mesh wide upgrade for all nodes on the network ); - if (!useSuccessBtn) { + if (!props.isSuccess) { title = Some nodes don't upgraded properly; content = ( @@ -90,15 +99,25 @@ export const useConfirmModal = ({ ); } - return useParallelQueriesModal({ - useSuccessBtn, - cb, - title, - content, - }); + return ( + { + confirmMeshUpgrade(); + props.onClose(); + }} + title={title} + {...props} + > + {content} + + ); }; -export const useAbortModal = ({ cb }: IUseParallelQueriesModalProps) => { +export const AbortModal = ({ + ...props +}: Omit) => { + const { abort } = useMeshUpgrade(); + const title = Abort current mesh wide upgrade?; const content = ( @@ -107,11 +126,17 @@ export const useAbortModal = ({ cb }: IUseParallelQueriesModalProps) => { ); const btnTxt = Abort; - return useParallelQueriesModal({ - useSuccessBtn: false, - cb, - title, - content, - btnTxt, - }); + return ( + { + abort(); + props.onClose(); + }} + {...props} + > + {content} + + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx index e2c82d4e8..11f8304b3 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx @@ -1,11 +1,203 @@ +import { Trans } from "@lingui/macro"; +import { useMemo } from "react"; + +import { useDisclosure } from "components/Modal/useDisclosure"; import { FooterStatus } from "components/status/footer"; +import { IStatusAndButton } from "components/status/statusAndButton"; + +import { + AbortModal, + ConfirmModal, + ScheduleUpgradeModal, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; +import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; +import { useParallelScheduleUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; +import { StepperState } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; + +export type ShowFooterStepperState = Extract< + StepperState, + | "UPDATE_AVAILABLE" + | "DOWNLOADED_MAIN" + | "TRANSACTION_STARTED" + | "UPGRADE_SCHEDULED" + | "CONFIRMATION_PENDING" + | "ERROR" +>; -import { useStep } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper"; +export function isShowFooterStepperState( + value: string +): value is ShowFooterStepperState { + return [ + "UPDATE_AVAILABLE", + "DOWNLOADED_MAIN", + "TRANSACTION_STARTED", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} + +function isShowAbortButtonState( + value: string +): value is ShowFooterStepperState { + return [ + "TRANSACTION_STARTED", + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} const NextStepFooter = () => { - const { step, showFooter } = useStep(); + const { + stepperState, + becomeMainNode, + startFwUpgradeTransaction, + allNodesReadyForUpgrade, + abort, + } = useMeshUpgrade(); + + const { errors: scheduleErrors } = useParallelScheduleUpgrade(); + + const { + open: showScheduleModal, + onOpen: openScheduleModal, + onClose: closeScheduleModal, + } = useDisclosure(); + + const { + open: showConfirmationModal, + onOpen: openConfirmationModal, + onClose: closeConfirmationModal, + } = useDisclosure(); + + const { + open: showAbort, + onOpen: openAbort, + onClose: closeAbort, + } = useDisclosure(); + + const showFooter = isShowFooterStepperState(stepperState); + + const step: IStatusAndButton | null = useMemo(() => { + if (!showFooter) return null; + + let step: IStatusAndButton; + switch (stepperState as ShowFooterStepperState) { + case "UPDATE_AVAILABLE": + step = { + status: "success", + onClick: () => becomeMainNode(), + children: ( + + Download remote firmware +
+ to start mesh upgrade +
+ ), + btn: Start mesh upgrade, + }; + break; + case "DOWNLOADED_MAIN": + step = { + status: "success", + onClick: startFwUpgradeTransaction, + children: Ready to start mesh wide upgrade, + btn: Start, + }; + break; + case "TRANSACTION_STARTED": + step = { + status: allNodesReadyForUpgrade ? "success" : "warning", + onClick: openScheduleModal, + children: allNodesReadyForUpgrade ? ( + Ready to start mesh wide upgrade + ) : ( + + Some nodes are not ready for upgrade
+ Check node details for more info +
+ ), + btn: Schedule upgrade, + }; + break; + case "UPGRADE_SCHEDULED": { + const data: Omit = { + onClick: openScheduleModal, + btn: Schedule again, + }; + if (scheduleErrors?.length) { + step = { + ...data, + status: "warning", + children: Some nodes have errors, + }; + } + step = { + ...data, + status: "success", + children: All nodes scheduled successful, + }; + break; + } + case "CONFIRMATION_PENDING": + step = { + status: "success", + onClick: openConfirmationModal, + children: Confirm upgrade on all nodes, + btn: Confirm, + }; + break; + case "ERROR": + default: + step = { + status: "warning", + children: Try last step again, + }; + } + if (isShowAbortButtonState(stepperState)) { + const showAbort: Pick< + IStatusAndButton, + "btnCancel" | "onClickCancel" + > = { + btnCancel: Abort, + onClickCancel: openAbort, + }; + step = { ...step, ...showAbort }; + } + return step; + }, [ + abort, + allNodesReadyForUpgrade, + becomeMainNode, + scheduleErrors?.length, + showConfirmationModal, + showFooter, + showScheduleModal, + startFwUpgradeTransaction, + stepperState, + ]); - return <>{showFooter && }; + return ( + <> + {showFooter && ( + <> + + + + + + )} + + ); }; export default NextStepFooter; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx index 65e376640..3ccb85ce0 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx @@ -1,12 +1,13 @@ import { Trans } from "@lingui/macro"; import { useMemo } from "react"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { IStatusAndButton } from "components/status/statusAndButton"; import { - useAbortModal, - useConfirmModal, - useScheduleUpgradeModal, + AbortModal, + ConfirmModal, + ScheduleUpgradeModal, } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; import { @@ -98,180 +99,3 @@ export const getStepperStatus = ( } return "INITIAL"; }; - -export type ShowFooterStepperState = Extract< - StepperState, - | "UPDATE_AVAILABLE" - | "DOWNLOADED_MAIN" - | "TRANSACTION_STARTED" - | "UPGRADE_SCHEDULED" - | "CONFIRMATION_PENDING" - | "ERROR" ->; - -export function isShowFooterStepperState( - value: string -): value is ShowFooterStepperState { - return [ - "UPDATE_AVAILABLE", - "DOWNLOADED_MAIN", - "TRANSACTION_STARTED", - "UPGRADE_SCHEDULED", - "CONFIRMATION_PENDING", - "ERROR", - ].includes(value); -} - -function isShowAbortButtonState( - value: string -): value is ShowFooterStepperState { - return [ - "TRANSACTION_STARTED", - "UPGRADE_SCHEDULED", - "CONFIRMATION_PENDING", - "ERROR", - ].includes(value); -} - -export const useStep = () => { - const { - stepperState, - becomeMainNode, - startFwUpgradeTransaction, - allNodesReadyForUpgrade, - abort, - } = useMeshUpgrade(); - - const { callMutations: startScheduleMeshUpgrade, errors: scheduleErrors } = - useParallelScheduleUpgrade(); - - const { callMutations: confirmMeshUpgrade } = useParallelConfirmUpgrade(); - - const { showModal: showScheduleModal } = useScheduleUpgradeModal({ - useSuccessBtn: allNodesReadyForUpgrade, - cb: () => { - return startScheduleMeshUpgrade(); - }, - }); - - const { showModal: showConfirmationModal } = useConfirmModal({ - // Ideally we have to implement some kind of state before run the upgrade to check if all nodes are up again. - useSuccessBtn: true, - cb: () => { - return confirmMeshUpgrade(); - }, - }); - - const { showModal: showAbortModal } = useAbortModal({ - cb: () => { - return abort(); - }, - }); - - const showFooter = isShowFooterStepperState(stepperState); - - const step: IStatusAndButton | null = useMemo(() => { - if (!showFooter) return null; - - let step: IStatusAndButton; - switch (stepperState as ShowFooterStepperState) { - case "UPDATE_AVAILABLE": - step = { - status: "success", - onClick: () => becomeMainNode(), - children: ( - - Download remote firmware -
- to start mesh upgrade -
- ), - btn: Start mesh upgrade, - }; - break; - case "DOWNLOADED_MAIN": - step = { - status: "success", - onClick: startFwUpgradeTransaction, - children: Ready to start mesh wide upgrade, - btn: Start, - }; - break; - case "TRANSACTION_STARTED": - step = { - status: allNodesReadyForUpgrade ? "success" : "warning", - onClick: () => { - showScheduleModal(); - }, - children: allNodesReadyForUpgrade ? ( - Ready to start mesh wide upgrade - ) : ( - - Some nodes are not ready for upgrade
- Check node details for more info -
- ), - btn: Schedule upgrade, - }; - break; - case "UPGRADE_SCHEDULED": { - const data: Omit = { - onClick: showScheduleModal, - btn: Schedule again, - }; - if (scheduleErrors?.length) { - step = { - ...data, - status: "warning", - children: Some nodes have errors, - }; - } - step = { - ...data, - status: "success", - children: All nodes scheduled successful, - }; - break; - } - case "CONFIRMATION_PENDING": - step = { - status: "success", - onClick: showConfirmationModal, - children: Confirm upgrade on all nodes, - btn: Confirm, - }; - break; - case "ERROR": - default: - step = { - status: "warning", - children: Try last step again, - }; - } - if (isShowAbortButtonState(stepperState)) { - const showAbort: Pick< - IStatusAndButton, - "btnCancel" | "onClickCancel" - > = { - btnCancel: Abort, - onClickCancel: async () => { - showAbortModal(); - }, - }; - step = { ...step, ...showAbort }; - } - return step; - }, [ - abort, - allNodesReadyForUpgrade, - becomeMainNode, - scheduleErrors?.length, - showConfirmationModal, - showFooter, - showScheduleModal, - startFwUpgradeTransaction, - stepperState, - ]); - - return { step, showFooter }; -}; diff --git a/plugins/lime-plugin-mesh-wide/src/components/Components.tsx b/plugins/lime-plugin-mesh-wide/src/components/Components.tsx index 9c802d2be..53b0ea7a1 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Components.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Components.tsx @@ -46,16 +46,3 @@ export const StatusMessage = ({ {children}
); - -export const EditOrDelete = ({ - onEdit, - onDelete, -}: { - onEdit: (e) => void; - onDelete: (e) => void; -}) => ( -
- - -
-); diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx index 44e07459e..c22a6a373 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx @@ -3,12 +3,13 @@ import { useMemo } from "preact/compat"; import { useState } from "preact/hooks"; import { useCallback } from "react"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { Warning } from "components/icons/status"; import Tabs from "components/tabs"; import { useToast } from "components/toast/toastProvider"; import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; -import { useSetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; +import { SetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; import { getQueryByLinkType, usePointToPointErrors, @@ -283,6 +284,8 @@ export const LinkReferenceStatus = ({ linkToShow, reference, }: LinkMapFeature) => { + const { open, onOpen, onClose } = useDisclosure(); + const isNewLink = !reference; const { errors } = usePointToPointErrors({ @@ -307,9 +310,6 @@ export const LinkReferenceStatus = ({ referenceError = true; } - // Modal to set ref state - const { closeModal, confirmModal, isModalOpen } = - useSetLinkReferenceStateModal(); const { showToast } = useToast(); // Get nodes to update @@ -355,9 +355,9 @@ export const LinkReferenceStatus = ({ text: Error setting new reference state!, }); } finally { - closeModal(); + onClose(); } - }, [callMutations, closeModal, showToast]); + }, [callMutations, onClose, showToast]); let btnText = ( @@ -394,20 +394,23 @@ export const LinkReferenceStatus = ({ errors?.hasErrors || isDown || isNewLink || referenceError; return ( - - confirmModal({ - dataType: linkToShow.type, - nodes: Object.values(nodesToUpdate), - isDown, - cb: setReferenceState, - }) - } - > - {errorMessage} - + <> + + {errorMessage} + + + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx index 3208f9b98..f8a26a66f 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -1,6 +1,8 @@ import { Trans } from "@lingui/macro"; +import { DomEvent } from "leaflet"; import { useCallback } from "react"; +import { useDisclosure } from "components/Modal/useDisclosure"; import UpdateSharedStateBtn from "components/shared-state/UpdateSharedStateBtn"; import useSharedStateSync from "components/shared-state/useSharedStateSync"; import { useToast } from "components/toast/toastProvider"; @@ -11,7 +13,7 @@ import { Row, TitleAndText, } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index"; -import { useSetNodeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; +import { SetNodeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/modals"; import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors"; import { getArrayDifference } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { @@ -146,6 +148,7 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => { }; export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { + const { open, onOpen, onClose } = useDisclosure(); const { hasErrors: hasNodeErrors, isDown, @@ -162,8 +165,6 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { const { data: meshWideNodesReference, isError: isReferenceError } = useMeshWideNodesReference({}); - const { toggleModal, confirmModal, isModalOpen } = - useSetNodeInfoReferenceStateModal(); const { showToast } = useToast(); const { syncNode } = useSharedStateSync({ @@ -190,17 +191,11 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { }); }, onSettled: () => { - if (isModalOpen) toggleModal(); + if (open) onClose(); }, }, }); - const setReferenceState = useCallback(async () => { - confirmModal(hostname, isDown, async () => { - await mutateAsync(); - }); - }, [confirmModal, hostname, isDown, mutateAsync]); - let btnText = Set reference state for this node; if (isDown) { btnText = Delete this this node from reference state; @@ -230,13 +225,24 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => { const showSetReferenceButton = hasNodeErrors || isNewNode || referenceError; return ( - - {errorMessage} - + <> + + {errorMessage} + + { + await mutateAsync(); + }} + onClose={onClose} + isOpen={open} + /> + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx index 131be722e..a8dec3224 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx @@ -1,9 +1,9 @@ import { Trans } from "@lingui/macro"; import { useMutation } from "@tanstack/react-query"; -import { useEffect, useState } from "preact/hooks"; -import { useCallback } from "react"; +import { useCallback, useState } from "preact/hooks"; -import { useModal } from "components/Modal/Modal"; +import { Modal, ModalProps } from "components/Modal/Modal"; +import { useDisclosure } from "components/Modal/useDisclosure"; import { Button } from "components/buttons/button"; import { ErrorMsg } from "components/form"; import Loading from "components/loading"; @@ -39,14 +39,15 @@ const useRemoteReboot = (opts?) => { }); }; -const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { - const modalKey = "rebootNodeModal"; - const { toggleModal, setModalState, isModalOpen, openModalKey } = - useModal(); +const RebootNodeModal = ({ + node, + isOpen, + onClose, +}: { node: INodeInfo } & Pick) => { const [password, setPassword] = useState(""); const { mutate, isLoading, error } = useRemoteReboot({ onSuccess: () => { - toggleModal(modalKey); + onClose(); }, }); @@ -58,73 +59,58 @@ const useRebootNodeModal = ({ node }: { node: INodeInfo }) => { mutate({ ip: node.ipv4, password }); }, [mutate, node.ipv4, password]); - const updateModalState = useCallback(() => { - setModalState({ - title: Reboot node {node.hostname}, - content: ( -
- - Are you sure you want to reboot this node? This action - will disconnect the node from the network for a few - minutes.
- Add shared password or let it empty if no password is - set. -
- {isLoading && } - {!isLoading && ( -
- - - {error && ( - - - Error performing reboot: {error} - - - )} -
- )} -
- ), - successCb: doLogin, - successBtnText: Reboot, - }); - }, [doLogin, error, isLoading, node.hostname, password, setModalState]); - - const rebootModal = useCallback(() => { - updateModalState(); - toggleModal(modalKey); - }, [toggleModal, updateModalState]); - - // Update modal state with mutation result - useEffect(() => { - if (isModalOpen && openModalKey === modalKey) { - updateModalState(); - } - }, [isLoading, error, isModalOpen, updateModalState, openModalKey]); - - return { rebootModal, toggleModal, isModalOpen }; + return ( + Reboot node {node.hostname}
} + successBtnText={Reboot} + > +
+ + Are you sure you want to reboot this node? This action will + disconnect the node from the network for a few minutes.{" "} +
+ Add shared password or let it empty if no password is set. +
+ {isLoading && } + {!isLoading && ( +
+ + + {error && ( + + Error performing reboot: {error} + + )} +
+ )} +
+ + ); }; const RemoteRebootBtn = ({ node }: { node: INodeInfo }) => { - const { rebootModal, isModalOpen } = useRebootNodeModal({ - node, - }); + const { open, onOpen, onClose } = useDisclosure(); return ( - + <> + + + ); }; diff --git a/plugins/lime-plugin-mesh-wide/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide/src/components/modals.tsx index ab7ce6a00..6a443fb23 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/modals.tsx @@ -1,95 +1,83 @@ import { Trans } from "@lingui/macro"; -import { ComponentChildren } from "preact"; -import { useCallback } from "preact/compat"; -import { useForm } from "react-hook-form"; -import { ModalActions, useModal } from "components/Modal/Modal"; -import InputField from "components/inputs/InputField"; +import { Modal, ModalProps } from "components/Modal/Modal"; import { dataTypeNameMapping } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; import { MeshWideMapDataTypeKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; -export const useSetNodeInfoReferenceStateModal = () => { - const { toggleModal, setModalState, isModalOpen } = useModal(); - - const confirmModal = useCallback( - (nodeName: string, isDown: boolean, cb: () => Promise) => { - let title = Set reference state for {nodeName}; - let content = Set the reference state for this node.; - if (isDown) { - title = ( - Remove {nodeName} from the reference state - ); - content = ( - - This node seems down, remove them from the reference - state? - - ); - } - setModalState({ - title, - content, - successCb: cb, - successBtnText: Continue, - }); - toggleModal(); - }, - [setModalState, toggleModal] +export const SetNodeInfoReferenceStateModal = ({ + nodeName, + isDown, + ...modalProps +}: { nodeName: string; isDown: boolean } & Pick< + ModalProps, + "onSuccess" | "isOpen" | "onClose" +>) => { + let title = Set reference state for {nodeName}; + let content = Set the reference state for this node.; + if (isDown) { + title = Remove {nodeName} from the reference state; + content = ( + + This node seems down, remove them from the reference state? + + ); + } + return ( + Continue} + {...modalProps} + > + {content} + ); - return { confirmModal, toggleModal, isModalOpen }; }; -export const useSetLinkReferenceStateModal = () => { - const { toggleModal, setModalState, isModalOpen, closeModal } = useModal(); - - const confirmModal = ({ - dataType, - nodes, - isDown, - cb, - }: { - dataType: MeshWideMapDataTypeKeys; - nodes: string[]; - isDown: boolean; - cb: () => Promise; - }) => { - let title = ( +export const SetLinkReferenceStateModal = ({ + dataType, + nodes, + isDown, + ...modalProps +}: { + dataType: MeshWideMapDataTypeKeys; + nodes: string[]; + isDown: boolean; +} & Pick) => { + let title = ( + + Set reference state for this {dataTypeNameMapping(dataType)}? + + ); + let content = ( + This will set the reference state of this link: + ); + if (isDown) { + title = ( - Set reference state for this {dataTypeNameMapping(dataType)}? + Remove this {dataTypeNameMapping(dataType)} from the reference + state ); - let content = ( - This will set the reference state of this link: + content = ( + + This link seems down, remove them from the reference state? + ); - if (isDown) { - title = ( - - Remove this {dataTypeNameMapping(dataType)} from the - reference state - - ); - content = ( - - This link seems down, remove them from the reference state? - - ); - } - setModalState({ - title, - content: ( -
- {content} -
-
- {nodes.join(", ")} -
+ } + return ( + Continue} + {...modalProps} + > +
+ {content} +
+
+ {nodes.join(", ")}
- ), - successCb: cb, - successBtnText: Continue, - }); - toggleModal(); - }; - return { confirmModal, closeModal, isModalOpen }; +
+
+ ); }; diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index d7dd9826d..d3a2f5740 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -1,153 +1,128 @@ import { Trans } from "@lingui/macro"; -import { ComponentChildren, createContext } from "preact"; -import { useContext, useState } from "preact/hooks"; -import { useCallback } from "react"; +import { createContext } from "preact"; +import { createPortal } from "preact/compat"; +import { useCallback, useContext, useState } from "preact/hooks"; import { Button } from "components/buttons/button"; import Divider from "components/divider"; -interface ModalContextProps { - isModalOpen: boolean; - openModalKey?: string | null; - toggleModal: (key?: string) => void; - closeModal: (key?: string) => void; - setModalState: (state?: ModalState) => void; +export type ModalActionsProps = { + isOpen: boolean; + onClose: () => void; + onSuccess?: CallbackFn; + onDelete?: CallbackFn; +}; + +export type ModalPortalProps = { + children?; + title?; + cancelBtn?; + successBtnText?; + deleteBtnText?; +}; + +type ModalContextProps = { isLoading: boolean; -} - -type CallbackFn = () => void | Promise; - -interface ModalState { - content?: ComponentChildren; - title: ComponentChildren | string; - cancelBtn?: boolean; - successCb?: CallbackFn; - successBtnText?: ComponentChildren; - deleteCb?: CallbackFn; - deleteBtnText?: ComponentChildren; - isLoading?: boolean; -} - -const ModalContext = createContext({ - isModalOpen: false, - openModalKey: null, - toggleModal: () => {}, - closeModal: () => {}, - setModalState: () => {}, - isLoading: false, -}); +} & ModalProps; + +export type CallbackFn = () => void | Promise; + +const ModalContext = createContext(null); + +export type ModalProps = ModalActionsProps & ModalPortalProps; export const useModal = () => { const context = useContext(ModalContext); if (context === undefined) { - throw new Error("useModal must be used within a UseModalProvider"); + throw new Error("useModal must be used within a Modal component"); } return context; }; -export type ModalActions = "success" | "delete"; - -export const UseModalProvider = ({ children }) => { - const [isModalOpen, setModalOpen] = useState(false); - const [openModalKey, setOpenModalKey] = useState(null); +export const Modal = ({ + children, + title, + cancelBtn = false, + onSuccess, + successBtnText, + onDelete, + deleteBtnText, + isOpen, + onClose, +}: ModalProps) => { const [isLoading, setIsLoading] = useState(false); - const [modalState, setModalState] = useState({ - content: <>, - title: "", - cancelBtn: false, - successCb: () => {}, - successBtnText: Success, - deleteCb: () => {}, - deleteBtnText: Cancel, - }); - - const toggleModal = useCallback((key?: string) => { - setModalOpen((prevIsModalOpen) => !prevIsModalOpen); - setOpenModalKey(key ?? null); - }, []); - - const closeModal = useCallback((key?: string) => { - setModalOpen(false); - setOpenModalKey(null); - }, []); - const runCb = useCallback( async (cb: CallbackFn) => { if (isLoading) return; setIsLoading(true); await cb(); + // For some reason non async functions doesn't work properly. + // This is a trick to let them be called properly + await new Promise((resolve) => setTimeout(resolve, 0)); setIsLoading(false); }, [isLoading] ); - const successCb = - modalState.successCb != null ? () => runCb(modalState.successCb) : null; - const deleteCb = - modalState.deleteCb != null ? () => runCb(modalState.deleteCb) : null; + let successCb = null; + if (onSuccess) { + successCb = () => runCb(onSuccess); + } + + let deleteCb = null; + if (onDelete) { + deleteCb = () => runCb(onDelete); + } return ( - {children} - - {modalState.content} - + {isOpen && ( + + {children} + + )} ); }; -const Modal = ({ - isModalOpen, - toggleModal, +const ModalPortal = ({ children, title, - cancelBtn = true, - successCb, + cancelBtn = false, successBtnText = Success, - deleteCb, - deleteBtnText = Cancel, - isLoading, -}: { - isModalOpen: boolean; - toggleModal: () => void; - children?: ComponentChildren; -} & ModalState) => { + deleteBtnText = Delete, +}: ModalPortalProps) => { + const { isOpen, isLoading, onClose, onSuccess, onDelete } = useModal(); + const stopPropagation = (e) => { e.stopPropagation(); }; - return ( + + if (!isOpen) { + return null; + } + + return createPortal( <> -
+
{ - if (!isLoading) toggleModal(); + if (!isLoading) onClose(); }} >
- {/*
*/} - {successCb && ( + {onSuccess && ( )} - {deleteCb && ( + {onDelete && (
- + , + document.body ); }; diff --git a/src/components/Modal/useDisclosure.ts b/src/components/Modal/useDisclosure.ts new file mode 100644 index 000000000..d6fbc0a91 --- /dev/null +++ b/src/components/Modal/useDisclosure.ts @@ -0,0 +1,61 @@ +import { useCallback, useState } from "preact/hooks"; + +export interface UseDisclosureProps { + open?: boolean; + defaultOpen?: boolean; + id?: string; + + onClose?(): void; + + onOpen?(): void; +} + +/** + * `useDisclosure` is a custom hook used to help handle common open, close, or toggle scenarios. + * It can be used to control feedback component such as `Modal`, `AlertDialog`, `Drawer`, etc. + * + * @see Docs https://chakra-ui.com/docs/hooks/use-disclosure + */ +export function useDisclosure(props: UseDisclosureProps = {}) { + const { onClose: onCloseProp, onOpen: onOpenProp, open: openProp } = props; + + const handleOpen = useCallback(onOpenProp, []); + const handleClose = useCallback(onCloseProp, []); + + const [openState, setopen] = useState(props.defaultOpen || false); + + const open = openProp !== undefined ? openProp : openState; + + const isControlled = openProp !== undefined; + + const onClose = useCallback(() => { + if (!isControlled) { + setopen(false); + } + handleClose?.(); + }, [isControlled, handleClose]); + + const onOpen = useCallback(() => { + if (!isControlled) { + setopen(true); + } + handleOpen?.(); + }, [isControlled, handleOpen]); + + const onToggle = useCallback(() => { + if (open) { + onClose(); + } else { + onOpen(); + } + }, [open, onOpen, onClose]); + + return { + open, + onOpen, + onClose, + onToggle, + }; +} + +export type UseDisclosureReturn = ReturnType; diff --git a/src/components/app.tsx b/src/components/app.tsx index a45d4bbca..3ac12c60b 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -6,7 +6,6 @@ import Router from "preact-router"; import { useEffect } from "preact/hooks"; import { Provider } from "react-redux"; -import { UseModalProvider } from "components/Modal/Modal"; import { ToastProvider } from "components/toast/toastProvider"; import { Menu } from "containers/Menu"; @@ -112,11 +111,9 @@ const AppDefault = () => { - - - - - + + + From ec3bb058eb7b53a6e5bcad200992c19261186c3c Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 8 Oct 2024 10:20:32 -0300 Subject: [PATCH 19/22] improve spanish tranlation (mostly by Jesi) --- i18n/en/messages.po | 839 +++++++++++++++++++++++++++++++-- i18n/es/messages.po | 1098 +++++++++++++++++++++++++++++++++++++------ i18n/it/messages.po | 839 +++++++++++++++++++++++++++++++-- i18n/pt/messages.po | 839 +++++++++++++++++++++++++++++++-- 4 files changed, 3378 insertions(+), 237 deletions(-) diff --git a/i18n/en/messages.po b/i18n/en/messages.po index c4d78aa3f..926673955 100644 --- a/i18n/en/messages.po +++ b/i18n/en/messages.po @@ -13,6 +13,18 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:46 +msgid "(Main Node) {descriptionMsg}" +msgstr "(Main Node) {descriptionMsg}" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx:40 +msgid "(new)" +msgstr "(new)" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:26 +msgid "10 of 12 node are ready to update" +msgstr "10 of 12 node are ready to update" + #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:67 msgid "A new firmware version has been released" msgstr "" @@ -21,6 +33,19 @@ msgstr "" msgid "A reboot is needed to apply changes" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:109 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:256 +msgid "Abort" +msgstr "Abort" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:102 +msgid "Abort current mesh wide upgrade?" +msgstr "Abort current mesh wide upgrade?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:23 +msgid "Aborting" +msgstr "Aborting" + #: plugins/lime-plugin-pirania/src/piraniaMenu.js:9 msgid "Access Vouchers" msgstr "Access Vouchers" @@ -49,6 +74,23 @@ msgstr "Activation deadline: {0}" msgid "Active" msgstr "Active" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:80 +msgid "Add" +msgstr "Add" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:101 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:78 +msgid "Add new section" +msgstr "Add new section" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:92 +msgid "Added section {0} - {1}" +msgstr "Added section {0} - {1}" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:46 +msgid "After a time the upgrade will be performed" +msgstr "After a time the upgrade will be performed" + #: plugins/lime-plugin-align/src/alignMenu.js:9 msgid "Align" msgstr "" @@ -57,10 +99,38 @@ msgstr "" msgid "All Vouchers" msgstr "All Vouchers" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:54 +msgid "All nodes are ready" +msgstr "All nodes are ready" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:80 +msgid "All nodes are upgraded successfully" +msgstr "All nodes are upgraded successfully" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:232 +msgid "All nodes scheduled successful" +msgstr "All nodes scheduled successful" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:87 +msgid "Are you sure you want to confirm the upgrade? <0/>Check node list to see the network status" +msgstr "Are you sure you want to confirm the upgrade? <0/>Check node list to see the network status" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:66 +msgid "Are you sure you want to reboot this node? This action will disconnect the node from the network for a few minutes. <0/>Add shared password or let it empty if no password is set." +msgstr "Are you sure you want to reboot this node? This action will disconnect the node from the network for a few minutes. <0/>Add shared password or let it empty if no password is set." + #: src/containers/RebootPage/RebootPage.js:39 msgid "Are you sure you want to reboot?" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:61 +msgid "Are you sure you want to start mesh wide upgrade? <0/>Check node list to see the network status" +msgstr "Are you sure you want to start mesh wide upgrade? <0/>Check node list to see the network status" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:24 +msgid "Are you sure you want to {title} the <0>{prop} property?" +msgstr "Are you sure you want to {title} the <0>{prop} property?" + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:24 msgid "Are you sure?" msgstr "Are you sure?" @@ -88,6 +158,22 @@ msgstr "Author node: {author_node}" msgid "Available" msgstr "Available" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:54 +msgid "Await until it reboots" +msgstr "Await until it reboots" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:50 +msgid "Awaiting confirmation" +msgstr "Awaiting confirmation" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:86 +msgid "Babel Links" +msgstr "Babel Links" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:88 +msgid "Babel Links Reference" +msgstr "Babel Links Reference" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:22 msgid "Back" msgstr "Back" @@ -96,10 +182,22 @@ msgstr "Back" msgid "Background Color" msgstr "Background Color" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:82 +msgid "Batman Links" +msgstr "Batman Links" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:84 +msgid "Batman Links Reference" +msgstr "Batman Links Reference" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:41 msgid "Best signal" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:65 +msgid "Board" +msgstr "Board" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:96 msgid "Calculating network path" msgstr "" @@ -107,6 +205,8 @@ msgstr "" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:83 #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:150 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:14 +#: src/components/Modal/Modal.tsx:62 +#: src/components/Modal/Modal.tsx:128 #: src/components/banner/index.js:20 msgid "Cancel" msgstr "" @@ -131,6 +231,10 @@ msgstr "Cannot use Radio 0, it's being used for mesh links" msgid "Cellphone Instructions" msgstr "Cellphone Instructions" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:132 +msgid "Chains" +msgstr "Chains" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:76 msgid "Change" msgstr "" @@ -140,9 +244,18 @@ msgid "Change Shared Password" msgstr "" #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:123 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:143 msgid "Channel" msgstr "Channel" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:22 +msgid "Check if network is working properly and confirm the upgrade<0/>If not confirmed, the upgrade will be rolled back after a while" +msgstr "Check if network is working properly and confirm the upgrade<0/>If not confirmed, the upgrade will be rolled back after a while" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:91 +msgid "Check<0/>Alignment" +msgstr "Check<0/>Alignment" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:100 msgid "Checking connection" msgstr "" @@ -173,6 +286,10 @@ msgstr "" msgid "Click at Show Console to follow the remote support session." msgstr "" +#: src/components/Modal/Modal.tsx:205 +msgid "Close" +msgstr "Close" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:170 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:183 msgid "Close Session" @@ -205,13 +322,46 @@ msgid "Configure your new community network" msgstr "" #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:11 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:241 msgid "Confirm" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:82 +msgid "Confirm mesh wide upgrade for all nodes on the network" +msgstr "Confirm mesh wide upgrade for all nodes on the network" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:240 +msgid "Confirm upgrade on all nodes" +msgstr "Confirm upgrade on all nodes" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:18 +msgid "Confirmation pending" +msgstr "Confirmation pending" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:19 +msgid "Confirmed" +msgstr "Confirmed" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:19 +msgid "Confirmed with some errors" +msgstr "Confirmed with some errors" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:15 +msgid "Confirmed!" +msgstr "Confirmed!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:63 +msgid "Confirming all upgraded nodes" +msgstr "Confirming all upgraded nodes" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:127 msgid "Congratulations" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:62 +msgid "Congratulations, this node was upgraded and confirmed successfully" +msgstr "Congratulations, this node was upgraded and confirmed successfully" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:37 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:199 @@ -235,6 +385,11 @@ msgstr "Connection to the cellphone" msgid "Connection to the internet" msgstr "Connection to the internet" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:34 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:90 +msgid "Continue" +msgstr "Continue" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:134 #: plugins/lime-plugin-pirania/src/screens/voucherList.js:122 msgid "Create" @@ -273,6 +428,30 @@ msgstr "Creation date: {0}" msgid "Currently your node has version:" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:44 +msgid "Delete" +msgstr "Delete" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:43 +msgid "Delete property" +msgstr "Delete property" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:206 +msgid "Delete this this node from reference state" +msgstr "Delete this this node from reference state" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:372 +msgid "Delete this {0}<0/>from reference state" +msgstr "Delete this {0}<0/>from reference state" + +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:99 +msgid "Deleted {keyString}" +msgstr "Deleted {keyString}" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:64 +msgid "Deleted {name} - {0}" +msgstr "Deleted {name} - {0}" + #: plugins/lime-plugin-pirania/src/screens/editVoucher.js:28 msgid "Description" msgstr "Description" @@ -282,10 +461,15 @@ msgstr "Description" msgid "Description: {name}" msgstr "Description: {name}" -#: plugins/lime-plugin-rx/src/rxPage.js:51 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:89 +#: plugins/lime-plugin-rx/src/sections/system.tsx:48 msgid "Device" msgstr "" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:125 +msgid "Diagnose" +msgstr "Diagnose" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:54 #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:72 #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigItem.tsx:20 @@ -298,14 +482,31 @@ msgstr "" msgid "Don't show this message again" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:53 +msgid "Done" +msgstr "Done" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:96 msgid "Download" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:183 +msgid "Download remote firmware<0/>to start mesh upgrade" +msgstr "Download remote firmware<0/>to start mesh upgrade" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:50 +msgid "Downloaded version<0/>{0}" +msgstr "Downloaded version<0/>{0}" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:103 +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:35 msgid "Downloading" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:15 +msgid "Downloading new firmware" +msgstr "Downloading new firmware" + #: plugins/lime-plugin-pirania/src/screens/postCreate.js:18 #: plugins/lime-plugin-pirania/src/screens/voucher.js:59 msgid "Duration: is permanent" @@ -316,6 +517,7 @@ msgstr "Duration: is permanent" msgid "Duration: {days, plural, one {# day} other {# days}}" msgstr "Duration: {days, plural, one {# day} other {# days}}" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:51 #: plugins/lime-plugin-pirania/src/screens/voucher.js:90 msgid "Edit" msgstr "Edit" @@ -324,10 +526,22 @@ msgstr "Edit" msgid "Edit Voucher" msgstr "Edit Voucher" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:50 +msgid "Edit property" +msgstr "Edit property" + #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:50 msgid "Edit wellcome screen" msgstr "Edit wellcome screen" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:123 +msgid "Edited {keyString}" +msgstr "Edited {keyString}" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:47 +msgid "Edited {name} - {0}" +msgstr "Edited {name} - {0}" + #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:25 msgid "Enable Community Roaming AP" msgstr "" @@ -361,6 +575,10 @@ msgstr "Encryption: {encryptionMethod}" msgid "Error" msgstr "" +#: src/components/toast/toasts.tsx:13 +msgid "Error connecting with {nodeInfo}, is node up?" +msgstr "Error connecting with {nodeInfo}, is node up?" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:61 msgid "Error destination network is not configured yet" msgstr "Error destination network is not configured yet" @@ -377,6 +595,14 @@ msgstr "Error downloading lime community" msgid "Error getting scan results" msgstr "Error getting scan results" +#: plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx:41 +msgid "Error loading leaflet" +msgstr "Error loading leaflet" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:85 +msgid "Error performing reboot: {error}" +msgstr "Error performing reboot: {error}" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:40 msgid "Error reaching hostname!" msgstr "Error reaching hostname!" @@ -386,6 +612,14 @@ msgstr "Error reaching hostname!" msgid "Error retrieving associated list" msgstr "Error retrieving associated list" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:43 +msgid "Error retrieving the status, is this node outdated?" +msgstr "Error retrieving the status, is this node outdated?" + +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:101 +msgid "Error retrieving<0/>last internet path" +msgstr "Error retrieving<0/>last internet path" + #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanList.js:155 msgid "Error scanning networks" msgstr "Error scanning networks" @@ -394,14 +628,31 @@ msgstr "Error scanning networks" msgid "Error setting network" msgstr "Error setting network" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:355 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:189 +msgid "Error setting new reference state!" +msgstr "Error setting new reference state!" + #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanPage.tsx:83 msgid "Error stopping scan" msgstr "Error stopping scan" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx:12 +msgid "Error!" +msgstr "Error!" + #: plugins/lime-plugin-node-admin/src/layouts/configPageLayout.tsx:55 msgid "Error: Not Saved" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:35 +msgid "Errors found getting mesh info!" +msgstr "Errors found getting mesh info!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:32 +msgid "Everything is up to date!" +msgstr "Everything is up to date!" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:66 msgid "Expiration date: {0}" msgstr "Expiration date: {0}" @@ -422,7 +673,7 @@ msgstr "Expires {0}" #: plugins/lime-plugin-align/src/alignPage.js:37 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:80 -#: plugins/lime-plugin-rx/src/rxPage.js:93 +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:67 msgid "Fetching name" msgstr "" @@ -435,10 +686,23 @@ msgid "Filter by" msgstr "Filter by" #: plugins/lime-plugin-firmware/src/firmwareMenu.js:9 -#: plugins/lime-plugin-rx/src/rxPage.js:58 +#: plugins/lime-plugin-rx/src/sections/system.tsx:49 msgid "Firmware" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:40 +msgid "Firmware download and verified" +msgstr "Firmware download and verified" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:16 +msgid "Firmware downloaded" +msgstr "Firmware downloaded" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:80 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:69 +msgid "Firmware version" +msgstr "Firmware version" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:151 msgid "From" msgstr "" @@ -484,8 +748,16 @@ msgid "I don't know the shared password" msgstr "" #: plugins/lime-plugin-rx/src/rxPage.js:181 -msgid "IP Addresses" -msgstr "" +#~ msgid "IP Addresses" +#~ msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:85 +msgid "IPv4" +msgstr "IPv4" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:86 +msgid "IPv6" +msgstr "IPv6" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:73 msgid "If network has been already created, look it up to join" @@ -503,15 +775,39 @@ msgstr "If you invalidate this voucher no one will be able to use it anymore. Th msgid "If your community network has local services, you can point a link to them." msgstr "If your community network has local services, you can point a link to them." +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:57 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:86 +msgid "Iface" +msgstr "Iface" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:222 +msgid "In the reference state this node is on" +msgstr "In the reference state this node is on" + #: plugins/lime-plugin-rx/src/rxPage.js:98 -msgid "Interface" -msgstr "" +#~ msgid "Interface" +#~ msgstr "" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:72 +msgid "Interface:" +msgstr "Interface:" + +#: plugins/lime-plugin-rx/src/components/internetPathChart.tsx:165 +msgid "Internet" +msgstr "Internet" #: plugins/lime-plugin-metrics/src/components/internetStatus.js:10 -#: plugins/lime-plugin-rx/src/rxPage.js:149 msgid "Internet connection" msgstr "" +#: plugins/lime-plugin-rx/src/components/internetStatus.tsx:17 +msgid "Internet<0/>connection" +msgstr "Internet<0/>connection" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:16 +msgid "Invalid Nodes" +msgstr "Invalid Nodes" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:97 msgid "Invalidate" msgstr "Invalidate" @@ -522,6 +818,10 @@ msgstr "Invalidate" msgid "Invalidated" msgstr "Invalidated" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:73 +msgid "Ip" +msgstr "Ip" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:75 msgid "Is permanent" msgstr "Is permanent" @@ -539,15 +839,31 @@ msgstr "" msgid "It must start with https:// or http://" msgstr "It must start with https:// or http://" +#: plugins/lime-plugin-rx/src/components/footer.tsx:22 +msgid "Join <0>foro.librerouter.org" +msgstr "Join <0>foro.librerouter.org" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:72 msgid "Join the mesh" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:44 +msgid "Key" +msgstr "Key" + #: plugins/lime-plugin-align/src/alignPage.js:55 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:134 msgid "Last packet" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:60 +msgid "Last seen" +msgstr "Last seen" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:29 +msgid "Last update: 30 second ago" +msgstr "Last update: 30 second ago" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:120 msgid "Link Title" msgstr "Link Title" @@ -556,18 +872,34 @@ msgstr "Link Title" msgid "Link URL" msgstr "Link URL" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:181 +msgid "Link from <0>{0} to <1>{1}" +msgstr "Link from <0>{0} to <1>{1}" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:248 +msgid "Link {0} {1}" +msgstr "Link {0} {1}" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:106 msgid "Load last known Internet path" msgstr "" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:84 +msgid "Loading <0/>last internet path..." +msgstr "Loading <0/>last internet path..." + #: plugins/lime-plugin-rx/src/rxPage.js:128 -msgid "Loading node status..." -msgstr "" +#~ msgid "Loading node status..." +#~ msgstr "" #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:111 msgid "Local services link" msgstr "Local services link" +#: plugins/lime-plugin-locate/src/locateMenu.js:9 +msgid "Locate" +msgstr "Locate" + #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:81 msgid "Logging in" msgstr "" @@ -576,6 +908,14 @@ msgstr "" msgid "Login" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:94 +msgid "Macs ({0})" +msgstr "Macs ({0})" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:106 +msgid "Macs not found ({0})" +msgstr "Macs not found ({0})" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:57 msgid "Main Text" msgstr "Main Text" @@ -584,7 +924,7 @@ msgstr "Main Text" msgid "Manage Vouchers" msgstr "Manage Vouchers" -#: plugins/lime-plugin-locate/src/locateMenu.js:9 +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:128 msgid "Map" msgstr "" @@ -596,6 +936,30 @@ msgstr "Max. {length} characters" msgid "Measuring links" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx:9 +msgid "Mesh Map" +msgstr "Mesh Map" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx:9 +msgid "Mesh Wide Upgrade" +msgstr "Mesh Wide Upgrade" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:16 +msgid "Mesh upgrade confirmed successfully" +msgstr "Mesh upgrade confirmed successfully" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:20 +msgid "Mesh upgrade confirmed with some errors" +msgstr "Mesh upgrade confirmed with some errors" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx:20 +msgid "Mesh wide config" +msgstr "Mesh wide config" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:10 +msgid "Mesh wide upgrade started!" +msgstr "Mesh wide upgrade started!" + #: plugins/lime-plugin-metrics/src/metricsMenu.js:9 msgid "Metrics" msgstr "" @@ -613,17 +977,62 @@ msgid "More than 10 characters" msgstr "" #: plugins/lime-plugin-rx/src/rxPage.js:80 -msgid "Most Active" -msgstr "" +#~ msgid "Most Active" +#~ msgstr "" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:60 +msgid "Most active link" +msgstr "Most active link" #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:129 msgid "Must select a valid hostname" msgstr "Must select a valid hostname" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:73 +msgid "Name" +msgstr "Name" + +#: plugins/lime-plugin-rx/src/components/footer.tsx:19 +msgid "Need support?" +msgstr "Need support?" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:82 msgid "Network Name: {ssid}" msgstr "Network Name: {ssid}" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:126 +msgid "New Macs ({0})" +msgstr "New Macs ({0})" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:36 +msgid "New available version:<0/>{0}" +msgstr "New available version:<0/>{0}" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx:85 +msgid "New link" +msgstr "New link" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:351 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:184 +msgid "New reference state set!" +msgstr "New reference state set!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:64 +msgid "New version available!" +msgstr "New version available!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:33 +msgid "No new version available is found" +msgstr "No new version available is found" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx:11 +msgid "No new version available!" +msgstr "No new version available!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx:23 +msgid "No nodes present on the <0/>mesh wide upgrade state yet!" +msgstr "No nodes present on the <0/>mesh wide upgrade state yet!" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:35 msgid "No password" msgstr "" @@ -632,6 +1041,10 @@ msgstr "" msgid "No scan result" msgstr "No scan result" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:14 +msgid "No upgrade in progres" +msgstr "No upgrade in progres" + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:30 #: src/containers/RebootPage/RebootPage.js:45 msgid "No, cancel" @@ -642,12 +1055,24 @@ msgstr "" msgid "Node Configuration" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:74 +msgid "Node Info" +msgstr "Node Info" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:76 +msgid "Node Info Reference" +msgstr "Node Info Reference" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:20 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:43 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:48 msgid "Node Name" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:53 +msgid "Node is upgrading" +msgstr "Node is upgrading" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:99 msgid "Not Connected" @@ -699,6 +1124,10 @@ msgstr "Or if this node is already configured, you can skip this step" msgid "Or upgrade to latest release" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:94 +msgid "Other nodes will download the firmware from it" +msgstr "Other nodes will download the firmware from it" + #: plugins/lime-plugin-metrics/src/components/box/index.js:110 msgid "Packet loss" msgstr "" @@ -712,6 +1141,10 @@ msgstr "" msgid "Password: {password}" msgstr "Password: {password}" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:119 +msgid "Path to Internet" +msgstr "Path to Internet" + #: plugins/lime-plugin-pirania/src/components/voucherListItem.js:58 msgid "Permanent" msgstr "Permanent" @@ -759,14 +1192,37 @@ msgstr "" msgid "Re-enter the shared password" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:196 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:207 +msgid "Ready to start mesh wide upgrade" +msgstr "Ready to start mesh wide upgrade" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:67 +msgid "Ready to start mesh wide<0/>firmware upgrade" +msgstr "Ready to start mesh wide<0/>firmware upgrade" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:95 #: src/containers/RebootBanner/rebootBanner.js:17 msgid "Reboot" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:63 +msgid "Reboot node {0}" +msgstr "Reboot node {0}" + #: src/containers/RebootPage/RebootPage.js:25 msgid "Rebooting" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:35 +msgid "Reference State is not set" +msgstr "Reference State is not set" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:387 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:220 +msgid "Reference is not set or has errors" +msgstr "Reference is not set or has errors" + #: plugins/lime-plugin-ground-routing/src/groundRoutingPage.js:32 msgid "Reload" msgstr "" @@ -779,6 +1235,14 @@ msgstr "" msgid "Remote Support" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:67 +msgid "Remove this {0} from the reference state" +msgstr "Remove this {0} from the reference state" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:21 +msgid "Remove {nodeName} from the reference state" +msgstr "Remove {nodeName} from the reference state" + #: src/components/form/index.js:17 msgid "Required" msgstr "Required" @@ -799,6 +1263,15 @@ msgstr "" msgid "Reverting to previous version" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:151 +msgid "RxRate" +msgstr "RxRate" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:380 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:218 +msgid "Same status as in the reference state" +msgstr "Same status as in the reference state" + #: plugins/lime-plugin-node-admin/src/screens/hostname.js:84 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:49 #: plugins/lime-plugin-node-admin/src/screens/password.js:74 @@ -821,6 +1294,30 @@ msgstr "" msgid "Scanning for existing networks" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:20 +msgid "Schedule" +msgstr "Schedule" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:56 +msgid "Schedule a firmware upgrade for all nodes on the network" +msgstr "Schedule a firmware upgrade for all nodes on the network" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:220 +msgid "Schedule again" +msgstr "Schedule again" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:214 +msgid "Schedule upgrade" +msgstr "Schedule upgrade" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:46 +msgid "Schedule upgrade to all available nodes" +msgstr "Schedule upgrade to all available nodes" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:44 +msgid "Scheduling upgrade" +msgstr "Scheduling upgrade" + #: plugins/lime-plugin-pirania/src/screens/voucherList.js:60 msgid "Search by" msgstr "Search by" @@ -858,14 +1355,46 @@ msgstr "" msgid "Selected network to join" msgstr "Selected network to join" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:25 +msgid "Sending abort message to this node. The abort order will be propagated to all nodes." +msgstr "Sending abort message to this node. The abort order will be propagated to all nodes." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:62 +msgid "Sending confirmation" +msgstr "Sending confirmation" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:106 msgid "Set network" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:204 +msgid "Set reference state for this node" +msgstr "Set reference state for this node" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:58 +msgid "Set reference state for this {0}?" +msgstr "Set reference state for this {0}?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:363 +msgid "Set reference state for this<0/> {0}" +msgstr "Set reference state for this<0/> {0}" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:17 +msgid "Set reference state for {nodeName}" +msgstr "Set reference state for {nodeName}" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:18 +msgid "Set the reference state for this node." +msgstr "Set the reference state for this node." + #: plugins/lime-plugin-fbw/src/containers/Setting.js:80 msgid "Setting network" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:86 +msgid "Setting up main node" +msgstr "Setting up main node" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:82 msgid "Setting up new password" msgstr "" @@ -895,11 +1424,27 @@ msgstr "" msgid "Shared Password changed successfully" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:68 +msgid "Shared state error" +msgstr "Shared state error" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:156 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:165 msgid "Show Console" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:65 +msgid "Show nodes" +msgstr "Show nodes" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:57 +msgid "Show state" +msgstr "Show state" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:118 +msgid "Signal" +msgstr "Signal" + #: plugins/lime-plugin-align/src/alignPage.js:52 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:64 msgid "Signal lost" @@ -909,6 +1454,50 @@ msgstr "" msgid "Size" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:59 +msgid "Some nodes are not ready" +msgstr "Some nodes are not ready" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:209 +msgid "Some nodes are not ready for upgrade <0/>Check node details for more info" +msgstr "Some nodes are not ready for upgrade <0/>Check node details for more info" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:18 +msgid "Some nodes are still downloading the firmware<0/>check network page for more information" +msgstr "Some nodes are still downloading the firmware<0/>check network page for more information" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:85 +msgid "Some nodes don't upgraded properly" +msgstr "Some nodes don't upgraded properly" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:226 +msgid "Some nodes have errors" +msgstr "Some nodes have errors" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx:36 +msgid "Some nodes have errors:" +msgstr "Some nodes have errors:" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:91 +msgid "Source IP" +msgstr "Source IP" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:197 +msgid "Start" +msgstr "Start" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:189 +msgid "Start mesh upgrade" +msgstr "Start mesh upgrade" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:74 +msgid "Start mesh wide firmware upgrade again" +msgstr "Start mesh wide firmware upgrade again" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:59 +msgid "Start mesh wide upgrade" +msgstr "Start mesh wide upgrade" + #: plugins/lime-plugin-rx/src/rxMenu.js:9 msgid "Status" msgstr "" @@ -917,7 +1506,12 @@ msgstr "" msgid "Status: {0}" msgstr "Status: {0}" -#: plugins/lime-plugin-rx/src/rxPage.js:42 +#: src/components/Modal/Modal.tsx:60 +#: src/components/Modal/Modal.tsx:126 +msgid "Success" +msgstr "Success" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:78 msgid "System" msgstr "" @@ -933,6 +1527,14 @@ msgstr "The Community Portal enables a welcome screen to be displayed in the web msgid "The are not mesh interfaces available" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:88 +msgid "The become main node process is starting on this node" +msgstr "The become main node process is starting on this node" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:135 +msgid "The difference between chains is too big" +msgstr "The difference between chains is too big" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:113 msgid "The download failed" msgstr "" @@ -941,6 +1543,22 @@ msgstr "" msgid "The firmware is being upgraded..." msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:52 +msgid "The firmware seems to be installed successfully. Confirm that the node is working properly or will be downgraded to the previous version" +msgstr "The firmware seems to be installed successfully. Confirm that the node is working properly or will be downgraded to the previous version" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:20 +msgid "The following nodes are not located or have not reference state. Please, set their location to see them on the map:" +msgstr "The following nodes are not located or have not reference state. Please, set their location to see them on the map:" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:72 +msgid "The following shared states packages have errors. Are they installed or properly initialized?" +msgstr "The following shared states packages have errors. Are they installed or properly initialized?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:39 +msgid "The following shared states packages have not data set" +msgstr "The following shared states packages have not data set" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:115 msgid "The hotspot couldn’t be found, please review the instructions above." msgstr "The hotspot couldn’t be found, please review the instructions above." @@ -949,6 +1567,10 @@ msgstr "The hotspot couldn’t be found, please review the instructions above." msgid "The name should have at least 3 characters" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:77 +msgid "The node is down" +msgstr "The node is down" + #: plugins/lime-plugin-node-admin/src/screens/password.js:60 msgid "The password should have at least 8 characters" msgstr "" @@ -974,6 +1596,14 @@ msgstr "" msgid "The shared password has been chosen by the community when the network was created. You can ask other community members for it." msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:123 +msgid "The signal is X below the reference state" +msgstr "The signal is X below the reference state" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:44 +msgid "The upgrade is scheduled" +msgstr "The upgrade is scheduled" + #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:9 msgid "The upgrade should be done" msgstr "" @@ -994,6 +1624,10 @@ msgstr "" msgid "These are the nodes associated on this radio" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:384 +msgid "This Link is not registered on the reference state" +msgstr "This Link is not registered on the reference state" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:35 msgid "This device does not support secure rollback to previous version if something goes wrong" msgstr "" @@ -1006,14 +1640,87 @@ msgstr "" msgid "This field is required" msgstr "This field is required" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:92 +msgid "This is a main node" +msgstr "This is a main node" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:389 +msgid "This link has errors" +msgstr "This link has errors" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:169 +msgid "This link seems down" +msgstr "This link seems down" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:73 +msgid "This link seems down, remove them from the reference state?" +msgstr "This link seems down, remove them from the reference state?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:111 +msgid "This macs are not on the actual state" +msgstr "This macs are not on the actual state" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:129 +msgid "This macs are not on the reference state" +msgstr "This macs are not on the reference state" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:73 +msgid "This node aborted" +msgstr "This node aborted" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:86 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:21 +msgid "This node aborted successfully" +msgstr "This node aborted successfully" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:41 +msgid "This node es ready for upgrade" +msgstr "This node es ready for upgrade" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:20 +msgid "This node has an error" +msgstr "This node has an error" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:69 +msgid "This node has an error!" +msgstr "This node has an error!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:36 +msgid "This node is downloading a new firmware" +msgstr "This node is downloading a new firmware" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:225 +msgid "This node is not registered on the reference state" +msgstr "This node is not registered on the reference state" + #: plugins/lime-plugin-metrics/src/components/showPathButton.js:16 msgid "This node is the gateway" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:36 +msgid "This node seems down" +msgstr "This node seems down" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:24 +msgid "This node seems down, remove them from the reference state?" +msgstr "This node seems down, remove them from the reference state?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:21 +msgid "This node version<0/>{0}" +msgstr "This node version<0/>{0}" + #: plugins/lime-plugin-align/src/alignPage.js:119 msgid "This radio is not associated with other nodes" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:63 +msgid "This will set the reference state of this link:" +msgstr "This will set the reference state of this link:" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:104 +msgid "This will the abort current upgrade process on all nodes. Are you sure you want to proceed?" +msgstr "This will the abort current upgrade process on all nodes. Are you sure you want to proceed?" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:120 msgid "This your last working path to the Internet" msgstr "" @@ -1031,17 +1738,37 @@ msgid "To enable remote access an internet connection is needed" msgstr "To enable remote access an internet connection is needed" #: plugins/lime-plugin-rx/src/rxPage.js:103 -msgid "Traffic" -msgstr "" +#~ msgid "Traffic" +#~ msgstr "" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:78 +msgid "Traffic:" +msgstr "Traffic:" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:248 +msgid "Try last step again" +msgstr "Try last step again" #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:12 msgid "Try reloading the app" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:148 +msgid "TxRate" +msgstr "TxRate" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:100 msgid "Unknown error" msgstr "Unknown error" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:226 +msgid "Unknown link type" +msgstr "Unknown link type" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:16 +msgid "Updating shared state {0}" +msgstr "Updating shared state {0}" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:229 msgid "Upgrade" msgstr "" @@ -1050,6 +1777,22 @@ msgstr "" msgid "Upgrade Now" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:74 +msgid "Upgrade all network nodes at once. This proces will take a while and will require user interaction." +msgstr "Upgrade all network nodes at once. This proces will take a while and will require user interaction." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:16 +msgid "Upgrade is scheduled!" +msgstr "Upgrade is scheduled!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:17 +msgid "Upgrade scheduled" +msgstr "Upgrade scheduled" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:60 +msgid "Upgrade successful" +msgstr "Upgrade successful" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:85 msgid "Upgrade to lastest firmware version" msgstr "" @@ -1059,11 +1802,17 @@ msgstr "" msgid "Upgrade to {versionName}" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:12 +msgid "Upgraded!<0/>Awaiting confirmation" +msgstr "Upgraded!<0/>Awaiting confirmation" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:181 msgid "Upload firmware image from your device" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:45 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:72 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:76 +#: plugins/lime-plugin-rx/src/sections/system.tsx:45 msgid "Uptime" msgstr "" @@ -1071,10 +1820,18 @@ msgstr "" msgid "Use vouchers for access" msgstr "Use vouchers for access" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:49 +msgid "Value" +msgstr "Value" + #: plugins/lime-plugin-changeNode/src/changeNodePage.js:75 msgid "Visit" msgstr "" +#: plugins/lime-plugin-rx/src/components/footer.tsx:33 +msgid "Visit <0>docs.altermundi.net" +msgstr "Visit <0>docs.altermundi.net" + #: plugins/lime-plugin-changeNode/src/changeNodeMenu.js:9 #: plugins/lime-plugin-changeNode/src/changeNodePage.js:50 msgid "Visit a neighboring node" @@ -1100,6 +1857,10 @@ msgstr "Voucher list" msgid "Vouchers can be used to limit access through the Community Portal to those who have an authorization code" msgstr "Vouchers can be used to limit access through the Community Portal to those who have an authorization code" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:37 +msgid "Wait until the download is finished!" +msgstr "Wait until the download is finished!" + #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:54 msgid "Welcome to LimeApp" msgstr "Welcome to LimeApp" @@ -1112,12 +1873,24 @@ msgstr "Wellcome Screen" msgid "When reloading the app you will be asked to confirm the upgrade, otherwise it will be reverted" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:78 +msgid "Wifi Links" +msgstr "Wifi Links" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:80 +msgid "Wifi Links Reference" +msgstr "Wifi Links Reference" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:34 #: plugins/lime-plugin-node-admin/src/screens/password.js:45 #: plugins/lime-plugin-node-admin/src/screens/password.js:105 msgid "Wifi Password" msgstr "" +#: plugins/lime-plugin-rx/src/sections/wired.tsx:62 +msgid "Wired connections" +msgstr "Wired connections" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:121 msgid "With radio {fromRadio} alignin with" msgstr "" @@ -1167,31 +1940,34 @@ msgstr "" msgid "You should try to connect to the network {wifiSsid}." msgstr "" +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:113 +msgid "Your Alignment" +msgstr "Your Alignment" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:74 msgid "Your node has no internet connection" msgstr "Your node has no internet connection" -#: plugins/lime-plugin-locate/src/locateMap.tsx:207 #: plugins/lime-plugin-locate/src/locatePage.tsx:225 msgid "cancel" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:193 #: plugins/lime-plugin-locate/src/locatePage.tsx:211 msgid "confirm location" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:209 #: plugins/lime-plugin-locate/src/locatePage.tsx:227 msgid "edit location" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:199 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:54 +msgid "for the following nodes: {nodes}" +msgstr "for the following nodes: {nodes}" + #: plugins/lime-plugin-locate/src/locatePage.tsx:217 msgid "hide community" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:212 #: plugins/lime-plugin-locate/src/locatePage.tsx:230 msgid "locate my node" msgstr "" @@ -1200,7 +1976,6 @@ msgstr "" msgid "more than a minute ago" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:201 #: plugins/lime-plugin-locate/src/locatePage.tsx:219 msgid "show community" msgstr "" @@ -1217,23 +1992,33 @@ msgstr "" msgid "{0, plural, =0 {No one has joined yet.} one {One person has joined.} other {# people have joined.}}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:20 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:66 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:70 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:74 +msgid "{0}" +msgstr "{0}" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:22 msgid "{days, plural, one {# day} other {# days}}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:23 +#: plugins/lime-plugin-rx/src/sections/system.tsx:25 msgid "{hours, plural, one {# hour} other {# hours}}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:26 +#: plugins/lime-plugin-rx/src/sections/system.tsx:28 msgid "{mins, plural, one {# minute} other {# minutes}}" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:18 +msgid "{nodesToBeUpgraded} of {totalNodes} will be upgraded" +msgstr "{nodesToBeUpgraded} of {totalNodes} will be upgraded" + #: plugins/lime-plugin-align/src/components/secondsAgo.js:23 msgid "{secondsAmount} seconds ago" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:29 +#: plugins/lime-plugin-rx/src/sections/system.tsx:31 msgid "{secs, plural, one {# second} other {# seconds}}" msgstr "" diff --git a/i18n/es/messages.po b/i18n/es/messages.po index 365c9563d..7753c9ab1 100644 --- a/i18n/es/messages.po +++ b/i18n/es/messages.po @@ -1,25 +1,50 @@ msgid "" msgstr "" -"POT-Creation-Date: 2021-11-10 13:08-0300\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.2.1\n" -"Language: es\n" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-10 13:08-0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" "Plural-Forms: \n" +"X-Generator: Poedit 3.0.1\n" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:46 +msgid "(Main Node) {descriptionMsg}" +msgstr "(Nodo principal) {descriptionMsg}" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx:40 +msgid "(new)" +msgstr "(nuevo)" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:26 +msgid "10 of 12 node are ready to update" +msgstr "10 de 12 nodos están listos para ser actualizados." #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:67 msgid "A new firmware version has been released" -msgstr "Nueva versión del firmware disponible" +msgstr "Nueva versión del sistema (firmware) disponible." #: src/containers/RebootBanner/rebootBanner.js:15 msgid "A reboot is needed to apply changes" -msgstr "Reinicia el nodo para aplicar cambios" +msgstr "Reinicie el nodo para aplicar cambios." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:109 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:256 +msgid "Abort" +msgstr "Cancelar" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:102 +msgid "Abort current mesh wide upgrade?" +msgstr "Interrumpir actualización de la red completa?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:23 +msgid "Aborting" +msgstr "Cancelando" #: plugins/lime-plugin-pirania/src/piraniaMenu.js:9 msgid "Access Vouchers" @@ -31,17 +56,17 @@ msgstr "Cupones de Acceso" #: plugins/lime-plugin-pirania/src/screens/voucher.js:74 msgid "Activation date: {0}" -msgstr "Plazo para activación: {0}" +msgstr "Fecha de activación: {0}" #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:115 msgid "Activation deadline" -msgstr "Plazo para activación" +msgstr "Plazo de activación" #: plugins/lime-plugin-pirania/src/components/voucherListItem.js:79 #: plugins/lime-plugin-pirania/src/screens/postCreate.js:53 #: plugins/lime-plugin-pirania/src/screens/voucher.js:82 msgid "Activation deadline: {0}" -msgstr "Plazo para activación: {0}" +msgstr "Plazo de activación: {0}" #: plugins/lime-plugin-pirania/src/components/voucherListItem.js:25 #: plugins/lime-plugin-pirania/src/screens/voucher.js:14 @@ -49,6 +74,23 @@ msgstr "Plazo para activación: {0}" msgid "Active" msgstr "Activo" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:80 +msgid "Add" +msgstr "Añadir" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:101 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:78 +msgid "Add new section" +msgstr "Añadir nueva sección" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:92 +msgid "Added section {0} - {1}" +msgstr "Sección añadida {0} - {1}" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:46 +msgid "After a time the upgrade will be performed" +msgstr "La actualización iniciará en unos instantes. Este proceso demorará algunos miniutos, espere." + #: plugins/lime-plugin-align/src/alignMenu.js:9 msgid "Align" msgstr "Alineación" @@ -57,13 +99,41 @@ msgstr "Alineación" msgid "All Vouchers" msgstr "Todos los cupones" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:54 +msgid "All nodes are ready" +msgstr "Todos los nodos están listos." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:80 +msgid "All nodes are upgraded successfully" +msgstr "Todos los nodos fueron actualizados con éxito!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:232 +msgid "All nodes scheduled successful" +msgstr "Todos los nodos fueron programados con éxito." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:87 +msgid "Are you sure you want to confirm the upgrade? <0/>Check node list to see the network status" +msgstr "¿Con seguridad desea confirmar la actualización? <0/>Verifique la lista de nodos para ver el estado de la red." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:66 +msgid "Are you sure you want to reboot this node? This action will disconnect the node from the network for a few minutes. <0/>Add shared password or let it empty if no password is set." +msgstr "¿Con seguridad desea reiniciar este nodo? Esta acción desconectará el nodo de la red durante unos minutos. <0/>Agregue una contraseña compartida o deje el campo en blanco si no quiere establecer ninguna contraseña." + #: src/containers/RebootPage/RebootPage.js:39 msgid "Are you sure you want to reboot?" -msgstr "Estás seguro/a de que quieres reiniciar?" +msgstr "Con seguridad quiere reiniciar?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:61 +msgid "Are you sure you want to start mesh wide upgrade? <0/>Check node list to see the network status" +msgstr "¿Con seguridad desea iniciar la actualización de toda la red? <0/>Verifique la lista de nodos para ver el estado de la red." + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:24 +msgid "Are you sure you want to {title} the <0>{prop} property?" +msgstr "¿Con seguridad quiere {título} la propiedad <0> {prop} ?" #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:24 msgid "Are you sure?" -msgstr "Estás seguro/a?" +msgstr "Lo confirma?" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:71 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:105 @@ -72,11 +142,11 @@ msgstr "Pedir soporte remoto" #: src/containers/SharedPasswordForm/sharedPasswordForm.js:47 msgid "At least one alphanumeric character" -msgstr "Al menos una letra" +msgstr "Al menos una letra o número." #: src/containers/SharedPasswordForm/sharedPasswordForm.js:44 msgid "At least one number" -msgstr "Al menos un número" +msgstr "Al menos un número." #: plugins/lime-plugin-pirania/src/screens/voucher.js:50 msgid "Author node: {author_node}" @@ -88,18 +158,46 @@ msgstr "Nodo autor: {author_node}" msgid "Available" msgstr "Disponible" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:54 +msgid "Await until it reboots" +msgstr "Espere mientra se reinicia." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:50 +msgid "Awaiting confirmation" +msgstr "Esperando confirmación." + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:86 +msgid "Babel Links" +msgstr "Enlaces de Babel" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:88 +msgid "Babel Links Reference" +msgstr "Enlaces de referencia en Babel" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:22 msgid "Back" msgstr "Volver" #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:100 msgid "Background Color" -msgstr "Color de Fondo" +msgstr "Color de fondo" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:82 +msgid "Batman Links" +msgstr "Enlaces en Batman" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:84 +msgid "Batman Links Reference" +msgstr "Enlaces de referencia en Batman" #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:41 msgid "Best signal" msgstr "Mejor señal" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:65 +msgid "Board" +msgstr "Equipo (Hardware)" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:96 msgid "Calculating network path" msgstr "Cargando el recorrido en la red" @@ -107,6 +205,8 @@ msgstr "Cargando el recorrido en la red" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:83 #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:150 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:14 +#: src/components/Modal/Modal.tsx:62 +#: src/components/Modal/Modal.tsx:128 #: src/components/banner/index.js:20 msgid "Cancel" msgstr "Cancelar" @@ -117,11 +217,11 @@ msgstr "Cancelando" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:123 msgid "Cannot connect to the remote support server" -msgstr "No hay conexión con el servidor de soporte remoto" +msgstr "No hay conexión con el servidor de soporte remoto." #: plugins/lime-plugin-locate/src/locatePage.tsx:153 msgid "Cannot load map, check your internet connection" -msgstr "El mapa no puede cargarse, verifica la conexión a internet" +msgstr "El mapa no puede cargarse, verifique la conexión a internet." #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:123 msgid "Cannot use Radio 0, it's being used for mesh links" @@ -131,6 +231,10 @@ msgstr "La Radio 0 no se puede utilizar por que está siendo utilizada para enla msgid "Cellphone Instructions" msgstr "Instrucciones para el celular" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:132 +msgid "Chains" +msgstr "Recorrido" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:76 msgid "Change" msgstr "Cambiar" @@ -140,39 +244,52 @@ msgid "Change Shared Password" msgstr "Cambiar Contraseña Compartida" #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:123 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:143 msgid "Channel" msgstr "Canal" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:22 +msgid "Check if network is working properly and confirm the upgrade<0/>If not confirmed, the upgrade will be rolled back after a while" +msgstr "Verifique si la red funciona correctamente y confirme la actualización. <0/>Si no se confirma, la actualización se revertirá luego de un tiempo." + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:91 +msgid "Check<0/>Alignment" +msgstr "Chequear<0/>Alineación" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:100 msgid "Checking connection" msgstr "Comprobando conexión" #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanList.js:96 msgid "Choose a mesh node to join it's network:" -msgstr "Elije un nodo mesh para unirse a su red" +msgstr "Elija un nodo para unirse a la misma red:" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:128 #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:84 msgid "Choose a name for this node" -msgstr "Elije el nombre para el nodo" +msgstr "Elija el nombre para el nodo" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:87 msgid "Choose a name for your network" -msgstr "Elije el nombre para la red" +msgstr "Elija el nombre para la red" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:97 #: plugins/lime-plugin-network-admin/src/netAdminPage.js:43 msgid "Choose a shared password for network administration" -msgstr "Elige una contraseña compartida para la administración de la red" +msgstr "Elija una contraseña compartida para la administración de la red" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:173 msgid "Click at Close Session to end the remote support session. No one will be able to access your node with this token again" -msgstr "Haz click en Cerrar Sesión para finalizar la sesión de soporte remoto. Nadie podrá volver a acceder tu nodo con este token" +msgstr "Haz click en Cerrar Sesión para finalizar la sesión de soporte remoto. Nadie podrá volver a acceder tu nodo con este mismo token de seguridad." #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:159 msgid "Click at Show Console to follow the remote support session." msgstr "Haz click en Ver Consola para seguir la sesión de soporte remoto." +#: src/components/Modal/Modal.tsx:205 +msgid "Close" +msgstr "Cerrar" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:170 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:183 msgid "Close Session" @@ -180,21 +297,21 @@ msgstr "Cerrar Sesión" #: plugins/lime-plugin-firmware/src/upgradeCountdown.js:21 msgid "Cofirm upgrade before {_counter} seconds or it will be reverted" -msgstr "Confirmá la actualización en los próximos {_counter} segundos o será revertida" +msgstr "Confirme la actualización en los próximos {_counter} segundos o el proceso se revertirá." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:76 msgid "Community Logo" -msgstr "Logo de la Comunidad" +msgstr "Logo de la comunidad" #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigItem.tsx:27 #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:113 msgid "Community Portal" -msgstr "Portal Comunitario" +msgstr "Portal comunitario" #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:49 #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:68 msgid "Community Roaming AP" -msgstr "AP Comunitario" +msgstr "Acceso (roaming) comunitario" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:92 msgid "Community name" @@ -205,12 +322,45 @@ msgid "Configure your new community network" msgstr "Configure su nueva red mesh" #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:11 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:241 msgid "Confirm" msgstr "Confirmar" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:82 +msgid "Confirm mesh wide upgrade for all nodes on the network" +msgstr "Confirmar la actualización de todos los nodos de la red." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:240 +msgid "Confirm upgrade on all nodes" +msgstr "Confirmar actualización para todos los nodos." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:18 +msgid "Confirmation pending" +msgstr "Confirmación pendiente" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:19 +msgid "Confirmed" +msgstr "Confirmado" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:19 +msgid "Confirmed with some errors" +msgstr "Confirmado con errores" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:15 +msgid "Confirmed!" +msgstr "Confirmado!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:63 +msgid "Confirming all upgraded nodes" +msgstr "Confirmando todos los nodos actualizados." + #: plugins/lime-plugin-fbw/src/containers/Setting.js:127 msgid "Congratulations" -msgstr "Felicitaciones" +msgstr "Felicitaciones!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:62 +msgid "Congratulations, this node was upgraded and confirmed successfully" +msgstr "Felicitaciones! Este nodo fue actualizado y confirmado exitosamente." #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:37 @@ -235,6 +385,11 @@ msgstr "Conexión al celular" msgid "Connection to the internet" msgstr "Conexión a internet" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:34 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:90 +msgid "Continue" +msgstr "Continuar" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:134 #: plugins/lime-plugin-pirania/src/screens/voucherList.js:122 msgid "Create" @@ -242,11 +397,11 @@ msgstr "Crear" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:116 msgid "Create Session" -msgstr "Crear Sesión" +msgstr "Crear sesión" #: plugins/lime-plugin-pirania/src/screens/createVoucher.js:53 msgid "Create Voucher" -msgstr "Crear Cupón" +msgstr "Crear cupón" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:58 #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:145 @@ -273,6 +428,33 @@ msgstr "Fecha de creación: {0}" msgid "Currently your node has version:" msgstr "Actualmente tu nodo tiene la versión:" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:44 +msgid "Delete" +msgstr "Eliminar" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:43 +msgid "Delete property" +msgstr "Eliminar propiedad" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:206 +msgid "Delete this this node from reference state" +msgstr "Eliminar este nodo del estado de referencia" + +#~ msgid "Delete this {0} link<0/>from reference state" +#~ msgstr "Eliminar este {0} enlace<0/>del estado de referencia" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:372 +msgid "Delete this {0}<0/>from reference state" +msgstr "Eliminar este {0}<0/> del estado de referencia" + +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:99 +msgid "Deleted {keyString}" +msgstr "Eliminado {keyString}" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:64 +msgid "Deleted {name} - {0}" +msgstr "Eliminado {name} - {0}" + #: plugins/lime-plugin-pirania/src/screens/editVoucher.js:28 msgid "Description" msgstr "Descripción" @@ -282,10 +464,15 @@ msgstr "Descripción" msgid "Description: {name}" msgstr "Descripción: {name}" -#: plugins/lime-plugin-rx/src/rxPage.js:51 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:89 +#: plugins/lime-plugin-rx/src/sections/system.tsx:48 msgid "Device" msgstr "Equipo" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:125 +msgid "Diagnose" +msgstr "Diagnóstico" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:54 #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:72 #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigItem.tsx:20 @@ -298,14 +485,31 @@ msgstr "Deshabilitado" msgid "Don't show this message again" msgstr "No volver a mostrar a este mensaje" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:53 +msgid "Done" +msgstr "Hecho" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:96 msgid "Download" msgstr "Descargar" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:183 +msgid "Download remote firmware<0/>to start mesh upgrade" +msgstr "Descargue el archivo del sistema (firmware)<0/>para iniciar la actualización de toda la red." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:50 +msgid "Downloaded version<0/>{0}" +msgstr "Versión descargada<0/>{0}" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:103 +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:35 msgid "Downloading" msgstr "Descargando" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:15 +msgid "Downloading new firmware" +msgstr "Descargando nuevo sistema (firmware)" + #: plugins/lime-plugin-pirania/src/screens/postCreate.js:18 #: plugins/lime-plugin-pirania/src/screens/voucher.js:59 msgid "Duration: is permanent" @@ -316,29 +520,42 @@ msgstr "Duración: es permanente" msgid "Duration: {days, plural, one {# day} other {# days}}" msgstr "Duración: {days, plural, one {# día} other {# días}}" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:51 #: plugins/lime-plugin-pirania/src/screens/voucher.js:90 msgid "Edit" msgstr "Editar" #: plugins/lime-plugin-pirania/src/screens/editVoucher.js:84 msgid "Edit Voucher" -msgstr "Editar Cupón" +msgstr "Editar cupón" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:50 +msgid "Edit property" +msgstr "Editar propiedad" #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:50 msgid "Edit wellcome screen" msgstr "Editar pantalla de bienvenida" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:123 +msgid "Edited {keyString}" +msgstr "Editado {keyString}" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:47 +msgid "Edited {name} - {0}" +msgstr "Editado {name} - {0}" + #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:25 msgid "Enable Community Roaming AP" -msgstr "Activar AP Comunitario" +msgstr "Activar AP (punto de acceso roaming) comunitario" #: plugins/lime-plugin-node-admin/src/screens/password.js:39 msgid "Enable Password" -msgstr "Activar Contraseña" +msgstr "Activar contraseña" #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:45 msgid "Enable Portal in Community AP" -msgstr "Habilita el Portal en el AP Comunitario" +msgstr "Habilitar el portal en el AP (punto de acceso) comunitario" #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:52 #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:72 @@ -361,46 +578,83 @@ msgstr "Cifrado: {encryptionMethod}" msgid "Error" msgstr "Error" +#: src/components/toast/toasts.tsx:13 +msgid "Error connecting with {nodeInfo}, is node up?" +msgstr "Error al conectar con {nodeInfo}, ¿el nodo está activo?" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:61 msgid "Error destination network is not configured yet" -msgstr "Error, la red de destino no está configurada aún" +msgstr "Error, la red de destino no está configurada aún." #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:67 msgid "Error downloading lime assets" -msgstr "Error al descargar lime assets" +msgstr "Error al descargar lime assets." #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:57 msgid "Error downloading lime community" -msgstr "Error al descargar lime community" +msgstr "Error al descargar lime community." #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanList.js:158 msgid "Error getting scan results" -msgstr "Error recibiendo los resultados del escaneo" +msgstr "Error recibiendo los resultados del escaneo." + +#: plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx:41 +msgid "Error loading leaflet" +msgstr "Error cargando leaflet." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:85 +msgid "Error performing reboot: {error}" +msgstr "Error al reiniciar: {error}" #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:40 msgid "Error reaching hostname!" -msgstr "No se pudo obtener el nombre de host!" +msgstr "No se pudo obtener el nombre del host!" #: plugins/lime-plugin-align/src/alignPage.js:102 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:97 msgid "Error retrieving associated list" -msgstr "Error recuperando la lista de nodos associados" +msgstr "Error recuperando la lista de nodos asociados." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:43 +msgid "Error retrieving the status, is this node outdated?" +msgstr "Error al recuperar el estado. ¿Este nodo está desactualizado?" + +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:101 +msgid "Error retrieving<0/>last internet path" +msgstr "Error al recuperar<0/>última ruta de Internet." #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanList.js:155 msgid "Error scanning networks" -msgstr "Error buscando redes" +msgstr "Error buscando redes." #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:126 msgid "Error setting network" -msgstr "Error configurando red" +msgstr "Error configurando red." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:355 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:189 +msgid "Error setting new reference state!" +msgstr "¡Error al establecer un nuevo estado de referencia!" #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanPage.tsx:83 msgid "Error stopping scan" -msgstr "Error deteniendo la búsqueda" +msgstr "Error deteniendo la búsqueda." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx:12 +msgid "Error!" +msgstr "Error!" #: plugins/lime-plugin-node-admin/src/layouts/configPageLayout.tsx:55 msgid "Error: Not Saved" -msgstr "Error: No se guardó" +msgstr "Error: No se guardó." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:35 +msgid "Errors found getting mesh info!" +msgstr "¡Se encontraron errores al obtener información de de la red (mesh info)!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:32 +msgid "Everything is up to date!" +msgstr "Todo quedó actualizado!" #: plugins/lime-plugin-pirania/src/screens/voucher.js:66 msgid "Expiration date: {0}" @@ -422,7 +676,7 @@ msgstr "Expira en {0}" #: plugins/lime-plugin-align/src/alignPage.js:37 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:80 -#: plugins/lime-plugin-rx/src/rxPage.js:93 +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:67 msgid "Fetching name" msgstr "Consiguiendo nombre" @@ -435,9 +689,22 @@ msgid "Filter by" msgstr "Filtrar por" #: plugins/lime-plugin-firmware/src/firmwareMenu.js:9 -#: plugins/lime-plugin-rx/src/rxPage.js:58 +#: plugins/lime-plugin-rx/src/sections/system.tsx:49 msgid "Firmware" -msgstr "Firmware" +msgstr "Sistema del nodo" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:40 +msgid "Firmware download and verified" +msgstr "Archivo de sistema (firmware) descargado y verificado." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:16 +msgid "Firmware downloaded" +msgstr "Archivo de sistema (firmware) descargado." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:80 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:69 +msgid "Firmware version" +msgstr "Versión de sistema (firmware)." #: plugins/lime-plugin-metrics/src/metricsPage.tsx:151 msgid "From" @@ -449,15 +716,15 @@ msgstr "Medir todo el recorrido" #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:67 msgid "Get an additional cell phone to the one you are currently using that has a mobile data connection" -msgstr "Consigue un teléfono adicional al que estás usando que tenga conexión a internet por datos móviles" +msgstr "Consiga otro teléfono que tenga conexión a internet por datos móviles." #: src/containers/Menu/menu.js:48 msgid "Go to Community View" -msgstr "Ir a la página de comunidad" +msgstr "Ir a la página de la comunidad" #: src/containers/Menu/menu.js:51 msgid "Go to Node View" -msgstr "Ir a la página de nodo" +msgstr "Ir a la página del nodo" #: plugins/lime-plugin-firmware/src/upgradeCountdown.js:27 msgid "Go!" @@ -473,7 +740,7 @@ msgstr "Configuración de Ground Routing" #: plugins/lime-plugin-remotesupport/src/consoleView.js:17 msgid "Hide Console" -msgstr "Esconder Consola" +msgstr "Esconder consola" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:133 msgid "Host name" @@ -481,37 +748,61 @@ msgstr "Nombre del nodo" #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:67 msgid "I don't know the shared password" -msgstr "No sé la contraseña compartida" +msgstr "No sé la contraseña compartida." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:85 +msgid "IPv4" +msgstr "IPv4" -#: plugins/lime-plugin-rx/src/rxPage.js:181 -msgid "IP Addresses" -msgstr "Direcciones IP" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:86 +msgid "IPv6" +msgstr "IPv6" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:73 msgid "If network has been already created, look it up to join" -msgstr "Si la red ya fue creada, búscala para unirte a ella" +msgstr "Si la red ya fue creada, búscala para unirte a ella." #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:60 msgid "If this is your network first node, you can create a new network" -msgstr "Si este es el primer nodo de tu red, puedes crear una red nueva" +msgstr "Si este es el primer nodo de tu red, puedes crear una red nueva." #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:18 msgid "If you invalidate this voucher no one will be able to use it anymore. This cannot be reverted." -msgstr "Si invalidas este cupón, el mismo no podrá volver a ser utilizado. Esto no se puede revertir." +msgstr "Si invalidas este cupón, el mismo no podrá volver a ser utilizado. Esta acción no se puede revertir." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:114 msgid "If your community network has local services, you can point a link to them." msgstr "Si tu red comunitaria tiene servicios locales, puedes indicar un enlace para acceder a ellos." -#: plugins/lime-plugin-rx/src/rxPage.js:98 -msgid "Interface" -msgstr "Interfaz" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:57 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:86 +msgid "Iface" +msgstr "Interface" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:222 +msgid "In the reference state this node is on" +msgstr "En el estado de referencia este nodo está encendido." + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:72 +msgid "Interface:" +msgstr "Interface:" + +#: plugins/lime-plugin-rx/src/components/internetPathChart.tsx:165 +msgid "Internet" +msgstr "Internet" #: plugins/lime-plugin-metrics/src/components/internetStatus.js:10 -#: plugins/lime-plugin-rx/src/rxPage.js:149 msgid "Internet connection" msgstr "Conexión a Internet" +#: plugins/lime-plugin-rx/src/components/internetStatus.tsx:17 +msgid "Internet<0/>connection" +msgstr "Conexión a<0/>internet" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:16 +msgid "Invalid Nodes" +msgstr "Nodos no válidos" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:97 msgid "Invalidate" msgstr "Invalidar" @@ -522,32 +813,52 @@ msgstr "Invalidar" msgid "Invalidated" msgstr "Invalidado" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:73 +msgid "Ip" +msgstr "IP" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:75 msgid "Is permanent" msgstr "Es permanente" #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:82 msgid "It is disabled by default in {communityName}" -msgstr "Está deshabilitado por defecto en {communityName}" +msgstr "Está deshabilitado en forma predeterminada en {communityName}." #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:87 msgid "It is enabled by default in {communityName}" -msgstr "Está habilitado por defecto en {communityName}" +msgstr "Está habilitado en forma predeterminada en {communityName}." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:138 #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:150 msgid "It must start with https:// or http://" msgstr "Debe empezar con https:// o http://" +#: plugins/lime-plugin-rx/src/components/footer.tsx:22 +msgid "Join <0>foro.librerouter.org" +msgstr "Ir a <0>foro.librerouter.org" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:72 msgid "Join the mesh" msgstr "Unirse a la red" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:44 +msgid "Key" +msgstr "Llave" + #: plugins/lime-plugin-align/src/alignPage.js:55 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:134 msgid "Last packet" msgstr "Último paquete" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:60 +msgid "Last seen" +msgstr "Visto por última vez" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:29 +msgid "Last update: 30 second ago" +msgstr "Última actualización: hace 30 segundos" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:120 msgid "Link Title" msgstr "Título del enlace" @@ -556,35 +867,61 @@ msgstr "Título del enlace" msgid "Link URL" msgstr "URL del enlace" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:181 +msgid "Link from <0>{0} to <1>{1}" +msgstr "Enlace desde <0>{0} hasta <1>{1}" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:248 +msgid "Link {0} {1}" +msgstr "Enlace {0} {1}" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:106 msgid "Load last known Internet path" -msgstr "Cargando última ruta a Internet conocida" +msgstr "Cargando la última ruta a Internet conocida..." -#: plugins/lime-plugin-rx/src/rxPage.js:128 -msgid "Loading node status..." -msgstr "Cargando el estado del nodo..." +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:84 +msgid "Loading <0/>last internet path..." +msgstr "Cargando <0/> la última ruta a internet conocida..." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:111 msgid "Local services link" msgstr "Enlace a servicios locales" +#: plugins/lime-plugin-locate/src/locateMenu.js:9 +msgid "Locate" +msgstr "Localizar" + #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:81 msgid "Logging in" -msgstr "Iniciando Sesión" +msgstr "Iniciando sesión" #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:63 msgid "Login" msgstr "Ingresar" +#~ msgid "Macs" +#~ msgstr "MACs" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:94 +msgid "Macs ({0})" +msgstr "MACs ({0})" + +#~ msgid "Macs not found" +#~ msgstr "MACs no encontrados" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:106 +msgid "Macs not found ({0})" +msgstr "Macs no encontradas ({0})" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:57 msgid "Main Text" msgstr "Texto principal" #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:75 msgid "Manage Vouchers" -msgstr "Administrar Cupones" +msgstr "Administrar cupones" -#: plugins/lime-plugin-locate/src/locateMenu.js:9 +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:128 msgid "Map" msgstr "Mapa" @@ -596,13 +933,37 @@ msgstr "Máx. {length} caracteres" msgid "Measuring links" msgstr "Midiendo enlaces" +#: plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx:9 +msgid "Mesh Map" +msgstr "Mapa de la red mesh" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx:9 +msgid "Mesh Wide Upgrade" +msgstr "Sistema de la red" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:16 +msgid "Mesh upgrade confirmed successfully" +msgstr "Actualización de toda la red confirmada." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:20 +msgid "Mesh upgrade confirmed with some errors" +msgstr "Actualización de la red confirmada con algunos errores." + +#: plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx:20 +msgid "Mesh wide config" +msgstr "Configuración de la red completa" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:10 +msgid "Mesh wide upgrade started!" +msgstr "¡Actualización lista para inciar!" + #: plugins/lime-plugin-metrics/src/metricsMenu.js:9 msgid "Metrics" -msgstr "Diagnostico" +msgstr "Diagnóstico" #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:79 msgid "More details on the release can be found at:" -msgstr "Puedes encontrar las novedades de esta versión en:" +msgstr "Puedes encontrar más información sobre esta versión en:" #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:127 msgid "More info at:" @@ -612,18 +973,59 @@ msgstr "Más info en:" msgid "More than 10 characters" msgstr "Más de 10 caracteres" -#: plugins/lime-plugin-rx/src/rxPage.js:80 -msgid "Most Active" -msgstr "Enlace más activo" +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:60 +msgid "Most active link" +msgstr "Link más activo" #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:129 msgid "Must select a valid hostname" -msgstr "Debes elegir un nombre de host valido" +msgstr "Debes elegir un nombre de host válido." + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:73 +msgid "Name" +msgstr "Nombre" + +#: plugins/lime-plugin-rx/src/components/footer.tsx:19 +msgid "Need support?" +msgstr "Necesita soporte?" #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:82 msgid "Network Name: {ssid}" msgstr "Nombre de Red: {ssid}" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:126 +msgid "New Macs ({0})" +msgstr "Nuevas MACs({0})" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:36 +msgid "New available version:<0/>{0}" +msgstr "Nueva versión disponible:<0/>{0}" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx:85 +msgid "New link" +msgstr "Nuevo link" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:351 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:184 +msgid "New reference state set!" +msgstr "¡Nuevo estado de referencia establecido!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:64 +msgid "New version available!" +msgstr "Nueva versión disponible!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:33 +msgid "No new version available is found" +msgstr "No se ha encontrado una nueva versión disponible." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx:11 +msgid "No new version available!" +msgstr "No hay una nueva versión disponible!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx:23 +msgid "No nodes present on the <0/>mesh wide upgrade state yet!" +msgstr "No hay nodos presentes en <0/> el estado de actualizaciones de la red completa!" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:35 msgid "No password" msgstr "Sin contraseña" @@ -632,6 +1034,10 @@ msgstr "Sin contraseña" msgid "No scan result" msgstr "Sin resultado de escaneo" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:14 +msgid "No upgrade in progres" +msgstr "No hay una actualización en curso." + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:30 #: src/containers/RebootPage/RebootPage.js:45 msgid "No, cancel" @@ -640,13 +1046,25 @@ msgstr "No, cancelar" #: plugins/lime-plugin-node-admin/src/nodeAdminMenu.js:9 #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:84 msgid "Node Configuration" -msgstr "Configuración del Nodo" +msgstr "Configuración del nodo" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:74 +msgid "Node Info" +msgstr "Información del nodo" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:76 +msgid "Node Info Reference" +msgstr "Información de referencia sobre el nodo" #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:20 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:43 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:48 msgid "Node Name" -msgstr "Nombre del Nodo" +msgstr "Nombre del nodo" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:53 +msgid "Node is upgrading" +msgstr "El nodo se está actualizando" #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:99 @@ -676,7 +1094,7 @@ msgstr "En su radio {radioNumber}" #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:126 msgid "On its radio {toRadio}" -msgstr "En su radio {radioNumber}" +msgstr "En su radio {toRadio}" #: plugins/lime-plugin-metrics/src/components/showPathButton.js:30 msgid "Only gateway" @@ -685,19 +1103,23 @@ msgstr "Solo la puerta de enlace" #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:57 #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:72 msgid "Opens the \"{apSsid}\" AP in this node" -msgstr "Abre el AP \"{apSsid}\" en este nodo" +msgstr "Habilita que los dispositivos se conecten a este nodo a la señal \"{apSsid}\"." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:136 msgid "Or choose a firmware image from your device" -msgstr "O elige una imagen de firmware desde tu dispositivo" +msgstr "O elige un archivo de sistema (firmware) desde tu dispositivo." #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:85 msgid "Or if this node is already configured, you can skip this step" -msgstr "O, si tu nodo ya está bien configurado, puedes saltear este paso" +msgstr "O, si tu nodo ya está bien configurado, puedes saltear este paso." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:248 msgid "Or upgrade to latest release" -msgstr "O actualiza a la última version del firmware" +msgstr "O actualiza a la última versión del sistema (firmware)." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:94 +msgid "Other nodes will download the firmware from it" +msgstr "Esto significa que otros nodos descargarán el archivo de sistema alojado en este nodo." #: plugins/lime-plugin-metrics/src/components/box/index.js:110 msgid "Packet loss" @@ -712,6 +1134,10 @@ msgstr "Contraseña" msgid "Password: {password}" msgstr "Contraseña: {password}" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:119 +msgid "Path to Internet" +msgstr "Recorrido a internet" + #: plugins/lime-plugin-pirania/src/components/voucherListItem.js:58 msgid "Permanent" msgstr "Permanente" @@ -722,28 +1148,28 @@ msgstr "Por favor, seleccione un archivo .bin o .sh" #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:219 msgid "Please select a file" -msgstr "Porfavor, elige un archivo" +msgstr "Por favor, elige un archivo." #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:106 msgid "Please stay connected to the wifi network" -msgstr "Por favor, permanece conectado/a a la red wifi." +msgstr "Por favor, no se desconecte de la red wifi." #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:126 msgid "Please verify your internet connection" -msgstr "Por favor verifica tu conexión a internet" +msgstr "Por favor, verifique su conexión a internet." #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:36 msgid "Please wait patiently for {remainingTime} seconds and do not disconnect the device." -msgstr "Por favor espere {remainingTime} segundos pacientemente y no desconecte el router." +msgstr "Por favor, espere {remainingTime} segundos pacientemente y no desconecte el equipo." #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:36 #: src/containers/RebootPage/RebootPage.js:28 msgid "Please wait while the device reboots, and reload the app" -msgstr "Por favor espere a que el dispositivo se reinicie y recargue la app" +msgstr "Por favor, espere hasta que el dispositivo se reinicie y recargue la app." #: plugins/lime-plugin-fbw/src/containers/Setting.js:90 msgid "Please wait {time} seconds" -msgstr "Por favor espere {time} segundos" +msgstr "Por favor, espere {time} segundos..." #: plugins/lime-plugin-align/src/alignPage.js:137 msgid "Radio {radioNumber}" @@ -752,21 +1178,47 @@ msgstr "Radio {radioNumber}" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:116 #: plugins/lime-plugin-network-admin/src/netAdminPage.js:60 msgid "Re-enter Password" -msgstr "Re-ingrese la contraseña" +msgstr "Reingrese la contraseña" #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:111 #: plugins/lime-plugin-network-admin/src/netAdminPage.js:56 msgid "Re-enter the shared password" -msgstr "Re-ingrese la contraseña compartida" +msgstr "Reingrese la contraseña compartida" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:196 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:207 +msgid "Ready to start mesh wide upgrade" +msgstr "Listo para distribuir la actualización a toda la red" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:67 +msgid "Ready to start mesh wide<0/>firmware upgrade" +msgstr "Listo para iniciar la actualización de sistema de toda la red" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:95 #: src/containers/RebootBanner/rebootBanner.js:17 msgid "Reboot" msgstr "Reiniciar" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:63 +msgid "Reboot node {0}" +msgstr "Reiniciar nodo {0}" + #: src/containers/RebootPage/RebootPage.js:25 msgid "Rebooting" msgstr "Reiniciando" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:35 +msgid "Reference State is not set" +msgstr "Estado de referencia no establecido." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:387 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:220 +msgid "Reference is not set or has errors" +msgstr "El estado de referencia no ha sido establecido o contiene errores." + +#~ msgid "Reference state is not set for {dataType}" +#~ msgstr "Estado de referencia no establecido por {dataType}." + #: plugins/lime-plugin-ground-routing/src/groundRoutingPage.js:32 msgid "Reload" msgstr "Recargar" @@ -779,6 +1231,17 @@ msgstr "Recargar página" msgid "Remote Support" msgstr "Soporte Remoto" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:67 +msgid "Remove this {0} from the reference state" +msgstr "Eliminar este {0} del estado de referencia" + +#~ msgid "Remove this {dataType} from the reference state" +#~ msgstr "Eliminar este {dataType} para el estado de referencia" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:21 +msgid "Remove {nodeName} from the reference state" +msgstr "Eliminar {nodeName} para el estado de referencia" + #: src/components/form/index.js:17 msgid "Required" msgstr "Requerido" @@ -799,6 +1262,15 @@ msgstr "Revertir" msgid "Reverting to previous version" msgstr "Volviendo a la versión anterior" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:151 +msgid "RxRate" +msgstr "RxRate" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:380 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:218 +msgid "Same status as in the reference state" +msgstr "Tiene el mismo estado que el estado de referencia." + #: plugins/lime-plugin-node-admin/src/screens/hostname.js:84 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:49 #: plugins/lime-plugin-node-admin/src/screens/password.js:74 @@ -821,6 +1293,30 @@ msgstr "Guardado" msgid "Scanning for existing networks" msgstr "Buscando redes existentes" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:20 +msgid "Schedule" +msgstr "Confirmar" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:56 +msgid "Schedule a firmware upgrade for all nodes on the network" +msgstr "Actualizar una actualización de sistema (firmware) para todos los nodos de la red" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:220 +msgid "Schedule again" +msgstr "Actualizar nuevamente" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:214 +msgid "Schedule upgrade" +msgstr "Actualizar" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:46 +msgid "Schedule upgrade to all available nodes" +msgstr "Actualizar todos los nodos disponibles" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:44 +msgid "Scheduling upgrade" +msgstr "Actualizando ..." + #: plugins/lime-plugin-pirania/src/screens/voucherList.js:60 msgid "Search by" msgstr "Buscar por" @@ -839,40 +1335,78 @@ msgstr "Ver más" #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:130 msgid "Select" -msgstr "Selecciona" +msgstr "Seleccione" #: plugins/lime-plugin-changeNode/src/changeNodePage.js:53 msgid "Select another node and use the LimeApp as you were there" -msgstr "Selecciona el nodo que quieras visitar y usa la LimeApp como si estuvieras ahí" +msgstr "Seleccione el nodo que quieras visitar y use la LimeApp como si estuviera ahí." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:190 #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:89 msgid "Select file" -msgstr "Seleccioná el archivo" +msgstr "Seleccione el archivo" #: plugins/lime-plugin-changeNode/src/changeNodePage.js:60 msgid "Select new node" -msgstr "Selecciona el nodo" +msgstr "Seleccione el nodo" #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:75 msgid "Selected network to join" msgstr "Red seleccionada para unirse" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:25 +msgid "Sending abort message to this node. The abort order will be propagated to all nodes." +msgstr "Enviando mensaje de cancelación a este nodo. La orden de cancelación se propagará a todos los nodos." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:62 +msgid "Sending confirmation" +msgstr "Enviando confirmación" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:106 msgid "Set network" msgstr "Sumarse a la red" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:204 +msgid "Set reference state for this node" +msgstr "Establecer el estado de referencia para este nodo." + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:58 +msgid "Set reference state for this {0}?" +msgstr "¿Desea fijar el estado de referencia para {0}?" + +#~ msgid "Set reference state for this {dataType} link?" +#~ msgstr "Establecer el estado de referencia para este {dataType} enlace?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:363 +msgid "Set reference state for this<0/> {0}" +msgstr "Fijar estado de referencia para este<0/> {0}" + +#~ msgid "Set reference state for this<0/> {0} link" +#~ msgstr "Establecer el estado de referencia para este<0/> {0} enlace." + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:17 +msgid "Set reference state for {nodeName}" +msgstr "Establecer el estado de referencia para {nodeName}." + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:18 +msgid "Set the reference state for this node." +msgstr "Establecer el estado de referencia para este nodo." + #: plugins/lime-plugin-fbw/src/containers/Setting.js:80 msgid "Setting network" msgstr "Configurando red" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:86 +msgid "Setting up main node" +msgstr "Configurando el nodo principal" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:82 msgid "Setting up new password" msgstr "Configurando la nueva contraseña" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:90 msgid "Setup Hotspot" -msgstr "Configurar Punto de Acceso Móvil" +msgstr "Configurar Punto de Acceso Móvil (Hotspot)" #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:111 msgid "Setup activation deadline" @@ -880,11 +1414,11 @@ msgstr "Elegir plazo para activación" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:146 msgid "Share the following command with whoever you want to give them access to your node" -msgstr "Comparte el siguiente comando con quien quieras para darle acceso a tu nodo" +msgstr "Comparte el siguiente comando con quien quieras para darle acceso a tu nodo." #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:139 msgid "Share your mobile connection by connecting the node to a mobile hotspost" -msgstr "Comparte tu conexión de datos con el nodo a través de un Punto de Acceso Móvil" +msgstr "Comparte la conexión de datos de tu celular con el nodo (y toda la red)." #: plugins/lime-plugin-network-admin/src/netAdminMenu.js:9 #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:48 @@ -893,13 +1427,29 @@ msgstr "Contraseña Compartida" #: plugins/lime-plugin-network-admin/src/netAdminPage.js:87 msgid "Shared Password changed successfully" -msgstr "La contraseña compartida se cambió correctamente" +msgstr "La contraseña compartida se cambió correctamente." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:68 +msgid "Shared state error" +msgstr "Error de shared state" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:156 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:165 msgid "Show Console" msgstr "Ver consola" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:65 +msgid "Show nodes" +msgstr "Ver nodos" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:57 +msgid "Show state" +msgstr "Ver estado" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:118 +msgid "Signal" +msgstr "Señal" + #: plugins/lime-plugin-align/src/alignPage.js:52 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:64 msgid "Signal lost" @@ -909,6 +1459,50 @@ msgstr "Sin señal" msgid "Size" msgstr "Tamaño" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:59 +msgid "Some nodes are not ready" +msgstr "Algunos nodos aún no están listos." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:209 +msgid "Some nodes are not ready for upgrade <0/>Check node details for more info" +msgstr "Algunos nodos aún no están listos para ser actualizados. <0/>Consulte el botón \"Ver nodos\" para obtener más información." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:18 +msgid "Some nodes are still downloading the firmware<0/>check network page for more information" +msgstr "Algunos nodos todavía están descargando el firmware<0/>consulte la página de red para obtener más información." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:85 +msgid "Some nodes don't upgraded properly" +msgstr "Algunos nodos no se actualizan correctamente." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:226 +msgid "Some nodes have errors" +msgstr "Algunos nodos tienen errores." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx:36 +msgid "Some nodes have errors:" +msgstr "Algunos nodos tienen errores:" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:91 +msgid "Source IP" +msgstr "IP de origen" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:197 +msgid "Start" +msgstr "Distribuir" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:189 +msgid "Start mesh upgrade" +msgstr "Iniciar descarga" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:74 +msgid "Start mesh wide firmware upgrade again" +msgstr "Es recomendable Iniciar la actualización en toda la red nuevamente." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:59 +msgid "Start mesh wide upgrade" +msgstr "Distribuir la actualización en todos los nodos de la red" + #: plugins/lime-plugin-rx/src/rxMenu.js:9 msgid "Status" msgstr "Estado" @@ -917,41 +1511,74 @@ msgstr "Estado" msgid "Status: {0}" msgstr "Estado: {0}" -#: plugins/lime-plugin-rx/src/rxPage.js:42 +#: src/components/Modal/Modal.tsx:60 +#: src/components/Modal/Modal.tsx:126 +msgid "Success" +msgstr "Completado" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:78 msgid "System" msgstr "Sistema" #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:75 msgid "The Community AP is present in every node allowing people to move around the network territory without losing connection" -msgstr "El AP Comunitario está presente en todos los nodos permitiendo que las personas se muevan por el territorio de la red sin perder conectividad" +msgstr "El punto de acceso (AP) comunitario está presente en todos los nodos permitiendo que las personas se muevan por el territorio de la red sin perder conectividad." #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:32 msgid "The Community Portal enables a welcome screen to be displayed in the web browser to anyone connecting to the network using the Community AP" -msgstr "El Portal Comunitario permite mostrar una pantalla de bienvenida en el navegador a cualquier persona que se conecte a la red a través del AP Comunitario" +msgstr "El portal comunitario permite mostrar una pantalla de bienvenida en el navegador a cualquier persona que se conecte a la red a través del punto de acceso (AP) comunitario." #: plugins/lime-plugin-align/src/alignPage.js:157 msgid "The are not mesh interfaces available" -msgstr "No hay interfaces mesh disponibles" +msgstr "No hay interfaces mesh disponibles." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:88 +msgid "The become main node process is starting on this node" +msgstr "El proceso para convertir este nodo en el principal está comenzando." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:135 +msgid "The difference between chains is too big" +msgstr "La diferencia entre cadenas es demasiado grande." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:113 msgid "The download failed" -msgstr "La descarga falló" +msgstr "La descarga falló." #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:32 msgid "The firmware is being upgraded..." msgstr "La actualización se está realizando..." +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:52 +msgid "The firmware seems to be installed successfully. Confirm that the node is working properly or will be downgraded to the previous version" +msgstr "El firmware parece haberse instalado correctamente. Confirme que el nodo funciona correctamente o se volverá a la versión anterior." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:20 +msgid "The following nodes are not located or have not reference state. Please, set their location to see them on the map:" +msgstr "Los siguientes nodos no están ubicados o no tienen estado de referencia. Por favor, establece su ubicación para verlos en el mapa:" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:72 +msgid "The following shared states packages have errors. Are they installed or properly initialized?" +msgstr "Los siguientes paquetes de shared states tienen errores. ¿Están instalados o inicializados correctamente?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:39 +msgid "The following shared states packages have not data set" +msgstr "Los siguientes paquetes de shared state no tienen conjunto de datos." + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:115 msgid "The hotspot couldn’t be found, please review the instructions above." -msgstr "El punto de acceso no se encuentra disponible, por favor revisa las instrucciones." +msgstr "El punto de acceso no se encuentra disponible. Por favor, revisa las instrucciones." #: plugins/lime-plugin-node-admin/src/screens/hostname.js:70 msgid "The name should have at least 3 characters" -msgstr "El nombre tiene que tener al menos 3 caracteres" +msgstr "El nombre tiene que tener al menos 3 caracteres." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:77 +msgid "The node is down" +msgstr "El nodo no está activo." #: plugins/lime-plugin-node-admin/src/screens/password.js:60 msgid "The password should have at least 8 characters" -msgstr "La contraseña tiene que tener al menos 8 caracteres" +msgstr "La contraseña tiene que tener al menos 8 caracteres." #: src/containers/SharedPasswordForm/sharedPasswordForm.js:38 msgid "The password should have:" @@ -968,55 +1595,140 @@ msgstr "La radio necesita reiniciarse..." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:240 msgid "The selected image is not valid for the target device" -msgstr "La imagen seleccionada no es válida para este dispositivo" +msgstr "La imagen seleccionada no es válida para este dispositivo." #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:71 msgid "The shared password has been chosen by the community when the network was created. You can ask other community members for it." -msgstr "La contraseña compartida fue elegida por la comunidad al iniciar la red. Pregúntale a otros miembros cuál es." +msgstr "La contraseña compartida fue elegida por la comunidad al iniciar la red. Pregúntale a quienes gestionan la red cuál es." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:123 +msgid "The signal is X below the reference state" +msgstr "La señal está X por debajo del estado de referencia." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:44 +msgid "The upgrade is scheduled" +msgstr "La actualización ha comenzado." #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:9 msgid "The upgrade should be done" -msgstr "La actualización debiera estar lista" +msgstr "La actualización debería estar lista." #: plugins/lime-plugin-pirania/src/screens/voucherList.js:110 msgid "There are no vouchers matching the current criteria" -msgstr "No hay cupones para tu búsqueda" +msgstr "No hay cupones para su búsqueda." #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:132 msgid "There's an active remote support session" -msgstr "Hay una sesión de soporte remoto activa" +msgstr "Hay una sesión de soporte remoto activa." #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:110 msgid "There's no open session for remote support. Click at Create Session to begin one" -msgstr "No hay una sesión de soporte remoto abierta. Haz click en Crear Sesión para empezar una" +msgstr "No hay una sesión de soporte remoto abierta. Haz click en Crear Sesión para empezar una." #: plugins/lime-plugin-align/src/alignPage.js:111 msgid "These are the nodes associated on this radio" -msgstr "Estos son los nodos asociados a esta radio" +msgstr "Estos son los nodos asociados a esta radio." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:384 +msgid "This Link is not registered on the reference state" +msgstr "Este enlace no está registrado en el estado de referencia." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:35 msgid "This device does not support secure rollback to previous version if something goes wrong" -msgstr "En este dispositivo no se puede revertir la actualización en caso de errores" +msgstr "Este dispositivo está habilitado para revertir la actualización en caso de errores." #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:27 msgid "This device supports secure rollback to previous version if something goes wrong" -msgstr "En este dispositivo se puede revertir la actualización en caso de errores" +msgstr "En este dispositivo sí se puede revertir la actualización en caso de errores." #: src/components/form/index.js:21 msgid "This field is required" msgstr "Este campo es requerido" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:92 +msgid "This is a main node" +msgstr "Este es un nodo principal" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:389 +msgid "This link has errors" +msgstr "Este enlace tiene errores." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:169 +msgid "This link seems down" +msgstr "Este enlace parece estar caído." + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:73 +msgid "This link seems down, remove them from the reference state?" +msgstr "Este enlace parece caído, ¿desea eliminarlo del estado de referencia?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:111 +msgid "This macs are not on the actual state" +msgstr "Estos macs no están en el estado actual." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:129 +msgid "This macs are not on the reference state" +msgstr "Estas MACs no están en el estado de referencia" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:73 +msgid "This node aborted" +msgstr "Actualización interrumpida." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:86 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:21 +msgid "This node aborted successfully" +msgstr "La actualización fue interrumpida con éxito." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:41 +msgid "This node es ready for upgrade" +msgstr "Este nodo está listo para actualizarse." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:20 +msgid "This node has an error" +msgstr "Este nodo tiene un error." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:69 +msgid "This node has an error!" +msgstr "Este nodo tiene un error!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:36 +msgid "This node is downloading a new firmware" +msgstr "Este nodo está descargando un nuevo archivo de sistema (firmware)." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:225 +msgid "This node is not registered on the reference state" +msgstr "Este nodo no está registrado en el estado de referencia." + #: plugins/lime-plugin-metrics/src/components/showPathButton.js:16 msgid "This node is the gateway" -msgstr "Este nodo es el gateway" +msgstr "Este nodo es el gateway." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:36 +msgid "This node seems down" +msgstr "Este nodo parece inactivo." + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:24 +msgid "This node seems down, remove them from the reference state?" +msgstr "Este nodo parece inactivo, ¿desea eliminarlo del estado de referencia?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:21 +msgid "This node version<0/>{0}" +msgstr "Versión de este nodo<0/>{0}" #: plugins/lime-plugin-align/src/alignPage.js:119 msgid "This radio is not associated with other nodes" -msgstr "Esta radio no está enlazada a otros nodos" +msgstr "Esta radio no está enlazada a otros nodos." + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:63 +msgid "This will set the reference state of this link:" +msgstr "Esto establecerá el estado de referencia de este enlace:" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:104 +msgid "This will the abort current upgrade process on all nodes. Are you sure you want to proceed?" +msgstr "Esto cancelará el proceso de actualización actual en todos los nodos. ¿Está seguro que deseas continuar?" #: plugins/lime-plugin-metrics/src/metricsPage.tsx:120 msgid "This your last working path to the Internet" -msgstr "Este es el último recorrido hasta Internet que funcionó" +msgstr "Este es el último recorrido hasta Internet que funcionó." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:41 msgid "Title" @@ -1030,26 +1742,58 @@ msgstr "Hasta Internet" msgid "To enable remote access an internet connection is needed" msgstr "Para posibilitar el acceso remoto es necesaria una conexión a internet." -#: plugins/lime-plugin-rx/src/rxPage.js:103 -msgid "Traffic" -msgstr "Tráfico" +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:78 +msgid "Traffic:" +msgstr "Tráfico:" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:248 +msgid "Try last step again" +msgstr "Intente el último paso nuevamente" #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:12 msgid "Try reloading the app" msgstr "Intentar recargar la app" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:148 +msgid "TxRate" +msgstr "TxRate" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:100 msgid "Unknown error" msgstr "Error desconocido" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:226 +msgid "Unknown link type" +msgstr "Tipo de enlace desconocido" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:16 +msgid "Updating shared state {0}" +msgstr "Actualizando shared state" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:229 msgid "Upgrade" -msgstr "Actualizar" +msgstr "Confirmar" #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:101 msgid "Upgrade Now" msgstr "Actualizar ahora" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:74 +msgid "Upgrade all network nodes at once. This proces will take a while and will require user interaction." +msgstr "Actualice todos los nodos de la red a la vez. Este proceso llevará un tiempo y requerirá la interacción del usuario." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:16 +msgid "Upgrade is scheduled!" +msgstr "La actualización está iniciada!" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:17 +msgid "Upgrade scheduled" +msgstr "La actualización está iniciada" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:60 +msgid "Upgrade successful" +msgstr "La actualización fue exitosa" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:85 msgid "Upgrade to lastest firmware version" msgstr "Actualizar a la última version del firwmare" @@ -1059,11 +1803,17 @@ msgstr "Actualizar a la última version del firwmare" msgid "Upgrade to {versionName}" msgstr "Actualizar a {versionName}" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:12 +msgid "Upgraded!<0/>Awaiting confirmation" +msgstr "Actualizado!<0/>Esperando confirmación" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:181 msgid "Upload firmware image from your device" -msgstr "Subí una imagen del firmware desde tu dispositivo" +msgstr "Suba un archivo de sistema (imagen del firmware) desde tu dispositivo" -#: plugins/lime-plugin-rx/src/rxPage.js:45 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:72 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:76 +#: plugins/lime-plugin-rx/src/sections/system.tsx:45 msgid "Uptime" msgstr "Tiempo en actividad" @@ -1071,10 +1821,18 @@ msgstr "Tiempo en actividad" msgid "Use vouchers for access" msgstr "Usar cupones de acceso" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:49 +msgid "Value" +msgstr "Valor" + #: plugins/lime-plugin-changeNode/src/changeNodePage.js:75 msgid "Visit" msgstr "Visitar" +#: plugins/lime-plugin-rx/src/components/footer.tsx:33 +msgid "Visit <0>docs.altermundi.net" +msgstr "Visitar <0>docs.altermundi.net" + #: plugins/lime-plugin-changeNode/src/changeNodeMenu.js:9 #: plugins/lime-plugin-changeNode/src/changeNodePage.js:50 msgid "Visit a neighboring node" @@ -1094,23 +1852,35 @@ msgstr "Descripción del grupo de cupones" #: plugins/lime-plugin-pirania/src/screens/voucherList.js:54 msgid "Voucher list" -msgstr "Lista de Cupones" +msgstr "Lista de cupones" #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:57 msgid "Vouchers can be used to limit access through the Community Portal to those who have an authorization code" -msgstr "Los cupones sirven para limitar el acceso a través del Portal Comunitario a quienes posean un código de autorización" +msgstr "Los cupones sirven para limitar el acceso a través del Portal Comunitario a quienes posean un código de autorización." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:37 +msgid "Wait until the download is finished!" +msgstr "¡Espere hasta que finalice la descarga!" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:54 msgid "Welcome to LimeApp" -msgstr "Bienvenido/a a la LimeApp" +msgstr "A disfrutar de LimeApp!" #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:197 msgid "Wellcome Screen" -msgstr "Pantalla de Bienvenida" +msgstr "Pantalla de bienvenida" #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:17 msgid "When reloading the app you will be asked to confirm the upgrade, otherwise it will be reverted" -msgstr "Al recargar la aplicación, se te pedirá que confirmes la actualización, si no lo haces se revertirá" +msgstr "Al recargar la aplicación, se te pedirá que confirmes la actualización, si no lo haces se revertirá." + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:78 +msgid "Wifi Links" +msgstr "Enlaces Wifi" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:80 +msgid "Wifi Links Reference" +msgstr "Enlaces Wifi de Referencia" #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:34 #: plugins/lime-plugin-node-admin/src/screens/password.js:45 @@ -1118,6 +1888,10 @@ msgstr "Al recargar la aplicación, se te pedirá que confirmes la actualizació msgid "Wifi Password" msgstr "Contraseña del Wifi" +#: plugins/lime-plugin-rx/src/sections/wired.tsx:62 +msgid "Wired connections" +msgstr "Conexiones cableadas" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:121 msgid "With radio {fromRadio} alignin with" msgstr "Con radio {fromRadio} alineando con" @@ -1128,7 +1902,7 @@ msgstr "Con este segundo celular crea un punto de acceso móvil (\"hotspot\") co #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:58 msgid "Wrong password, try again" -msgstr "Contraseña incorrecta, intenta nuevamente" +msgstr "Contraseña incorrecta, intente nuevamente" #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:27 #: src/containers/RebootPage/RebootPage.js:42 @@ -1145,15 +1919,15 @@ msgstr "Usted es ahora parte de" #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:83 msgid "You can share your mobile connection to the node by setting up a mobile hotspot" -msgstr "Puedes compartir tu conexión de datos con el nodo a través de un Punto de Acceso Móvil" +msgstr "Puede compartir tu conexión de datos con el nodo a través de un Punto de Acceso Móvil (hotspot)." #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:73 msgid "You can upgrade to:" -msgstr "Puedes actualizar a:" +msgstr "Puede actualizar a:" #: plugins/lime-plugin-metrics/src/components/showPathButton.js:19 msgid "You don't go through any paths to get here." -msgstr "No necesitas pasar por ningún nodo para llega hasta aquí." +msgstr "No necesita pasar por ningún nodo para llega hasta aquí." #: plugins/lime-plugin-fbw/src/containers/Setting.js:131 msgid "You have successfuly connected to" @@ -1161,53 +1935,55 @@ msgstr "La conexión fué exitosa, está conectado a" #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:43 msgid "You need to know the shared password to enter this page" -msgstr "Debes ingresar la contraseña compartida para seguir" +msgstr "Debe ingresar la contraseña compartida para seguir" #: plugins/lime-plugin-fbw/src/containers/Setting.js:113 msgid "You should try to connect to the network {wifiSsid}." msgstr "Intente conectarse a la red wifi {wifiSsid} para completar la instalación." +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:113 +msgid "Your Alignment" +msgstr "Su alineación" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:74 msgid "Your node has no internet connection" -msgstr "Tu nodo no tiene conexión a internet" +msgstr "Su nodo no tiene conexión a internet" -#: plugins/lime-plugin-locate/src/locateMap.tsx:207 #: plugins/lime-plugin-locate/src/locatePage.tsx:225 msgid "cancel" -msgstr "cancelar" +msgstr "Cancelar" -#: plugins/lime-plugin-locate/src/locateMap.tsx:193 #: plugins/lime-plugin-locate/src/locatePage.tsx:211 msgid "confirm location" -msgstr "confirmar ubicación" +msgstr "Confirmar ubicación" -#: plugins/lime-plugin-locate/src/locateMap.tsx:209 #: plugins/lime-plugin-locate/src/locatePage.tsx:227 msgid "edit location" -msgstr "modificar ubicación" +msgstr "Modificar ubicación" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:54 +msgid "for the following nodes: {nodes}" +msgstr "para los siguientes nodos: {nodes}" -#: plugins/lime-plugin-locate/src/locateMap.tsx:199 #: plugins/lime-plugin-locate/src/locatePage.tsx:217 msgid "hide community" -msgstr "esconder comunidad" +msgstr "Esconder comunidad" -#: plugins/lime-plugin-locate/src/locateMap.tsx:212 #: plugins/lime-plugin-locate/src/locatePage.tsx:230 msgid "locate my node" -msgstr "ubicar mi nodo" +msgstr "Ubicar mi nodo" #: plugins/lime-plugin-align/src/components/secondsAgo.js:21 msgid "more than a minute ago" -msgstr "hace más de un minuto" +msgstr "hace más de un minuto." -#: plugins/lime-plugin-locate/src/locateMap.tsx:201 #: plugins/lime-plugin-locate/src/locatePage.tsx:219 msgid "show community" -msgstr "mostrar comunidad" +msgstr "Mostrar comunidad" #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:14 msgid "to keep the current configuration. Or ..." -msgstr "la actualización, o..." +msgstr "para mantener la configuración actual, o..." #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:20 msgid "to the previous configuration" @@ -1217,23 +1993,33 @@ msgstr "a la versión anterior" msgid "{0, plural, =0 {No one has joined yet.} one {One person has joined.} other {# people have joined.}}" msgstr "{0, plural, =0 {Nadie se ha unido aún.} one {Una persona se ha unido.} other {# personas se han unido.}}" -#: plugins/lime-plugin-rx/src/rxPage.js:20 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:66 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:70 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:74 +msgid "{0}" +msgstr "{0}" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:22 msgid "{days, plural, one {# day} other {# days}}" msgstr "{days, plural, one {# día} other {# días}}" -#: plugins/lime-plugin-rx/src/rxPage.js:23 +#: plugins/lime-plugin-rx/src/sections/system.tsx:25 msgid "{hours, plural, one {# hour} other {# hours}}" msgstr "{hours, plural, one {# hora} other {# horas}}" -#: plugins/lime-plugin-rx/src/rxPage.js:26 +#: plugins/lime-plugin-rx/src/sections/system.tsx:28 msgid "{mins, plural, one {# minute} other {# minutes}}" msgstr "{mins, plural, one {# minuto} other {# minutos}}" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:18 +msgid "{nodesToBeUpgraded} of {totalNodes} will be upgraded" +msgstr "{nodesToBeUpgraded} de {totalNodes} serán actualizados, espere." + #: plugins/lime-plugin-align/src/components/secondsAgo.js:23 msgid "{secondsAmount} seconds ago" msgstr "hace {secondsAmount} segundos" -#: plugins/lime-plugin-rx/src/rxPage.js:29 +#: plugins/lime-plugin-rx/src/sections/system.tsx:31 msgid "{secs, plural, one {# second} other {# seconds}}" msgstr "{secs, plural, one {# segundo} other {# segundos}}" diff --git a/i18n/it/messages.po b/i18n/it/messages.po index 9808ac164..e617028e4 100644 --- a/i18n/it/messages.po +++ b/i18n/it/messages.po @@ -13,6 +13,18 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:46 +msgid "(Main Node) {descriptionMsg}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx:40 +msgid "(new)" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:26 +msgid "10 of 12 node are ready to update" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:67 msgid "A new firmware version has been released" msgstr "" @@ -21,6 +33,19 @@ msgstr "" msgid "A reboot is needed to apply changes" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:109 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:256 +msgid "Abort" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:102 +msgid "Abort current mesh wide upgrade?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:23 +msgid "Aborting" +msgstr "" + #: plugins/lime-plugin-pirania/src/piraniaMenu.js:9 msgid "Access Vouchers" msgstr "" @@ -49,6 +74,23 @@ msgstr "" msgid "Active" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:80 +msgid "Add" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:101 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:78 +msgid "Add new section" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:92 +msgid "Added section {0} - {1}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:46 +msgid "After a time the upgrade will be performed" +msgstr "" + #: plugins/lime-plugin-align/src/alignMenu.js:9 msgid "Align" msgstr "Allineare" @@ -57,10 +99,38 @@ msgstr "Allineare" msgid "All Vouchers" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:54 +msgid "All nodes are ready" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:80 +msgid "All nodes are upgraded successfully" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:232 +msgid "All nodes scheduled successful" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:87 +msgid "Are you sure you want to confirm the upgrade? <0/>Check node list to see the network status" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:66 +msgid "Are you sure you want to reboot this node? This action will disconnect the node from the network for a few minutes. <0/>Add shared password or let it empty if no password is set." +msgstr "" + #: src/containers/RebootPage/RebootPage.js:39 msgid "Are you sure you want to reboot?" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:61 +msgid "Are you sure you want to start mesh wide upgrade? <0/>Check node list to see the network status" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:24 +msgid "Are you sure you want to {title} the <0>{prop} property?" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:24 msgid "Are you sure?" msgstr "" @@ -88,6 +158,22 @@ msgstr "" msgid "Available" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:54 +msgid "Await until it reboots" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:50 +msgid "Awaiting confirmation" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:86 +msgid "Babel Links" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:88 +msgid "Babel Links Reference" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:22 msgid "Back" msgstr "" @@ -96,10 +182,22 @@ msgstr "" msgid "Background Color" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:82 +msgid "Batman Links" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:84 +msgid "Batman Links Reference" +msgstr "" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:41 msgid "Best signal" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:65 +msgid "Board" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:96 msgid "Calculating network path" msgstr "" @@ -107,6 +205,8 @@ msgstr "" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:83 #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:150 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:14 +#: src/components/Modal/Modal.tsx:62 +#: src/components/Modal/Modal.tsx:128 #: src/components/banner/index.js:20 msgid "Cancel" msgstr "" @@ -131,6 +231,10 @@ msgstr "" msgid "Cellphone Instructions" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:132 +msgid "Chains" +msgstr "" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:76 msgid "Change" msgstr "Modifica" @@ -140,9 +244,18 @@ msgid "Change Shared Password" msgstr "" #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:123 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:143 msgid "Channel" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:22 +msgid "Check if network is working properly and confirm the upgrade<0/>If not confirmed, the upgrade will be rolled back after a while" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:91 +msgid "Check<0/>Alignment" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:100 msgid "Checking connection" msgstr "" @@ -173,6 +286,10 @@ msgstr "" msgid "Click at Show Console to follow the remote support session." msgstr "" +#: src/components/Modal/Modal.tsx:205 +msgid "Close" +msgstr "" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:170 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:183 msgid "Close Session" @@ -205,13 +322,46 @@ msgid "Configure your new community network" msgstr "" #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:11 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:241 msgid "Confirm" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:82 +msgid "Confirm mesh wide upgrade for all nodes on the network" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:240 +msgid "Confirm upgrade on all nodes" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:18 +msgid "Confirmation pending" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:19 +msgid "Confirmed" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:19 +msgid "Confirmed with some errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:15 +msgid "Confirmed!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:63 +msgid "Confirming all upgraded nodes" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:127 msgid "Congratulations" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:62 +msgid "Congratulations, this node was upgraded and confirmed successfully" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:37 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:199 @@ -235,6 +385,11 @@ msgstr "" msgid "Connection to the internet" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:34 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:90 +msgid "Continue" +msgstr "" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:134 #: plugins/lime-plugin-pirania/src/screens/voucherList.js:122 msgid "Create" @@ -273,6 +428,30 @@ msgstr "" msgid "Currently your node has version:" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:44 +msgid "Delete" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:43 +msgid "Delete property" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:206 +msgid "Delete this this node from reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:372 +msgid "Delete this {0}<0/>from reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:99 +msgid "Deleted {keyString}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:64 +msgid "Deleted {name} - {0}" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/editVoucher.js:28 msgid "Description" msgstr "" @@ -282,10 +461,15 @@ msgstr "" msgid "Description: {name}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:51 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:89 +#: plugins/lime-plugin-rx/src/sections/system.tsx:48 msgid "Device" msgstr "" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:125 +msgid "Diagnose" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:54 #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:72 #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigItem.tsx:20 @@ -298,14 +482,31 @@ msgstr "" msgid "Don't show this message again" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:53 +msgid "Done" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:96 msgid "Download" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:183 +msgid "Download remote firmware<0/>to start mesh upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:50 +msgid "Downloaded version<0/>{0}" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:103 +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:35 msgid "Downloading" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:15 +msgid "Downloading new firmware" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/postCreate.js:18 #: plugins/lime-plugin-pirania/src/screens/voucher.js:59 msgid "Duration: is permanent" @@ -316,6 +517,7 @@ msgstr "" msgid "Duration: {days, plural, one {# day} other {# days}}" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:51 #: plugins/lime-plugin-pirania/src/screens/voucher.js:90 msgid "Edit" msgstr "" @@ -324,10 +526,22 @@ msgstr "" msgid "Edit Voucher" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:50 +msgid "Edit property" +msgstr "" + #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:50 msgid "Edit wellcome screen" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:123 +msgid "Edited {keyString}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:47 +msgid "Edited {name} - {0}" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:25 msgid "Enable Community Roaming AP" msgstr "" @@ -361,6 +575,10 @@ msgstr "" msgid "Error" msgstr "" +#: src/components/toast/toasts.tsx:13 +msgid "Error connecting with {nodeInfo}, is node up?" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:61 msgid "Error destination network is not configured yet" msgstr "" @@ -377,6 +595,14 @@ msgstr "" msgid "Error getting scan results" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx:41 +msgid "Error loading leaflet" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:85 +msgid "Error performing reboot: {error}" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:40 msgid "Error reaching hostname!" msgstr "" @@ -386,6 +612,14 @@ msgstr "" msgid "Error retrieving associated list" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:43 +msgid "Error retrieving the status, is this node outdated?" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:101 +msgid "Error retrieving<0/>last internet path" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanList.js:155 msgid "Error scanning networks" msgstr "" @@ -394,14 +628,31 @@ msgstr "" msgid "Error setting network" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:355 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:189 +msgid "Error setting new reference state!" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanPage.tsx:83 msgid "Error stopping scan" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx:12 +msgid "Error!" +msgstr "" + #: plugins/lime-plugin-node-admin/src/layouts/configPageLayout.tsx:55 msgid "Error: Not Saved" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:35 +msgid "Errors found getting mesh info!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:32 +msgid "Everything is up to date!" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:66 msgid "Expiration date: {0}" msgstr "" @@ -422,7 +673,7 @@ msgstr "" #: plugins/lime-plugin-align/src/alignPage.js:37 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:80 -#: plugins/lime-plugin-rx/src/rxPage.js:93 +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:67 msgid "Fetching name" msgstr "" @@ -435,10 +686,23 @@ msgid "Filter by" msgstr "" #: plugins/lime-plugin-firmware/src/firmwareMenu.js:9 -#: plugins/lime-plugin-rx/src/rxPage.js:58 +#: plugins/lime-plugin-rx/src/sections/system.tsx:49 msgid "Firmware" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:40 +msgid "Firmware download and verified" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:16 +msgid "Firmware downloaded" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:80 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:69 +msgid "Firmware version" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:151 msgid "From" msgstr "Da" @@ -484,8 +748,16 @@ msgid "I don't know the shared password" msgstr "" #: plugins/lime-plugin-rx/src/rxPage.js:181 -msgid "IP Addresses" -msgstr "Indirizzi IP" +#~ msgid "IP Addresses" +#~ msgstr "Indirizzi IP" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:85 +msgid "IPv4" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:86 +msgid "IPv6" +msgstr "" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:73 msgid "If network has been already created, look it up to join" @@ -503,15 +775,39 @@ msgstr "" msgid "If your community network has local services, you can point a link to them." msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:57 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:86 +msgid "Iface" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:222 +msgid "In the reference state this node is on" +msgstr "" + #: plugins/lime-plugin-rx/src/rxPage.js:98 -msgid "Interface" -msgstr "Interfaccia" +#~ msgid "Interface" +#~ msgstr "Interfaccia" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:72 +msgid "Interface:" +msgstr "" + +#: plugins/lime-plugin-rx/src/components/internetPathChart.tsx:165 +msgid "Internet" +msgstr "" #: plugins/lime-plugin-metrics/src/components/internetStatus.js:10 -#: plugins/lime-plugin-rx/src/rxPage.js:149 msgid "Internet connection" msgstr "Connessione a Internet" +#: plugins/lime-plugin-rx/src/components/internetStatus.tsx:17 +msgid "Internet<0/>connection" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:16 +msgid "Invalid Nodes" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:97 msgid "Invalidate" msgstr "" @@ -522,6 +818,10 @@ msgstr "" msgid "Invalidated" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:73 +msgid "Ip" +msgstr "" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:75 msgid "Is permanent" msgstr "" @@ -539,15 +839,31 @@ msgstr "" msgid "It must start with https:// or http://" msgstr "" +#: plugins/lime-plugin-rx/src/components/footer.tsx:22 +msgid "Join <0>foro.librerouter.org" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:72 msgid "Join the mesh" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:44 +msgid "Key" +msgstr "" + #: plugins/lime-plugin-align/src/alignPage.js:55 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:134 msgid "Last packet" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:60 +msgid "Last seen" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:29 +msgid "Last update: 30 second ago" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:120 msgid "Link Title" msgstr "" @@ -556,18 +872,34 @@ msgstr "" msgid "Link URL" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:181 +msgid "Link from <0>{0} to <1>{1}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:248 +msgid "Link {0} {1}" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:106 msgid "Load last known Internet path" msgstr "" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:84 +msgid "Loading <0/>last internet path..." +msgstr "" + #: plugins/lime-plugin-rx/src/rxPage.js:128 -msgid "Loading node status..." -msgstr "Caricando lo stato del nodo..." +#~ msgid "Loading node status..." +#~ msgstr "Caricando lo stato del nodo..." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:111 msgid "Local services link" msgstr "" +#: plugins/lime-plugin-locate/src/locateMenu.js:9 +msgid "Locate" +msgstr "" + #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:81 msgid "Logging in" msgstr "" @@ -576,6 +908,14 @@ msgstr "" msgid "Login" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:94 +msgid "Macs ({0})" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:106 +msgid "Macs not found ({0})" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:57 msgid "Main Text" msgstr "" @@ -584,7 +924,7 @@ msgstr "" msgid "Manage Vouchers" msgstr "" -#: plugins/lime-plugin-locate/src/locateMenu.js:9 +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:128 msgid "Map" msgstr "" @@ -596,6 +936,30 @@ msgstr "" msgid "Measuring links" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx:9 +msgid "Mesh Map" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx:9 +msgid "Mesh Wide Upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:16 +msgid "Mesh upgrade confirmed successfully" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:20 +msgid "Mesh upgrade confirmed with some errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx:20 +msgid "Mesh wide config" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:10 +msgid "Mesh wide upgrade started!" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsMenu.js:9 msgid "Metrics" msgstr "Metriche" @@ -613,17 +977,62 @@ msgid "More than 10 characters" msgstr "" #: plugins/lime-plugin-rx/src/rxPage.js:80 -msgid "Most Active" -msgstr "Più attivi" +#~ msgid "Most Active" +#~ msgstr "Più attivi" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:60 +msgid "Most active link" +msgstr "" #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:129 msgid "Must select a valid hostname" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:73 +msgid "Name" +msgstr "" + +#: plugins/lime-plugin-rx/src/components/footer.tsx:19 +msgid "Need support?" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:82 msgid "Network Name: {ssid}" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:126 +msgid "New Macs ({0})" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:36 +msgid "New available version:<0/>{0}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx:85 +msgid "New link" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:351 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:184 +msgid "New reference state set!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:64 +msgid "New version available!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:33 +msgid "No new version available is found" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx:11 +msgid "No new version available!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx:23 +msgid "No nodes present on the <0/>mesh wide upgrade state yet!" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:35 msgid "No password" msgstr "" @@ -632,6 +1041,10 @@ msgstr "" msgid "No scan result" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:14 +msgid "No upgrade in progres" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:30 #: src/containers/RebootPage/RebootPage.js:45 msgid "No, cancel" @@ -642,12 +1055,24 @@ msgstr "" msgid "Node Configuration" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:74 +msgid "Node Info" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:76 +msgid "Node Info Reference" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:20 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:43 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:48 msgid "Node Name" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:53 +msgid "Node is upgrading" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:99 msgid "Not Connected" @@ -699,6 +1124,10 @@ msgstr "" msgid "Or upgrade to latest release" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:94 +msgid "Other nodes will download the firmware from it" +msgstr "" + #: plugins/lime-plugin-metrics/src/components/box/index.js:110 msgid "Packet loss" msgstr "Perdita di pacchetti" @@ -712,6 +1141,10 @@ msgstr "" msgid "Password: {password}" msgstr "" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:119 +msgid "Path to Internet" +msgstr "" + #: plugins/lime-plugin-pirania/src/components/voucherListItem.js:58 msgid "Permanent" msgstr "" @@ -759,14 +1192,37 @@ msgstr "" msgid "Re-enter the shared password" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:196 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:207 +msgid "Ready to start mesh wide upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:67 +msgid "Ready to start mesh wide<0/>firmware upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:95 #: src/containers/RebootBanner/rebootBanner.js:17 msgid "Reboot" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:63 +msgid "Reboot node {0}" +msgstr "" + #: src/containers/RebootPage/RebootPage.js:25 msgid "Rebooting" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:35 +msgid "Reference State is not set" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:387 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:220 +msgid "Reference is not set or has errors" +msgstr "" + #: plugins/lime-plugin-ground-routing/src/groundRoutingPage.js:32 msgid "Reload" msgstr "" @@ -779,6 +1235,14 @@ msgstr "" msgid "Remote Support" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:67 +msgid "Remove this {0} from the reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:21 +msgid "Remove {nodeName} from the reference state" +msgstr "" + #: src/components/form/index.js:17 msgid "Required" msgstr "" @@ -799,6 +1263,15 @@ msgstr "" msgid "Reverting to previous version" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:151 +msgid "RxRate" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:380 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:218 +msgid "Same status as in the reference state" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hostname.js:84 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:49 #: plugins/lime-plugin-node-admin/src/screens/password.js:74 @@ -821,6 +1294,30 @@ msgstr "" msgid "Scanning for existing networks" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:20 +msgid "Schedule" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:56 +msgid "Schedule a firmware upgrade for all nodes on the network" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:220 +msgid "Schedule again" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:214 +msgid "Schedule upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:46 +msgid "Schedule upgrade to all available nodes" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:44 +msgid "Scheduling upgrade" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/voucherList.js:60 msgid "Search by" msgstr "" @@ -858,14 +1355,46 @@ msgstr "" msgid "Selected network to join" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:25 +msgid "Sending abort message to this node. The abort order will be propagated to all nodes." +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:62 +msgid "Sending confirmation" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:106 msgid "Set network" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:204 +msgid "Set reference state for this node" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:58 +msgid "Set reference state for this {0}?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:363 +msgid "Set reference state for this<0/> {0}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:17 +msgid "Set reference state for {nodeName}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:18 +msgid "Set the reference state for this node." +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:80 msgid "Setting network" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:86 +msgid "Setting up main node" +msgstr "" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:82 msgid "Setting up new password" msgstr "" @@ -895,11 +1424,27 @@ msgstr "" msgid "Shared Password changed successfully" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:68 +msgid "Shared state error" +msgstr "" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:156 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:165 msgid "Show Console" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:65 +msgid "Show nodes" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:57 +msgid "Show state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:118 +msgid "Signal" +msgstr "" + #: plugins/lime-plugin-align/src/alignPage.js:52 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:64 msgid "Signal lost" @@ -909,6 +1454,50 @@ msgstr "" msgid "Size" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:59 +msgid "Some nodes are not ready" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:209 +msgid "Some nodes are not ready for upgrade <0/>Check node details for more info" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:18 +msgid "Some nodes are still downloading the firmware<0/>check network page for more information" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:85 +msgid "Some nodes don't upgraded properly" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:226 +msgid "Some nodes have errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx:36 +msgid "Some nodes have errors:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:91 +msgid "Source IP" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:197 +msgid "Start" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:189 +msgid "Start mesh upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:74 +msgid "Start mesh wide firmware upgrade again" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:59 +msgid "Start mesh wide upgrade" +msgstr "" + #: plugins/lime-plugin-rx/src/rxMenu.js:9 msgid "Status" msgstr "Stato" @@ -917,7 +1506,12 @@ msgstr "Stato" msgid "Status: {0}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:42 +#: src/components/Modal/Modal.tsx:60 +#: src/components/Modal/Modal.tsx:126 +msgid "Success" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:78 msgid "System" msgstr "Sistema" @@ -933,6 +1527,14 @@ msgstr "" msgid "The are not mesh interfaces available" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:88 +msgid "The become main node process is starting on this node" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:135 +msgid "The difference between chains is too big" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:113 msgid "The download failed" msgstr "" @@ -941,6 +1543,22 @@ msgstr "" msgid "The firmware is being upgraded..." msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:52 +msgid "The firmware seems to be installed successfully. Confirm that the node is working properly or will be downgraded to the previous version" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:20 +msgid "The following nodes are not located or have not reference state. Please, set their location to see them on the map:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:72 +msgid "The following shared states packages have errors. Are they installed or properly initialized?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:39 +msgid "The following shared states packages have not data set" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:115 msgid "The hotspot couldn’t be found, please review the instructions above." msgstr "" @@ -949,6 +1567,10 @@ msgstr "" msgid "The name should have at least 3 characters" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:77 +msgid "The node is down" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/password.js:60 msgid "The password should have at least 8 characters" msgstr "" @@ -974,6 +1596,14 @@ msgstr "" msgid "The shared password has been chosen by the community when the network was created. You can ask other community members for it." msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:123 +msgid "The signal is X below the reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:44 +msgid "The upgrade is scheduled" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:9 msgid "The upgrade should be done" msgstr "" @@ -994,6 +1624,10 @@ msgstr "" msgid "These are the nodes associated on this radio" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:384 +msgid "This Link is not registered on the reference state" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:35 msgid "This device does not support secure rollback to previous version if something goes wrong" msgstr "" @@ -1006,14 +1640,87 @@ msgstr "" msgid "This field is required" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:92 +msgid "This is a main node" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:389 +msgid "This link has errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:169 +msgid "This link seems down" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:73 +msgid "This link seems down, remove them from the reference state?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:111 +msgid "This macs are not on the actual state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:129 +msgid "This macs are not on the reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:73 +msgid "This node aborted" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:86 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:21 +msgid "This node aborted successfully" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:41 +msgid "This node es ready for upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:20 +msgid "This node has an error" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:69 +msgid "This node has an error!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:36 +msgid "This node is downloading a new firmware" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:225 +msgid "This node is not registered on the reference state" +msgstr "" + #: plugins/lime-plugin-metrics/src/components/showPathButton.js:16 msgid "This node is the gateway" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:36 +msgid "This node seems down" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:24 +msgid "This node seems down, remove them from the reference state?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:21 +msgid "This node version<0/>{0}" +msgstr "" + #: plugins/lime-plugin-align/src/alignPage.js:119 msgid "This radio is not associated with other nodes" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:63 +msgid "This will set the reference state of this link:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:104 +msgid "This will the abort current upgrade process on all nodes. Are you sure you want to proceed?" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:120 msgid "This your last working path to the Internet" msgstr "" @@ -1031,17 +1738,37 @@ msgid "To enable remote access an internet connection is needed" msgstr "" #: plugins/lime-plugin-rx/src/rxPage.js:103 -msgid "Traffic" -msgstr "Traffico di dati" +#~ msgid "Traffic" +#~ msgstr "Traffico di dati" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:78 +msgid "Traffic:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:248 +msgid "Try last step again" +msgstr "" #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:12 msgid "Try reloading the app" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:148 +msgid "TxRate" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:100 msgid "Unknown error" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:226 +msgid "Unknown link type" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:16 +msgid "Updating shared state {0}" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:229 msgid "Upgrade" msgstr "" @@ -1050,6 +1777,22 @@ msgstr "" msgid "Upgrade Now" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:74 +msgid "Upgrade all network nodes at once. This proces will take a while and will require user interaction." +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:16 +msgid "Upgrade is scheduled!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:17 +msgid "Upgrade scheduled" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:60 +msgid "Upgrade successful" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:85 msgid "Upgrade to lastest firmware version" msgstr "" @@ -1059,11 +1802,17 @@ msgstr "" msgid "Upgrade to {versionName}" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:12 +msgid "Upgraded!<0/>Awaiting confirmation" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:181 msgid "Upload firmware image from your device" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:45 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:72 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:76 +#: plugins/lime-plugin-rx/src/sections/system.tsx:45 msgid "Uptime" msgstr "Tempo di attività" @@ -1071,10 +1820,18 @@ msgstr "Tempo di attività" msgid "Use vouchers for access" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:49 +msgid "Value" +msgstr "" + #: plugins/lime-plugin-changeNode/src/changeNodePage.js:75 msgid "Visit" msgstr "" +#: plugins/lime-plugin-rx/src/components/footer.tsx:33 +msgid "Visit <0>docs.altermundi.net" +msgstr "" + #: plugins/lime-plugin-changeNode/src/changeNodeMenu.js:9 #: plugins/lime-plugin-changeNode/src/changeNodePage.js:50 msgid "Visit a neighboring node" @@ -1100,6 +1857,10 @@ msgstr "" msgid "Vouchers can be used to limit access through the Community Portal to those who have an authorization code" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:37 +msgid "Wait until the download is finished!" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:54 msgid "Welcome to LimeApp" msgstr "" @@ -1112,12 +1873,24 @@ msgstr "" msgid "When reloading the app you will be asked to confirm the upgrade, otherwise it will be reverted" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:78 +msgid "Wifi Links" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:80 +msgid "Wifi Links Reference" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:34 #: plugins/lime-plugin-node-admin/src/screens/password.js:45 #: plugins/lime-plugin-node-admin/src/screens/password.js:105 msgid "Wifi Password" msgstr "" +#: plugins/lime-plugin-rx/src/sections/wired.tsx:62 +msgid "Wired connections" +msgstr "" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:121 msgid "With radio {fromRadio} alignin with" msgstr "" @@ -1167,31 +1940,34 @@ msgstr "" msgid "You should try to connect to the network {wifiSsid}." msgstr "" +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:113 +msgid "Your Alignment" +msgstr "" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:74 msgid "Your node has no internet connection" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:207 #: plugins/lime-plugin-locate/src/locatePage.tsx:225 msgid "cancel" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:193 #: plugins/lime-plugin-locate/src/locatePage.tsx:211 msgid "confirm location" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:209 #: plugins/lime-plugin-locate/src/locatePage.tsx:227 msgid "edit location" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:199 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:54 +msgid "for the following nodes: {nodes}" +msgstr "" + #: plugins/lime-plugin-locate/src/locatePage.tsx:217 msgid "hide community" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:212 #: plugins/lime-plugin-locate/src/locatePage.tsx:230 msgid "locate my node" msgstr "" @@ -1200,7 +1976,6 @@ msgstr "" msgid "more than a minute ago" msgstr "" -#: plugins/lime-plugin-locate/src/locateMap.tsx:201 #: plugins/lime-plugin-locate/src/locatePage.tsx:219 msgid "show community" msgstr "" @@ -1217,23 +1992,33 @@ msgstr "" msgid "{0, plural, =0 {No one has joined yet.} one {One person has joined.} other {# people have joined.}}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:20 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:66 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:70 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:74 +msgid "{0}" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:22 msgid "{days, plural, one {# day} other {# days}}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:23 +#: plugins/lime-plugin-rx/src/sections/system.tsx:25 msgid "{hours, plural, one {# hour} other {# hours}}" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:26 +#: plugins/lime-plugin-rx/src/sections/system.tsx:28 msgid "{mins, plural, one {# minute} other {# minutes}}" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:18 +msgid "{nodesToBeUpgraded} of {totalNodes} will be upgraded" +msgstr "" + #: plugins/lime-plugin-align/src/components/secondsAgo.js:23 msgid "{secondsAmount} seconds ago" msgstr "" -#: plugins/lime-plugin-rx/src/rxPage.js:29 +#: plugins/lime-plugin-rx/src/sections/system.tsx:31 msgid "{secs, plural, one {# second} other {# seconds}}" msgstr "" diff --git a/i18n/pt/messages.po b/i18n/pt/messages.po index c80e598ed..1e3fcbd0a 100644 --- a/i18n/pt/messages.po +++ b/i18n/pt/messages.po @@ -13,6 +13,18 @@ msgstr "" "Language-Team: \n" "Plural-Forms: \n" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:46 +msgid "(Main Node) {descriptionMsg}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/NodeMarker.tsx:40 +msgid "(new)" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:26 +msgid "10 of 12 node are ready to update" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:67 msgid "A new firmware version has been released" msgstr "Uma nova versão do firmware foi lançada" @@ -21,6 +33,19 @@ msgstr "Uma nova versão do firmware foi lançada" msgid "A reboot is needed to apply changes" msgstr "É preciso reiniciar para aplicar as modificações" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:109 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:256 +msgid "Abort" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:102 +msgid "Abort current mesh wide upgrade?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:23 +msgid "Aborting" +msgstr "" + #: plugins/lime-plugin-pirania/src/piraniaMenu.js:9 msgid "Access Vouchers" msgstr "Vouchers de Acesso" @@ -49,6 +74,23 @@ msgstr "Prazo de Ativação: {0}" msgid "Active" msgstr "Ativo" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:80 +msgid "Add" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:101 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:78 +msgid "Add new section" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:92 +msgid "Added section {0} - {1}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:46 +msgid "After a time the upgrade will be performed" +msgstr "" + #: plugins/lime-plugin-align/src/alignMenu.js:9 msgid "Align" msgstr "Alinhar" @@ -57,10 +99,38 @@ msgstr "Alinhar" msgid "All Vouchers" msgstr "Todos os Vouchers" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:54 +msgid "All nodes are ready" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:80 +msgid "All nodes are upgraded successfully" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:232 +msgid "All nodes scheduled successful" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:87 +msgid "Are you sure you want to confirm the upgrade? <0/>Check node list to see the network status" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:66 +msgid "Are you sure you want to reboot this node? This action will disconnect the node from the network for a few minutes. <0/>Add shared password or let it empty if no password is set." +msgstr "" + #: src/containers/RebootPage/RebootPage.js:39 msgid "Are you sure you want to reboot?" msgstr "Você tem certeza que quer reiniciar?" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:61 +msgid "Are you sure you want to start mesh wide upgrade? <0/>Check node list to see the network status" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:24 +msgid "Are you sure you want to {title} the <0>{prop} property?" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:24 msgid "Are you sure?" msgstr "É isso mesmo?" @@ -88,6 +158,22 @@ msgstr "Nó que cadastrou: {author_node}" msgid "Available" msgstr "Disponível" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:54 +msgid "Await until it reboots" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:50 +msgid "Awaiting confirmation" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:86 +msgid "Babel Links" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:88 +msgid "Babel Links Reference" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:22 msgid "Back" msgstr "" @@ -96,10 +182,22 @@ msgstr "" msgid "Background Color" msgstr "Cor de fundo" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:82 +msgid "Batman Links" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:84 +msgid "Batman Links Reference" +msgstr "" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:41 msgid "Best signal" msgstr "Melhor sinal" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:65 +msgid "Board" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:96 msgid "Calculating network path" msgstr "Calculando o caminho da rede" @@ -107,6 +205,8 @@ msgstr "Calculando o caminho da rede" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:83 #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:150 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:14 +#: src/components/Modal/Modal.tsx:62 +#: src/components/Modal/Modal.tsx:128 #: src/components/banner/index.js:20 msgid "Cancel" msgstr "Cancelar" @@ -131,6 +231,10 @@ msgstr "O Radio 0 não pode ser utilizado, eles está em uso para os links mesh. msgid "Cellphone Instructions" msgstr "Instruções para celular" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:132 +msgid "Chains" +msgstr "" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:76 msgid "Change" msgstr "Mudar" @@ -140,9 +244,18 @@ msgid "Change Shared Password" msgstr "Mudar senha compartilhada" #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:123 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:143 msgid "Channel" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:22 +msgid "Check if network is working properly and confirm the upgrade<0/>If not confirmed, the upgrade will be rolled back after a while" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:91 +msgid "Check<0/>Alignment" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:100 msgid "Checking connection" msgstr "Verificando conexão" @@ -173,6 +286,10 @@ msgstr "Clique em Encerrar Sessão para finalizar a sessão de suporte remoto. N msgid "Click at Show Console to follow the remote support session." msgstr "Clique em Mostrar Console para acompanhar a sessão de suporte remoto." +#: src/components/Modal/Modal.tsx:205 +msgid "Close" +msgstr "" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:170 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:183 msgid "Close Session" @@ -205,13 +322,46 @@ msgid "Configure your new community network" msgstr "Configure sua nova rede mesh" #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:11 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:241 msgid "Confirm" msgstr "Confirmar" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:82 +msgid "Confirm mesh wide upgrade for all nodes on the network" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:240 +msgid "Confirm upgrade on all nodes" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:18 +msgid "Confirmation pending" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:19 +msgid "Confirmed" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:19 +msgid "Confirmed with some errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:15 +msgid "Confirmed!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:63 +msgid "Confirming all upgraded nodes" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:127 msgid "Congratulations" msgstr "Parabéns" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:62 +msgid "Congratulations, this node was upgraded and confirmed successfully" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:37 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:199 @@ -235,6 +385,11 @@ msgstr "Conexão com o celular" msgid "Connection to the internet" msgstr "Conexão com a internet" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:34 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:90 +msgid "Continue" +msgstr "" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:134 #: plugins/lime-plugin-pirania/src/screens/voucherList.js:122 msgid "Create" @@ -273,6 +428,30 @@ msgstr "Data de criação: {0}" msgid "Currently your node has version:" msgstr "Atualmente seu nó usa a versão:" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:44 +msgid "Delete" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:43 +msgid "Delete property" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:206 +msgid "Delete this this node from reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:372 +msgid "Delete this {0}<0/>from reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:99 +msgid "Deleted {keyString}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:64 +msgid "Deleted {name} - {0}" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/editVoucher.js:28 msgid "Description" msgstr "Descrição" @@ -282,10 +461,15 @@ msgstr "Descrição" msgid "Description: {name}" msgstr "Descrição: {name}" -#: plugins/lime-plugin-rx/src/rxPage.js:51 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:89 +#: plugins/lime-plugin-rx/src/sections/system.tsx:48 msgid "Device" msgstr "Dispositivo" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:125 +msgid "Diagnose" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:54 #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:72 #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigItem.tsx:20 @@ -298,14 +482,31 @@ msgstr "Desativado" msgid "Don't show this message again" msgstr "Não mostrar essa mensagem novamente" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:53 +msgid "Done" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:96 msgid "Download" msgstr "Baixar" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:183 +msgid "Download remote firmware<0/>to start mesh upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:50 +msgid "Downloaded version<0/>{0}" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:103 +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:35 msgid "Downloading" msgstr "Baixando" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:15 +msgid "Downloading new firmware" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/postCreate.js:18 #: plugins/lime-plugin-pirania/src/screens/voucher.js:59 msgid "Duration: is permanent" @@ -316,6 +517,7 @@ msgstr "Duração: permanente" msgid "Duration: {days, plural, one {# day} other {# days}}" msgstr "Duração: {dias, plural, one {# dia} other {# dias}}" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:51 #: plugins/lime-plugin-pirania/src/screens/voucher.js:90 msgid "Edit" msgstr "Editar" @@ -324,10 +526,22 @@ msgstr "Editar" msgid "Edit Voucher" msgstr "Editar Voucher" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:50 +msgid "Edit property" +msgstr "" + #: plugins/lime-plugin-pirania/nodeAdmin/PortalConfigPage.js:50 msgid "Edit wellcome screen" msgstr "Editar tela de boas vindas" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:123 +msgid "Edited {keyString}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:47 +msgid "Edited {name} - {0}" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:25 msgid "Enable Community Roaming AP" msgstr "Ativar Rede AP (Roaming)" @@ -361,6 +575,10 @@ msgstr "Encriptação: {encryptionMethod}" msgid "Error" msgstr "Erro" +#: src/components/toast/toasts.tsx:13 +msgid "Error connecting with {nodeInfo}, is node up?" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:61 msgid "Error destination network is not configured yet" msgstr "" @@ -377,6 +595,14 @@ msgstr "" msgid "Error getting scan results" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx:41 +msgid "Error loading leaflet" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:85 +msgid "Error performing reboot: {error}" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:40 msgid "Error reaching hostname!" msgstr "" @@ -386,6 +612,14 @@ msgstr "" msgid "Error retrieving associated list" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:43 +msgid "Error retrieving the status, is this node outdated?" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:101 +msgid "Error retrieving<0/>last internet path" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanList.js:155 msgid "Error scanning networks" msgstr "" @@ -394,14 +628,31 @@ msgstr "" msgid "Error setting network" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:355 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:189 +msgid "Error setting new reference state!" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/ScanPage.tsx:83 msgid "Error stopping scan" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx:12 +msgid "Error!" +msgstr "" + #: plugins/lime-plugin-node-admin/src/layouts/configPageLayout.tsx:55 msgid "Error: Not Saved" msgstr "Erro: Não Salvo" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:35 +msgid "Errors found getting mesh info!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:32 +msgid "Everything is up to date!" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:66 msgid "Expiration date: {0}" msgstr "Data de expiração: {0}" @@ -422,7 +673,7 @@ msgstr "" #: plugins/lime-plugin-align/src/alignPage.js:37 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:80 -#: plugins/lime-plugin-rx/src/rxPage.js:93 +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:67 msgid "Fetching name" msgstr "Pegando nome" @@ -435,10 +686,23 @@ msgid "Filter by" msgstr "Filtrar por" #: plugins/lime-plugin-firmware/src/firmwareMenu.js:9 -#: plugins/lime-plugin-rx/src/rxPage.js:58 +#: plugins/lime-plugin-rx/src/sections/system.tsx:49 msgid "Firmware" msgstr "Firmware" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:40 +msgid "Firmware download and verified" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:16 +msgid "Firmware downloaded" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:80 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:69 +msgid "Firmware version" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:151 msgid "From" msgstr "De" @@ -484,8 +748,16 @@ msgid "I don't know the shared password" msgstr "Não sei a senha compartilhada" #: plugins/lime-plugin-rx/src/rxPage.js:181 -msgid "IP Addresses" -msgstr "Endereços IP" +#~ msgid "IP Addresses" +#~ msgstr "Endereços IP" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:85 +msgid "IPv4" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:86 +msgid "IPv6" +msgstr "" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:73 msgid "If network has been already created, look it up to join" @@ -503,15 +775,39 @@ msgstr "Se você invalidar este voucher, ninguém mais poderá utilizá-lo. E is msgid "If your community network has local services, you can point a link to them." msgstr "Se a sua rede comunitária tem serviços locais, você pode colocar o link para eles." +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:57 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:86 +msgid "Iface" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:222 +msgid "In the reference state this node is on" +msgstr "" + #: plugins/lime-plugin-rx/src/rxPage.js:98 -msgid "Interface" -msgstr "Interface" +#~ msgid "Interface" +#~ msgstr "Interface" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:72 +msgid "Interface:" +msgstr "" + +#: plugins/lime-plugin-rx/src/components/internetPathChart.tsx:165 +msgid "Internet" +msgstr "" #: plugins/lime-plugin-metrics/src/components/internetStatus.js:10 -#: plugins/lime-plugin-rx/src/rxPage.js:149 msgid "Internet connection" msgstr "Conexão à Internet" +#: plugins/lime-plugin-rx/src/components/internetStatus.tsx:17 +msgid "Internet<0/>connection" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:16 +msgid "Invalid Nodes" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/voucher.js:97 msgid "Invalidate" msgstr "Invalidar" @@ -522,6 +818,10 @@ msgstr "Invalidar" msgid "Invalidated" msgstr "Invalidado" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:73 +msgid "Ip" +msgstr "" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:75 msgid "Is permanent" msgstr "É permanente" @@ -539,15 +839,31 @@ msgstr "Está ativado por padrão na {communityName}" msgid "It must start with https:// or http://" msgstr "Deve-se iniciar com https:// ou http://" +#: plugins/lime-plugin-rx/src/components/footer.tsx:22 +msgid "Join <0>foro.librerouter.org" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:72 msgid "Join the mesh" msgstr "Se junte à rede" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:44 +msgid "Key" +msgstr "" + #: plugins/lime-plugin-align/src/alignPage.js:55 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:134 msgid "Last packet" msgstr "Último pacote" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:60 +msgid "Last seen" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:29 +msgid "Last update: 30 second ago" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:120 msgid "Link Title" msgstr "Titulo do link" @@ -556,18 +872,34 @@ msgstr "Titulo do link" msgid "Link URL" msgstr "Link URL" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:181 +msgid "Link from <0>{0} to <1>{1}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:248 +msgid "Link {0} {1}" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:106 msgid "Load last known Internet path" msgstr "Calculando o caminho da rede" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:84 +msgid "Loading <0/>last internet path..." +msgstr "" + #: plugins/lime-plugin-rx/src/rxPage.js:128 -msgid "Loading node status..." -msgstr "Carregando o status do nó..." +#~ msgid "Loading node status..." +#~ msgstr "Carregando o status do nó..." #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:111 msgid "Local services link" msgstr "Link dos serviços locais" +#: plugins/lime-plugin-locate/src/locateMenu.js:9 +msgid "Locate" +msgstr "" + #: src/containers/SharedPasswordLogin/sharedPasswordLogin.tsx:81 msgid "Logging in" msgstr "Entrando" @@ -576,6 +908,14 @@ msgstr "Entrando" msgid "Login" msgstr "Entrar" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:94 +msgid "Macs ({0})" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:106 +msgid "Macs not found ({0})" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:57 msgid "Main Text" msgstr "Texto principal" @@ -584,7 +924,7 @@ msgstr "Texto principal" msgid "Manage Vouchers" msgstr "Gerenciar Vouchers" -#: plugins/lime-plugin-locate/src/locateMenu.js:9 +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:128 msgid "Map" msgstr "Mapa" @@ -596,6 +936,30 @@ msgstr "Max. {length} caracteres" msgid "Measuring links" msgstr "Links de medição" +#: plugins/lime-plugin-mesh-wide/src/meshWideMenu.tsx:9 +msgid "Mesh Map" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx:9 +msgid "Mesh Wide Upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:16 +msgid "Mesh upgrade confirmed successfully" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:20 +msgid "Mesh upgrade confirmed with some errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx:20 +msgid "Mesh wide config" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:10 +msgid "Mesh wide upgrade started!" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsMenu.js:9 msgid "Metrics" msgstr "Métrica" @@ -613,17 +977,62 @@ msgid "More than 10 characters" msgstr "Mais de 10 caracteres" #: plugins/lime-plugin-rx/src/rxPage.js:80 -msgid "Most Active" -msgstr "Mais Ativos" +#~ msgid "Most Active" +#~ msgstr "Mais Ativos" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:60 +msgid "Most active link" +msgstr "" #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:129 msgid "Must select a valid hostname" msgstr "" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:73 +msgid "Name" +msgstr "" + +#: plugins/lime-plugin-rx/src/components/footer.tsx:19 +msgid "Need support?" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:82 msgid "Network Name: {ssid}" msgstr "Nome da Rede: {ssid}" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:126 +msgid "New Macs ({0})" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:36 +msgid "New available version:<0/>{0}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx:85 +msgid "New link" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:351 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:184 +msgid "New reference state set!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:64 +msgid "New version available!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:33 +msgid "No new version available is found" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx:11 +msgid "No new version available!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx:23 +msgid "No nodes present on the <0/>mesh wide upgrade state yet!" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:35 msgid "No password" msgstr "Sem senha" @@ -632,6 +1041,10 @@ msgstr "Sem senha" msgid "No scan result" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:14 +msgid "No upgrade in progres" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:30 #: src/containers/RebootPage/RebootPage.js:45 msgid "No, cancel" @@ -642,12 +1055,24 @@ msgstr "Não, cancelar" msgid "Node Configuration" msgstr "Configurações do Nó" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:74 +msgid "Node Info" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:76 +msgid "Node Info Reference" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:20 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:43 #: plugins/lime-plugin-node-admin/src/screens/hostname.js:48 msgid "Node Name" msgstr "Nome do Nó" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:53 +msgid "Node is upgrading" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:71 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/components/testBoxes.js:99 msgid "Not Connected" @@ -699,6 +1124,10 @@ msgstr "" msgid "Or upgrade to latest release" msgstr "Ou atualize para última versão do firmware" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:94 +msgid "Other nodes will download the firmware from it" +msgstr "" + #: plugins/lime-plugin-metrics/src/components/box/index.js:110 msgid "Packet loss" msgstr "Perda de pacotes" @@ -712,6 +1141,10 @@ msgstr "Senha" msgid "Password: {password}" msgstr "Senha: {password}" +#: plugins/lime-plugin-rx/src/sections/internetPath.tsx:119 +msgid "Path to Internet" +msgstr "" + #: plugins/lime-plugin-pirania/src/components/voucherListItem.js:58 msgid "Permanent" msgstr "Permanent" @@ -759,14 +1192,37 @@ msgstr "Coloque a senha novamente" msgid "Re-enter the shared password" msgstr "Coloque a senha compartilhada novamente" +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:196 +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:207 +msgid "Ready to start mesh wide upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:67 +msgid "Ready to start mesh wide<0/>firmware upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:95 #: src/containers/RebootBanner/rebootBanner.js:17 msgid "Reboot" msgstr "Reiniciar" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:63 +msgid "Reboot node {0}" +msgstr "" + #: src/containers/RebootPage/RebootPage.js:25 msgid "Rebooting" msgstr "Reiniciando" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:35 +msgid "Reference State is not set" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:387 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:220 +msgid "Reference is not set or has errors" +msgstr "" + #: plugins/lime-plugin-ground-routing/src/groundRoutingPage.js:32 msgid "Reload" msgstr "Recarregar" @@ -779,6 +1235,14 @@ msgstr "Recarregar a página" msgid "Remote Support" msgstr "Suporte Remoto" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:67 +msgid "Remove this {0} from the reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:21 +msgid "Remove {nodeName} from the reference state" +msgstr "" + #: src/components/form/index.js:17 msgid "Required" msgstr "Requisitado" @@ -799,6 +1263,15 @@ msgstr "Reverter" msgid "Reverting to previous version" msgstr "Revertendo para versão prévia" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:151 +msgid "RxRate" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:380 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:218 +msgid "Same status as in the reference state" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hostname.js:84 #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:49 #: plugins/lime-plugin-node-admin/src/screens/password.js:74 @@ -821,6 +1294,30 @@ msgstr "Salvo" msgid "Scanning for existing networks" msgstr "Buscando por redes existentes" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:20 +msgid "Schedule" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:56 +msgid "Schedule a firmware upgrade for all nodes on the network" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:220 +msgid "Schedule again" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:214 +msgid "Schedule upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:46 +msgid "Schedule upgrade to all available nodes" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:44 +msgid "Scheduling upgrade" +msgstr "" + #: plugins/lime-plugin-pirania/src/screens/voucherList.js:60 msgid "Search by" msgstr "Procurar por" @@ -858,14 +1355,46 @@ msgstr "Selecione um nó" msgid "Selected network to join" msgstr "" +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:25 +msgid "Sending abort message to this node. The abort order will be propagated to all nodes." +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:62 +msgid "Sending confirmation" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/SelectForm.js:106 msgid "Set network" msgstr "Juntar-se à rede" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:204 +msgid "Set reference state for this node" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:58 +msgid "Set reference state for this {0}?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:363 +msgid "Set reference state for this<0/> {0}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:17 +msgid "Set reference state for {nodeName}" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:18 +msgid "Set the reference state for this node." +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/Setting.js:80 msgid "Setting network" msgstr "Configurando a rede" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:86 +msgid "Setting up main node" +msgstr "" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:82 msgid "Setting up new password" msgstr "Configurando uma nova senha" @@ -895,11 +1424,27 @@ msgstr "Senha Compartilhada" msgid "Shared Password changed successfully" msgstr "Senha compartilhada alterada com sucesso" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:68 +msgid "Shared state error" +msgstr "" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:156 #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:165 msgid "Show Console" msgstr "Mostrar console" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:65 +msgid "Show nodes" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:57 +msgid "Show state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:118 +msgid "Signal" +msgstr "" + #: plugins/lime-plugin-align/src/alignPage.js:52 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:64 msgid "Signal lost" @@ -909,6 +1454,50 @@ msgstr "Sinal perdido" msgid "Size" msgstr "Tamanho" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:59 +msgid "Some nodes are not ready" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:209 +msgid "Some nodes are not ready for upgrade <0/>Check node details for more info" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:18 +msgid "Some nodes are still downloading the firmware<0/>check network page for more information" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:85 +msgid "Some nodes don't upgraded properly" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:226 +msgid "Some nodes have errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx:36 +msgid "Some nodes have errors:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:91 +msgid "Source IP" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:197 +msgid "Start" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:189 +msgid "Start mesh upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:74 +msgid "Start mesh wide firmware upgrade again" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:59 +msgid "Start mesh wide upgrade" +msgstr "" + #: plugins/lime-plugin-rx/src/rxMenu.js:9 msgid "Status" msgstr "Status" @@ -917,7 +1506,12 @@ msgstr "Status" msgid "Status: {0}" msgstr "Estado: {0}" -#: plugins/lime-plugin-rx/src/rxPage.js:42 +#: src/components/Modal/Modal.tsx:60 +#: src/components/Modal/Modal.tsx:126 +msgid "Success" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:78 msgid "System" msgstr "Sistema" @@ -933,6 +1527,14 @@ msgstr "O Portal da Comunidade permite que uma tela de boas-vindas seja exibida msgid "The are not mesh interfaces available" msgstr "Não a interfaces de malha disponíveis" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:88 +msgid "The become main node process is starting on this node" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:135 +msgid "The difference between chains is too big" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:113 msgid "The download failed" msgstr "O download falhou" @@ -941,6 +1543,22 @@ msgstr "O download falhou" msgid "The firmware is being upgraded..." msgstr "O firmware está sendo atualizado." +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:52 +msgid "The firmware seems to be installed successfully. Confirm that the node is working properly or will be downgraded to the previous version" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:20 +msgid "The following nodes are not located or have not reference state. Please, set their location to see them on the map:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:72 +msgid "The following shared states packages have errors. Are they installed or properly initialized?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:39 +msgid "The following shared states packages have not data set" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/hotspot/src/hotspotPage.js:115 msgid "The hotspot couldn’t be found, please review the instructions above." msgstr "O ponto de acesso não pode ser encontrado, favor reveja a situação acima." @@ -949,6 +1567,10 @@ msgstr "O ponto de acesso não pode ser encontrado, favor reveja a situação ac msgid "The name should have at least 3 characters" msgstr "O nome deve ter pelo menos 3 caracteres" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:77 +msgid "The node is down" +msgstr "" + #: plugins/lime-plugin-node-admin/src/screens/password.js:60 msgid "The password should have at least 8 characters" msgstr "A senha deve ter pelo menos 8 caracteres" @@ -974,6 +1596,14 @@ msgstr "A imagem selecionada não é válida para este dispositivo" msgid "The shared password has been chosen by the community when the network was created. You can ask other community members for it." msgstr "A senha compartilhada foi escolhida pela comunidade ao iniciar a rede. Pergunte sobre ela a outros membros." +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:123 +msgid "The signal is X below the reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:44 +msgid "The upgrade is scheduled" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:9 msgid "The upgrade should be done" msgstr "A atualização deve estar pronta" @@ -994,6 +1624,10 @@ msgstr "Não a uma sessão de suporte remoto aberta. Clique em Criar Sessão par msgid "These are the nodes associated on this radio" msgstr "Esses são os nós associados a este rádio" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:384 +msgid "This Link is not registered on the reference state" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:35 msgid "This device does not support secure rollback to previous version if something goes wrong" msgstr "Neste dispositivo não se pode revertar a atualização em caso de erros" @@ -1006,14 +1640,87 @@ msgstr "Neste dispositivo se pode revertar a atualização em caso de erros" msgid "This field is required" msgstr "Este campo é necessário" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:92 +msgid "This is a main node" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:389 +msgid "This link has errors" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:169 +msgid "This link seems down" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:73 +msgid "This link seems down, remove them from the reference state?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:111 +msgid "This macs are not on the actual state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:129 +msgid "This macs are not on the reference state" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:73 +msgid "This node aborted" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:86 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:21 +msgid "This node aborted successfully" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:41 +msgid "This node es ready for upgrade" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:20 +msgid "This node has an error" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:69 +msgid "This node has an error!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:36 +msgid "This node is downloading a new firmware" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:225 +msgid "This node is not registered on the reference state" +msgstr "" + #: plugins/lime-plugin-metrics/src/components/showPathButton.js:16 msgid "This node is the gateway" msgstr "Esse nó não é o gateway" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:36 +msgid "This node seems down" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:24 +msgid "This node seems down, remove them from the reference state?" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx:21 +msgid "This node version<0/>{0}" +msgstr "" + #: plugins/lime-plugin-align/src/alignPage.js:119 msgid "This radio is not associated with other nodes" msgstr "Esse rádio não está conectado a outros nós" +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:63 +msgid "This will set the reference state of this link:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:104 +msgid "This will the abort current upgrade process on all nodes. Are you sure you want to proceed?" +msgstr "" + #: plugins/lime-plugin-metrics/src/metricsPage.tsx:120 msgid "This your last working path to the Internet" msgstr "Esse foi o último caminho para Internet que funcionou" @@ -1031,17 +1738,37 @@ msgid "To enable remote access an internet connection is needed" msgstr "Para ativar o acesso remoto é preciso uma conexão com a internet" #: plugins/lime-plugin-rx/src/rxPage.js:103 -msgid "Traffic" -msgstr "Tráfego" +#~ msgid "Traffic" +#~ msgstr "Tráfego" + +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:78 +msgid "Traffic:" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:248 +msgid "Try last step again" +msgstr "" #: plugins/lime-plugin-firmware/src/upgradingPage/upgradingPage.js:12 msgid "Try reloading the app" msgstr "Tente recarregar o aplicativo" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:148 +msgid "TxRate" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:100 msgid "Unknown error" msgstr "" +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:226 +msgid "Unknown link type" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:16 +msgid "Updating shared state {0}" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:229 msgid "Upgrade" msgstr "Atualizar" @@ -1050,6 +1777,22 @@ msgstr "Atualizar" msgid "Upgrade Now" msgstr "Atualizar agora" +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:74 +msgid "Upgrade all network nodes at once. This proces will take a while and will require user interaction." +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:16 +msgid "Upgrade is scheduled!" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:17 +msgid "Upgrade scheduled" +msgstr "" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:60 +msgid "Upgrade successful" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:85 msgid "Upgrade to lastest firmware version" msgstr "Atualizar para última versão do firmware" @@ -1059,11 +1802,17 @@ msgstr "Atualizar para última versão do firmware" msgid "Upgrade to {versionName}" msgstr "Atualizar para {versionName}" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:12 +msgid "Upgraded!<0/>Awaiting confirmation" +msgstr "" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:181 msgid "Upload firmware image from your device" msgstr "Carregar uma imagem de firmware do seu dispositivo" -#: plugins/lime-plugin-rx/src/rxPage.js:45 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:72 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:76 +#: plugins/lime-plugin-rx/src/sections/system.tsx:45 msgid "Uptime" msgstr "Tempo de atividade" @@ -1071,10 +1820,18 @@ msgstr "Tempo de atividade" msgid "Use vouchers for access" msgstr "Use vouchers de acesso" +#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:49 +msgid "Value" +msgstr "" + #: plugins/lime-plugin-changeNode/src/changeNodePage.js:75 msgid "Visit" msgstr "Visitar" +#: plugins/lime-plugin-rx/src/components/footer.tsx:33 +msgid "Visit <0>docs.altermundi.net" +msgstr "" + #: plugins/lime-plugin-changeNode/src/changeNodeMenu.js:9 #: plugins/lime-plugin-changeNode/src/changeNodePage.js:50 msgid "Visit a neighboring node" @@ -1100,6 +1857,10 @@ msgstr "Lista de vouchers" msgid "Vouchers can be used to limit access through the Community Portal to those who have an authorization code" msgstr "Os vouchers podem ser utilizados para limitar o acesso através do Portal Comunitário para quem possuir um código de autorização" +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:37 +msgid "Wait until the download is finished!" +msgstr "" + #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:54 msgid "Welcome to LimeApp" msgstr "" @@ -1112,12 +1873,24 @@ msgstr "Tela de Boas Vindas" msgid "When reloading the app you will be asked to confirm the upgrade, otherwise it will be reverted" msgstr "Ao carregar o aplicativo, será pedida uma confirmação da atualização, caso não confirme a versão será revertida" +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:78 +msgid "Wifi Links" +msgstr "" + +#: plugins/lime-plugin-mesh-wide/src/lib/utils.ts:80 +msgid "Wifi Links Reference" +msgstr "" + #: plugins/lime-plugin-node-admin/src/nodeAdminPage.js:34 #: plugins/lime-plugin-node-admin/src/screens/password.js:45 #: plugins/lime-plugin-node-admin/src/screens/password.js:105 msgid "Wifi Password" msgstr "Senha do WiFi" +#: plugins/lime-plugin-rx/src/sections/wired.tsx:62 +msgid "Wired connections" +msgstr "" + #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:121 msgid "With radio {fromRadio} alignin with" msgstr "Com rádio %{radio} alinhado com" @@ -1167,31 +1940,34 @@ msgstr "Deve usar a senha compartiada para entrar" msgid "You should try to connect to the network {wifiSsid}." msgstr "Tente conectar-se a rede wifi %{network} para completar a instalação." +#: plugins/lime-plugin-rx/src/sections/alignment.tsx:113 +msgid "Your Alignment" +msgstr "" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:74 msgid "Your node has no internet connection" msgstr "Seu nó não tem conexão com a internet" -#: plugins/lime-plugin-locate/src/locateMap.tsx:207 #: plugins/lime-plugin-locate/src/locatePage.tsx:225 msgid "cancel" msgstr "cancelar" -#: plugins/lime-plugin-locate/src/locateMap.tsx:193 #: plugins/lime-plugin-locate/src/locatePage.tsx:211 msgid "confirm location" msgstr "confirmar localização" -#: plugins/lime-plugin-locate/src/locateMap.tsx:209 #: plugins/lime-plugin-locate/src/locatePage.tsx:227 msgid "edit location" msgstr "editar localização" -#: plugins/lime-plugin-locate/src/locateMap.tsx:199 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/ShowErrorsDetail.tsx:54 +msgid "for the following nodes: {nodes}" +msgstr "" + #: plugins/lime-plugin-locate/src/locatePage.tsx:217 msgid "hide community" msgstr "esconder comunidade" -#: plugins/lime-plugin-locate/src/locateMap.tsx:212 #: plugins/lime-plugin-locate/src/locatePage.tsx:230 msgid "locate my node" msgstr "localizar meu nó" @@ -1200,7 +1976,6 @@ msgstr "localizar meu nó" msgid "more than a minute ago" msgstr "faz mais de um minuto" -#: plugins/lime-plugin-locate/src/locateMap.tsx:201 #: plugins/lime-plugin-locate/src/locatePage.tsx:219 msgid "show community" msgstr "mostrar comunidade" @@ -1217,23 +1992,33 @@ msgstr "a versão prévia" msgid "{0, plural, =0 {No one has joined yet.} one {One person has joined.} other {# people have joined.}}" msgstr "{0, plural, =0 {Ninguém se uniu à sessão.} one {Uma pessoa se uniu à sessão.} other {# pessoas se uniram à sessão.}}" -#: plugins/lime-plugin-rx/src/rxPage.js:20 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:66 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:70 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:74 +msgid "{0}" +msgstr "" + +#: plugins/lime-plugin-rx/src/sections/system.tsx:22 msgid "{days, plural, one {# day} other {# days}}" msgstr "{days, plural, one {# dia} other {# dias}}" -#: plugins/lime-plugin-rx/src/rxPage.js:23 +#: plugins/lime-plugin-rx/src/sections/system.tsx:25 msgid "{hours, plural, one {# hour} other {# hours}}" msgstr "{hours, plural, one {# hora} other {# horas}}" -#: plugins/lime-plugin-rx/src/rxPage.js:26 +#: plugins/lime-plugin-rx/src/sections/system.tsx:28 msgid "{mins, plural, one {# minute} other {# minutes}}" msgstr "{mins, plural, one {# minuto} other {# minutos}}" +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:18 +msgid "{nodesToBeUpgraded} of {totalNodes} will be upgraded" +msgstr "" + #: plugins/lime-plugin-align/src/components/secondsAgo.js:23 msgid "{secondsAmount} seconds ago" msgstr "a {secondsAmount} segundos" -#: plugins/lime-plugin-rx/src/rxPage.js:29 +#: plugins/lime-plugin-rx/src/sections/system.tsx:31 msgid "{secs, plural, one {# second} other {# seconds}}" msgstr "{secs, plural, one {# segundo} other {# segundos}}" From 4b4b3297089da9e4c6d724927f0774516bbe00b8 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 13 Dec 2024 05:45:25 -0500 Subject: [PATCH 20/22] Implement mesh wide config stepper (#459) * chore(meshconfig): implement WizardWrapper * chore(meshconfig): implement useMeshWideConfigState * chore(meshconfig): implement NodesListWrapper * chore(meshconfig): implement NodeInfoListItem * chore(meshconfig): fix mesh types * chore(meshconfig): mock stepper types * chore(meshconfig): implement lime config json parser * chore(meshconfig): implement entry edition * chore(meshconfig): implement delete entry * chore(meshconfig): support list forms * chore(meshconfig): implement add new section * chore(meshconfig): implement add new config section * chore(meshconfig): implement add new list item * chore(meshconfig): fix rebase * chore(meshconfig): implement add new configuration section * chore(meshconfig): bulk bugfix * chore(meshconfig): fix form * chore(meshconfig): fix form layout * chore(meshconfig): fix form * chore(meshconfig): implement is dirty * chore(meshconfig): implement submit * chore(mesh-config): fix query keys * chore(mesh-config): implement api calls * chore(mesh-config): create standarized api call * chore(mesh-config): reimplement parse community file * chore(mesh-config): mock base states * chore(mesh-config): refactor query keys * chore(mesh-config): implement abort * chore(mesh-config): implement mutate new config * chore(mesh-config): improve mesh info messages * chore(mesh-config): implemented schedule safe rebot * chore(mesh-config): implemented confirm * chore(mesh-config): some bulkfix * chore(mesh-config): move common files * chore(mesh-config): implement stepper states * chore(mesh-config): implement applying * chore(mesh-config): fixes key name * chore(mesh-config): implement spanish translation * f_mc: fixes some text related to upgrade * chore(mesh-config): fix parser to ignore \\t * chore(mesh-config): fix full screen modal loading * chore(mesh-config): fix message --------- Co-authored-by: javierbrk --- i18n/es/messages.po | 633 ++++++++++++------ .../src/components/Components.tsx | 24 +- .../src/components/ConfigSection.tsx | 121 ---- .../src/components/FormEdit.tsx | 185 +++++ .../src/components/FormFooter.tsx | 63 ++ .../src/components/FormOption.tsx | 120 ++++ .../src/components/FormSection.tsx | 80 +++ .../src/components/MeshStatus.tsx | 34 - .../src/components/OptionForm.tsx | 135 ---- .../src/components/StepStates.tsx | 108 +++ .../src/components/modals.tsx | 211 +++++- .../src/containers/EditConfiguration.tsx | 39 -- .../src/containers/LimeConfigEditForm.tsx | 87 +++ .../src/containers/NextStepFooter.tsx | 161 +++++ .../src/containers/NodesListPage.tsx | 166 +++++ .../src/containers/StatusPage.tsx | 69 ++ .../src/meshConfigApi.ts | 31 - .../src/meshConfigPage.tsx | 47 +- .../src/meshConfigQueries.tsx | 223 +++++- .../src/meshConfigQueriesKeys.tsx | 15 + .../src/meshConfigTypes.tsx | 55 +- .../src/providers/useMeshConfigProvider.tsx | 192 ++++++ .../src/utils/jsonParser.ts | 71 ++ .../src/components/modals.tsx | 12 +- .../src/components/nodeUpgradeInfo.tsx | 80 +-- .../upgradeState/ConfirmationPending.tsx | 9 +- .../src/components/upgradeState/Confirmed.tsx | 9 +- .../upgradeState/NewVersionAvailable.tsx | 6 +- .../components/upgradeState/NoNewVersion.tsx | 6 +- .../upgradeState/TransactionStarted.tsx | 7 +- .../upgradeState/UpgradeScheduled.tsx | 9 +- .../src/containers/meshWideUpgradeStatus.tsx | 16 +- .../src/containers/nodesList.tsx | 44 +- .../src/meshUpgradeApi.tsx | 37 +- .../src/meshUpgradePage.tsx | 110 +-- .../src/meshUpgradeQueriesKeys.tsx | 14 +- .../src/utils/api.ts | 23 + .../src/utils/divs.tsx | 9 - .../src/utils/upgradeStatusMessages.tsx | 3 +- .../lime-plugin-rx/src/sections/alignment.tsx | 2 +- .../src/sections/internetPath.tsx | 2 +- src/components/Modal/FullScreenModal.tsx | 21 +- src/components/buttons/button.tsx | 24 +- src/components/elements/button.tsx | 57 -- src/components/inputs/InputField.tsx | 25 +- .../mesh-wide-wizard}/ErrorState.tsx | 8 +- .../mesh-wide-wizard}/LoadingPage.tsx | 7 +- .../mesh-wide-wizard/NodeInfoListItem.tsx | 67 ++ .../mesh-wide-wizard/NodesListWrapper.tsx | 47 ++ .../components/mesh-wide-wizard/StepState.tsx | 15 +- .../mesh-wide-wizard/WizardWrapper.tsx | 103 +++ src/components/shared-state/SharedStateApi.ts | 17 +- .../shared-state/SharedStateQueriesKeys.ts | 22 +- .../shared-state/SharedStateTypes.ts | 8 +- src/components/status/statusAndButton.tsx | 16 +- src/utils/meshWideSyncCall.ts | 2 +- src/utils/standarizedApi.ts | 45 ++ 57 files changed, 2750 insertions(+), 1002 deletions(-) delete mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/FormSection.tsx delete mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx delete mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx delete mode 100644 plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx delete mode 100644 plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts create mode 100644 plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider.tsx create mode 100644 plugins/lime-plugin-mesh-wide-config/src/utils/jsonParser.ts delete mode 100644 plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx delete mode 100644 src/components/elements/button.tsx rename {plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState => src/components/mesh-wide-wizard}/ErrorState.tsx (67%) rename {plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState => src/components/mesh-wide-wizard}/LoadingPage.tsx (55%) create mode 100644 src/components/mesh-wide-wizard/NodeInfoListItem.tsx create mode 100644 src/components/mesh-wide-wizard/NodesListWrapper.tsx rename plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx => src/components/mesh-wide-wizard/StepState.tsx (83%) create mode 100644 src/components/mesh-wide-wizard/WizardWrapper.tsx create mode 100644 src/utils/standarizedApi.ts diff --git a/i18n/es/messages.po b/i18n/es/messages.po index 7753c9ab1..5ce05fd26 100644 --- a/i18n/es/messages.po +++ b/i18n/es/messages.po @@ -4,7 +4,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-10 13:08-0300\n" "PO-Revision-Date: \n" -"Last-Translator: \n" +"Last-Translator: Javier Jorge\n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" @@ -13,7 +13,12 @@ msgstr "" "Plural-Forms: \n" "X-Generator: Poedit 3.0.1\n" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:46 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx:75 +msgid "(List)" +msgstr "(Lista)" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:45 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:36 msgid "(Main Node) {descriptionMsg}" msgstr "(Nodo principal) {descriptionMsg}" @@ -21,10 +26,6 @@ msgstr "(Nodo principal) {descriptionMsg}" msgid "(new)" msgstr "(nuevo)" -#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:26 -msgid "10 of 12 node are ready to update" -msgstr "10 de 12 nodos están listos para ser actualizados." - #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:67 msgid "A new firmware version has been released" msgstr "Nueva versión del sistema (firmware) disponible." @@ -33,15 +34,22 @@ msgstr "Nueva versión del sistema (firmware) disponible." msgid "A reboot is needed to apply changes" msgstr "Reinicie el nodo para aplicar cambios." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:109 -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:256 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:159 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:127 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:122 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:163 msgid "Abort" msgstr "Cancelar" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:102 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:152 +msgid "Abort current mesh wide configuration update?" +msgstr "¿Desea interrumpir el cambio de configuración de la red completa?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:115 msgid "Abort current mesh wide upgrade?" msgstr "Interrumpir actualización de la red completa?" +#: plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx:30 #: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:23 msgid "Aborting" msgstr "Cancelando" @@ -74,20 +82,27 @@ msgstr "Plazo de activación: {0}" msgid "Active" msgstr "Activo" -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:80 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:98 msgid "Add" msgstr "Añadir" -#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:101 -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:78 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:86 msgid "Add new section" msgstr "Añadir nueva sección" -#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:92 -msgid "Added section {0} - {1}" -msgstr "Sección añadida {0} - {1}" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:88 +msgid "Add new section for {sectionName}" +msgstr "Añadir una nueva sección para {sectionName}" + +#: plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx:157 +msgid "Added section {0}" +msgstr "Sección agregada {0}" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:46 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:114 +msgid "After a time the new configuration will be installed and the node will reboot" +msgstr "El cambio de configuración iniciará en unos instantes. Este proceso demorará algunos miniutos y el nodo se reiniciará" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:47 msgid "After a time the upgrade will be performed" msgstr "La actualización iniciará en unos instantes. Este proceso demorará algunos miniutos, espere." @@ -99,23 +114,58 @@ msgstr "Alineación" msgid "All Vouchers" msgstr "Todos los cupones" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:54 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:216 +msgid "All nodes applied the configuration" +msgstr "Todos los nodos aplicaron la nueva configuración" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:181 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:52 msgid "All nodes are ready" msgstr "Todos los nodos están listos." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:80 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:83 msgid "All nodes are upgraded successfully" msgstr "Todos los nodos fueron actualizados con éxito!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:232 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:74 +msgid "All nodes have the configuration ready to apply" +msgstr "Todos los nodos tienen la configuración y estan listos para aplicar" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:109 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:139 msgid "All nodes scheduled successful" msgstr "Todos los nodos fueron programados con éxito." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:87 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:183 +msgid "Apply configuration on all of them with a scheduled safe reboot?" +msgstr "¿Desea aplicar la configuracion en todos los nodos de manera segura?" + +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:104 +msgid "Apply mesh wide new configuration!" +msgstr "Aplicar una configuración a toda la red" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:89 +msgid "Apply new configuration" +msgstr "Aplicar la nueva configuración " + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:190 +msgid "Are you sure you want to apply the configuration to the nodes that are ready? <0/>This will make some of them to reboot<1/>Check node list to see the network status" +msgstr "¿Esta seguro de que desea aplicar la configuración a todos los nodos que esten listos? <0/> los nodos se reiniciarán<1/> Puede verificar en la lista de nodos el estado" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:226 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:90 msgid "Are you sure you want to confirm the upgrade? <0/>Check node list to see the network status" msgstr "¿Con seguridad desea confirmar la actualización? <0/>Verifique la lista de nodos para ver el estado de la red." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:66 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:26 +msgid "Are you sure you want to delete the <0>{prop} property?" +msgstr "Estas seguro que quieres borrar el atributo <0>{prop} ?" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:45 +msgid "Are you sure you want to edit the <0>{prop} property?" +msgstr "Estas seguro que quieres editar el atributo <0>{prop} ?" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:71 msgid "Are you sure you want to reboot this node? This action will disconnect the node from the network for a few minutes. <0/>Add shared password or let it empty if no password is set." msgstr "¿Con seguridad desea reiniciar este nodo? Esta acción desconectará el nodo de la red durante unos minutos. <0/>Agregue una contraseña compartida o deje el campo en blanco si no quiere establecer ninguna contraseña." @@ -123,14 +173,10 @@ msgstr "¿Con seguridad desea reiniciar este nodo? Esta acción desconectará el msgid "Are you sure you want to reboot?" msgstr "Con seguridad quiere reiniciar?" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:61 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:59 msgid "Are you sure you want to start mesh wide upgrade? <0/>Check node list to see the network status" msgstr "¿Con seguridad desea iniciar la actualización de toda la red? <0/>Verifique la lista de nodos para ver el estado de la red." -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:24 -msgid "Are you sure you want to {title} the <0>{prop} property?" -msgstr "¿Con seguridad quiere {título} la propiedad <0> {prop} ?" - #: plugins/lime-plugin-pirania/src/screens/invalidateVoucher.js:24 msgid "Are you sure?" msgstr "Lo confirma?" @@ -162,7 +208,8 @@ msgstr "Disponible" msgid "Await until it reboots" msgstr "Espere mientra se reinicia." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:50 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:121 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:51 msgid "Awaiting confirmation" msgstr "Esperando confirmación." @@ -194,7 +241,7 @@ msgstr "Enlaces de referencia en Batman" msgid "Best signal" msgstr "Mejor señal" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:65 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:43 msgid "Board" msgstr "Equipo (Hardware)" @@ -205,8 +252,7 @@ msgstr "Cargando el recorrido en la red" #: plugins/lime-plugin-fbw/src/containers/FbwBanner.tsx:83 #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:150 #: plugins/lime-plugin-fbw/src/containers/scanPage/components/buttons.js:14 -#: src/components/Modal/Modal.tsx:62 -#: src/components/Modal/Modal.tsx:128 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx:105 #: src/components/banner/index.js:20 msgid "Cancel" msgstr "Cancelar" @@ -231,24 +277,36 @@ msgstr "La Radio 0 no se puede utilizar por que está siendo utilizada para enla msgid "Cellphone Instructions" msgstr "Instrucciones para el celular" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:132 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:133 msgid "Chains" -msgstr "Recorrido" +msgstr "Cadenas (chains)" #: plugins/lime-plugin-network-admin/src/netAdminPage.js:76 msgid "Change" msgstr "Cambiar" +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:63 +msgid "Change LiMe Config" +msgstr "Cambiar la configuración" + #: plugins/lime-plugin-network-admin/src/netAdminPage.js:40 msgid "Change Shared Password" msgstr "Cambiar Contraseña Compartida" +#: plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx:40 +msgid "Changes made" +msgstr "Los cambios fueron realizados" + #: plugins/lime-plugin-fbw/src/containers/scanPage/components/networkTile.js:123 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:143 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:144 msgid "Channel" msgstr "Canal" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:22 +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:88 +msgid "Check if network is working properly and confirm the new configuration<0/>If not confirmed, the new configuration will be rolled back after a while" +msgstr "Verifique que la red este funcionando correctamente y luego confirme la nueva configuración<0/> Si no confirma el cambio de configuracion la red volvera a la configuración anterior. " + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:23 msgid "Check if network is working properly and confirm the upgrade<0/>If not confirmed, the upgrade will be rolled back after a while" msgstr "Verifique si la red funciona correctamente y confirme la actualización. <0/>Si no se confirma, la actualización se revertirá luego de un tiempo." @@ -286,7 +344,7 @@ msgstr "Haz click en Cerrar Sesión para finalizar la sesión de soporte remoto. msgid "Click at Show Console to follow the remote support session." msgstr "Haz click en Ver Consola para seguir la sesión de soporte remoto." -#: src/components/Modal/Modal.tsx:205 +#: src/components/Modal/Modal.tsx:179 msgid "Close" msgstr "Cerrar" @@ -317,36 +375,57 @@ msgstr "Acceso (roaming) comunitario" msgid "Community name" msgstr "Nombre de la comunidad" +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:131 +msgid "Configuration applied" +msgstr "La configuración fue aplicada" + +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:78 +msgid "Configuration applied!<0/>Awaiting confirmation" +msgstr "La configuración fue aplicada!<0/> Esperando confirmación" + #: plugins/lime-plugin-fbw/src/containers/NetworkForm.js:83 msgid "Configure your new community network" msgstr "Configure su nueva red mesh" #: plugins/lime-plugin-firmware/src/confirmPage/confirmPage.js:11 -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:241 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:118 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:148 msgid "Confirm" msgstr "Confirmar" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:82 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:117 +msgid "Confirm configuration on all nodes" +msgstr "Confirmar la configuración en todos los nodos" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:218 +msgid "Confirm configuration works properlly for al updated nodes" +msgstr "Confirme que la configuracion funciona correctamente para todos los nodos" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:85 msgid "Confirm mesh wide upgrade for all nodes on the network" msgstr "Confirmar la actualización de todos los nodos de la red." -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:240 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:147 msgid "Confirm upgrade on all nodes" msgstr "Confirmar actualización para todos los nodos." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:18 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:86 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:19 msgid "Confirmation pending" msgstr "Confirmación pendiente" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:19 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:87 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:20 msgid "Confirmed" msgstr "Confirmado" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:19 +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:63 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:20 msgid "Confirmed with some errors" msgstr "Confirmado con errores" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:15 +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:59 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:16 msgid "Confirmed!" msgstr "Confirmado!" @@ -354,11 +433,19 @@ msgstr "Confirmado!" msgid "Confirming all upgraded nodes" msgstr "Confirmando todos los nodos actualizados." +#: plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx:57 +msgid "Confirming new configuration to available nodes" +msgstr "Confirmando la configuración a todos los nodos." + #: plugins/lime-plugin-fbw/src/containers/Setting.js:127 msgid "Congratulations" msgstr "Felicitaciones!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:62 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:133 +msgid "Congratulations, this node has the new configuration working on it" +msgstr "Felicitaciones! Este nodo tiene la nueva configuración funcionando." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:63 msgid "Congratulations, this node was upgraded and confirmed successfully" msgstr "Felicitaciones! Este nodo fue actualizado y confirmado exitosamente." @@ -385,8 +472,8 @@ msgstr "Conexión al celular" msgid "Connection to the internet" msgstr "Conexión a internet" -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:34 -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:90 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:29 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:71 msgid "Continue" msgstr "Continuar" @@ -428,30 +515,27 @@ msgstr "Fecha de creación: {0}" msgid "Currently your node has version:" msgstr "Actualmente tu nodo tiene la versión:" -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:44 +#: src/components/Modal/Modal.tsx:107 msgid "Delete" msgstr "Eliminar" -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:43 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:24 msgid "Delete property" msgstr "Eliminar propiedad" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:206 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:201 msgid "Delete this this node from reference state" msgstr "Eliminar este nodo del estado de referencia" -#~ msgid "Delete this {0} link<0/>from reference state" -#~ msgstr "Eliminar este {0} enlace<0/>del estado de referencia" - #: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:372 msgid "Delete this {0}<0/>from reference state" msgstr "Eliminar este {0}<0/> del estado de referencia" -#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:99 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx:40 msgid "Deleted {keyString}" msgstr "Eliminado {keyString}" -#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:64 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormSection.tsx:59 msgid "Deleted {name} - {0}" msgstr "Eliminado {name} - {0}" @@ -464,7 +548,7 @@ msgstr "Descripción" msgid "Description: {name}" msgstr "Descripción: {name}" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:89 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:91 #: plugins/lime-plugin-rx/src/sections/system.tsx:48 msgid "Device" msgstr "Equipo" @@ -485,7 +569,7 @@ msgstr "Deshabilitado" msgid "Don't show this message again" msgstr "No volver a mostrar a este mensaje" -#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:53 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx:95 msgid "Done" msgstr "Hecho" @@ -493,7 +577,7 @@ msgstr "Hecho" msgid "Download" msgstr "Descargar" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:183 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:92 msgid "Download remote firmware<0/>to start mesh upgrade" msgstr "Descargue el archivo del sistema (firmware)<0/>para iniciar la actualización de toda la red." @@ -506,7 +590,7 @@ msgstr "Versión descargada<0/>{0}" msgid "Downloading" msgstr "Descargando" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:15 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:16 msgid "Downloading new firmware" msgstr "Descargando nuevo sistema (firmware)" @@ -520,7 +604,7 @@ msgstr "Duración: es permanente" msgid "Duration: {days, plural, one {# day} other {# days}}" msgstr "Duración: {days, plural, one {# día} other {# días}}" -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:51 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:40 #: plugins/lime-plugin-pirania/src/screens/voucher.js:90 msgid "Edit" msgstr "Editar" @@ -529,7 +613,7 @@ msgstr "Editar" msgid "Edit Voucher" msgstr "Editar cupón" -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:50 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:39 msgid "Edit property" msgstr "Editar propiedad" @@ -537,14 +621,6 @@ msgstr "Editar propiedad" msgid "Edit wellcome screen" msgstr "Editar pantalla de bienvenida" -#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:123 -msgid "Edited {keyString}" -msgstr "Editado {keyString}" - -#: plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx:47 -msgid "Edited {name} - {0}" -msgstr "Editado {name} - {0}" - #: plugins/lime-plugin-node-admin/src/screens/roamingAP.js:25 msgid "Enable Community Roaming AP" msgstr "Activar AP (punto de acceso roaming) comunitario" @@ -602,7 +678,7 @@ msgstr "Error recibiendo los resultados del escaneo." msgid "Error loading leaflet" msgstr "Error cargando leaflet." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:85 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:89 msgid "Error performing reboot: {error}" msgstr "Error al reiniciar: {error}" @@ -615,7 +691,11 @@ msgstr "No se pudo obtener el nombre del host!" msgid "Error retrieving associated list" msgstr "Error recuperando la lista de nodos asociados." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:43 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:34 +msgid "Error retrieving the status" +msgstr "Error al obtener informacion del nodo" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:31 msgid "Error retrieving the status, is this node outdated?" msgstr "Error al recuperar el estado. ¿Este nodo está desactualizado?" @@ -632,7 +712,7 @@ msgid "Error setting network" msgstr "Error configurando red." #: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:355 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:189 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:190 msgid "Error setting new reference state!" msgstr "¡Error al establecer un nuevo estado de referencia!" @@ -640,7 +720,11 @@ msgstr "¡Error al establecer un nuevo estado de referencia!" msgid "Error stopping scan" msgstr "Error deteniendo la búsqueda." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx:12 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx:21 +msgid "Error updating the new configuration" +msgstr "Error al intentar cambiar la nueva configuración" + +#: src/components/mesh-wide-wizard/ErrorState.tsx:12 msgid "Error!" msgstr "Error!" @@ -648,11 +732,12 @@ msgstr "Error!" msgid "Error: Not Saved" msgstr "Error: No se guardó." -#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:35 -msgid "Errors found getting mesh info!" +#: src/components/mesh-wide-wizard/WizardWrapper.tsx:36 +msgid "Errors found getting info!" msgstr "¡Se encontraron errores al obtener información de de la red (mesh info)!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:32 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:100 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:33 msgid "Everything is up to date!" msgstr "Todo quedó actualizado!" @@ -693,16 +778,16 @@ msgstr "Filtrar por" msgid "Firmware" msgstr "Sistema del nodo" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:40 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:41 msgid "Firmware download and verified" msgstr "Archivo de sistema (firmware) descargado y verificado." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:16 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:17 msgid "Firmware downloaded" msgstr "Archivo de sistema (firmware) descargado." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:80 -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:69 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:82 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:47 msgid "Firmware version" msgstr "Versión de sistema (firmware)." @@ -750,11 +835,15 @@ msgstr "Nombre del nodo" msgid "I don't know the shared password" msgstr "No sé la contraseña compartida." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:85 +#: plugins/lime-plugin-rx/src/rxPage.js:181 +#~ msgid "IP Addresses" +#~ msgstr "Direcciones IP" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:87 msgid "IPv4" msgstr "IPv4" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:86 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:88 msgid "IPv6" msgstr "IPv6" @@ -774,15 +863,19 @@ msgstr "Si invalidas este cupón, el mismo no podrá volver a ser utilizado. Est msgid "If your community network has local services, you can point a link to them." msgstr "Si tu red comunitaria tiene servicios locales, puedes indicar un enlace para acceder a ellos." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:57 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:86 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:58 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:87 msgid "Iface" msgstr "Interface" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:222 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:217 msgid "In the reference state this node is on" msgstr "En el estado de referencia este nodo está encendido." +#: plugins/lime-plugin-rx/src/rxPage.js:98 +#~ msgid "Interface" +#~ msgstr "Interfaz" + #: plugins/lime-plugin-rx/src/sections/alignment.tsx:72 msgid "Interface:" msgstr "Interface:" @@ -813,10 +906,15 @@ msgstr "Invalidar" msgid "Invalidated" msgstr "Invalidado" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:73 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:53 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:51 msgid "Ip" msgstr "IP" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:132 +msgid "Is a list" +msgstr "Es una lista" + #: plugins/lime-plugin-pirania/src/components/createVoucherForm.tsx:75 msgid "Is permanent" msgstr "Es permanente" @@ -842,23 +940,15 @@ msgstr "Ir a <0>foro.librerouter.org" msgid "Join the mesh" msgstr "Unirse a la red" -#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:44 -msgid "Key" -msgstr "Llave" - #: plugins/lime-plugin-align/src/alignPage.js:55 #: plugins/lime-plugin-align/src/containers/alignSingle/index.js:134 msgid "Last packet" msgstr "Último paquete" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:60 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:61 msgid "Last seen" msgstr "Visto por última vez" -#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:29 -msgid "Last update: 30 second ago" -msgstr "Última actualización: hace 30 segundos" - #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:120 msgid "Link Title" msgstr "Título del enlace" @@ -867,11 +957,11 @@ msgstr "Título del enlace" msgid "Link URL" msgstr "URL del enlace" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:181 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:182 msgid "Link from <0>{0} to <1>{1}" msgstr "Enlace desde <0>{0} hasta <1>{1}" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:248 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:249 msgid "Link {0} {1}" msgstr "Enlace {0} {1}" @@ -883,6 +973,10 @@ msgstr "Cargando la última ruta a Internet conocida..." msgid "Loading <0/>last internet path..." msgstr "Cargando <0/> la última ruta a internet conocida..." +#: plugins/lime-plugin-rx/src/rxPage.js:128 +#~ msgid "Loading node status..." +#~ msgstr "Cargando el estado del nodo..." + #: plugins/lime-plugin-pirania/src/screens/wellcomeScreenEditor.js:111 msgid "Local services link" msgstr "Enlace a servicios locales" @@ -899,17 +993,11 @@ msgstr "Iniciando sesión" msgid "Login" msgstr "Ingresar" -#~ msgid "Macs" -#~ msgstr "MACs" - -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:94 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:96 msgid "Macs ({0})" msgstr "MACs ({0})" -#~ msgid "Macs not found" -#~ msgstr "MACs no encontrados" - -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:106 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:108 msgid "Macs not found ({0})" msgstr "Macs no encontradas ({0})" @@ -941,19 +1029,23 @@ msgstr "Mapa de la red mesh" msgid "Mesh Wide Upgrade" msgstr "Sistema de la red" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:16 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:102 +msgid "Mesh configuration is on the last version" +msgstr "La configuración de la red está en su última versión" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:17 msgid "Mesh upgrade confirmed successfully" msgstr "Actualización de toda la red confirmada." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:20 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx:21 msgid "Mesh upgrade confirmed with some errors" msgstr "Actualización de la red confirmada con algunos errores." -#: plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx:20 +#: plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm.tsx:23 msgid "Mesh wide config" -msgstr "Configuración de la red completa" +msgstr "Configuración de la red completa (archivo lime-community)" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:10 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:11 msgid "Mesh wide upgrade started!" msgstr "¡Actualización lista para inciar!" @@ -961,6 +1053,12 @@ msgstr "¡Actualización lista para inciar!" msgid "Metrics" msgstr "Diagnóstico" +#: plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx:76 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx:113 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:109 +msgid "Minimum length is 1" +msgstr "La longitud mínima es 1" + #: plugins/lime-plugin-firmware/src/upgradeAvailable.js:79 msgid "More details on the release can be found at:" msgstr "Puedes encontrar más información sobre esta versión en:" @@ -973,6 +1071,10 @@ msgstr "Más info en:" msgid "More than 10 characters" msgstr "Más de 10 caracteres" +#: plugins/lime-plugin-rx/src/rxPage.js:80 +#~ msgid "Most Active" +#~ msgstr "Enlace más activo" + #: plugins/lime-plugin-rx/src/sections/alignment.tsx:60 msgid "Most active link" msgstr "Link más activo" @@ -981,10 +1083,6 @@ msgstr "Link más activo" msgid "Must select a valid hostname" msgstr "Debes elegir un nombre de host válido." -#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:73 -msgid "Name" -msgstr "Nombre" - #: plugins/lime-plugin-rx/src/components/footer.tsx:19 msgid "Need support?" msgstr "Necesita soporte?" @@ -993,7 +1091,7 @@ msgstr "Necesita soporte?" msgid "Network Name: {ssid}" msgstr "Nombre de Red: {ssid}" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:126 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:128 msgid "New Macs ({0})" msgstr "Nuevas MACs({0})" @@ -1001,12 +1099,24 @@ msgstr "Nuevas MACs({0})" msgid "New available version:<0/>{0}" msgstr "Nueva versión disponible:<0/>{0}" +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:60 +msgid "New configuration confirmed successfully" +msgstr "Nueva configuración confirmada! " + +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:106 +msgid "New configuration is on the node" +msgstr "La nueva configuración esta disponible en el nodo" + +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:64 +msgid "New configuration was confirmed with some errors" +msgstr "La nueva configuración fue confirmada con errores" + #: plugins/lime-plugin-mesh-wide/src/components/Map/LinkLine.tsx:85 msgid "New link" -msgstr "Nuevo link" +msgstr "Nuevo enlace" #: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:351 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:184 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:185 msgid "New reference state set!" msgstr "¡Nuevo estado de referencia establecido!" @@ -1014,7 +1124,11 @@ msgstr "¡Nuevo estado de referencia establecido!" msgid "New version available!" msgstr "Nueva versión disponible!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:33 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx:36 +msgid "No changes made" +msgstr "No se realizaron cambios" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:34 msgid "No new version available is found" msgstr "No se ha encontrado una nueva versión disponible." @@ -1022,7 +1136,7 @@ msgstr "No se ha encontrado una nueva versión disponible." msgid "No new version available!" msgstr "No hay una nueva versión disponible!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx:23 +#: src/components/mesh-wide-wizard/NodesListWrapper.tsx:29 msgid "No nodes present on the <0/>mesh wide upgrade state yet!" msgstr "No hay nodos presentes en <0/> el estado de actualizaciones de la red completa!" @@ -1034,7 +1148,11 @@ msgstr "Sin contraseña" msgid "No scan result" msgstr "Sin resultado de escaneo" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:14 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:83 +msgid "No update in progres" +msgstr "No hay un cambio de configuración en curso." + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:15 msgid "No upgrade in progres" msgstr "No hay una actualización en curso." @@ -1117,9 +1235,10 @@ msgstr "O, si tu nodo ya está bien configurado, puedes saltear este paso." msgid "Or upgrade to latest release" msgstr "O actualiza a la última versión del sistema (firmware)." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:94 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:167 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:95 msgid "Other nodes will download the firmware from it" -msgstr "Esto significa que otros nodos descargarán el archivo de sistema alojado en este nodo." +msgstr "Esto significa que otros nodos descargarán el archivo alojado en este nodo." #: plugins/lime-plugin-metrics/src/components/box/index.js:110 msgid "Packet loss" @@ -1185,8 +1304,16 @@ msgstr "Reingrese la contraseña" msgid "Re-enter the shared password" msgstr "Reingrese la contraseña compartida" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:196 -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:207 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:84 +msgid "Ready for apply" +msgstr "Listo para aplicar" + +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:36 +msgid "Ready for apply new configuration" +msgstr "Listo para aplicar la nueva configuración" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:105 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:114 msgid "Ready to start mesh wide upgrade" msgstr "Listo para distribuir la actualización a toda la red" @@ -1194,12 +1321,12 @@ msgstr "Listo para distribuir la actualización a toda la red" msgid "Ready to start mesh wide<0/>firmware upgrade" msgstr "Listo para iniciar la actualización de sistema de toda la red" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:95 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:68 #: src/containers/RebootBanner/rebootBanner.js:17 msgid "Reboot" msgstr "Reiniciar" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:63 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn.tsx:67 msgid "Reboot node {0}" msgstr "Reiniciar nodo {0}" @@ -1212,13 +1339,10 @@ msgid "Reference State is not set" msgstr "Estado de referencia no establecido." #: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:387 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:220 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:215 msgid "Reference is not set or has errors" msgstr "El estado de referencia no ha sido establecido o contiene errores." -#~ msgid "Reference state is not set for {dataType}" -#~ msgstr "Estado de referencia no establecido por {dataType}." - #: plugins/lime-plugin-ground-routing/src/groundRoutingPage.js:32 msgid "Reload" msgstr "Recargar" @@ -1231,14 +1355,11 @@ msgstr "Recargar página" msgid "Remote Support" msgstr "Soporte Remoto" -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:67 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:57 msgid "Remove this {0} from the reference state" msgstr "Eliminar este {0} del estado de referencia" -#~ msgid "Remove this {dataType} from the reference state" -#~ msgstr "Eliminar este {dataType} para el estado de referencia" - -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:21 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:19 msgid "Remove {nodeName} from the reference state" msgstr "Eliminar {nodeName} para el estado de referencia" @@ -1250,6 +1371,14 @@ msgstr "Requerido" msgid "Rescan" msgstr "Volver a escanear" +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:21 +msgid "Restart is scheduled!" +msgstr "Reinicio programado" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:85 +msgid "Restart scheduled" +msgstr "Reinicio programado" + #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:116 msgid "Retry" msgstr "Reintenar" @@ -1262,12 +1391,12 @@ msgstr "Revertir" msgid "Reverting to previous version" msgstr "Volviendo a la versión anterior" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:151 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:152 msgid "RxRate" msgstr "RxRate" #: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:380 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:218 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:213 msgid "Same status as in the reference state" msgstr "Tiene el mismo estado que el estado de referencia." @@ -1293,19 +1422,25 @@ msgstr "Guardado" msgid "Scanning for existing networks" msgstr "Buscando redes existentes" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:20 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:33 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:38 msgid "Schedule" msgstr "Confirmar" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:56 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:54 msgid "Schedule a firmware upgrade for all nodes on the network" msgstr "Actualizar una actualización de sistema (firmware) para todos los nodos de la red" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:220 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:97 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:127 msgid "Schedule again" msgstr "Actualizar nuevamente" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:214 +#: plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx:46 +msgid "Schedule apply configuration to all available nodes" +msgstr "Programar el inicio de cambio de configuración en todos los nodos" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:121 msgid "Schedule upgrade" msgstr "Actualizar" @@ -1313,6 +1448,10 @@ msgstr "Actualizar" msgid "Schedule upgrade to all available nodes" msgstr "Actualizar todos los nodos disponibles" +#: plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx:44 +msgid "Scheduling apply configuration" +msgstr "Agendando la aplicacion de la configuracion" + #: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:44 msgid "Scheduling upgrade" msgstr "Actualizando ..." @@ -1354,10 +1493,12 @@ msgstr "Seleccione el nodo" msgid "Selected network to join" msgstr "Red seleccionada para unirse" +#: plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx:32 #: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:25 msgid "Sending abort message to this node. The abort order will be propagated to all nodes." msgstr "Enviando mensaje de cancelación a este nodo. La orden de cancelación se propagará a todos los nodos." +#: plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx:55 #: plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx:62 msgid "Sending confirmation" msgstr "Enviando confirmación" @@ -1366,29 +1507,23 @@ msgstr "Enviando confirmación" msgid "Set network" msgstr "Sumarse a la red" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:204 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:199 msgid "Set reference state for this node" msgstr "Establecer el estado de referencia para este nodo." -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:58 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:48 msgid "Set reference state for this {0}?" msgstr "¿Desea fijar el estado de referencia para {0}?" -#~ msgid "Set reference state for this {dataType} link?" -#~ msgstr "Establecer el estado de referencia para este {dataType} enlace?" - #: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:363 msgid "Set reference state for this<0/> {0}" msgstr "Fijar estado de referencia para este<0/> {0}" -#~ msgid "Set reference state for this<0/> {0} link" -#~ msgstr "Establecer el estado de referencia para este<0/> {0} enlace." - -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:17 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:16 msgid "Set reference state for {nodeName}" -msgstr "Establecer el estado de referencia para {nodeName}." +msgstr "Establecer el estado de referencia para el nodo {nodeName}" -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:18 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:17 msgid "Set the reference state for this node." msgstr "Establecer el estado de referencia para este nodo." @@ -1396,7 +1531,8 @@ msgstr "Establecer el estado de referencia para este nodo." msgid "Setting network" msgstr "Configurando red" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:86 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:159 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:87 msgid "Setting up main node" msgstr "Configurando el nodo principal" @@ -1438,15 +1574,15 @@ msgstr "Error de shared state" msgid "Show Console" msgstr "Ver consola" -#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:65 +#: src/components/mesh-wide-wizard/WizardWrapper.tsx:66 msgid "Show nodes" -msgstr "Ver nodos" +msgstr "Estado de los vecinos" -#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:57 +#: src/components/mesh-wide-wizard/WizardWrapper.tsx:58 msgid "Show state" -msgstr "Ver estado" +msgstr "Estado de este nodo" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:118 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:119 msgid "Signal" msgstr "Señal" @@ -1459,43 +1595,66 @@ msgstr "Sin señal" msgid "Size" msgstr "Tamaño" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:59 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:81 +msgid "Some nodes are not marked as ready to apply" +msgstr "Algunos nodos fueron marcados como listos para aplicar" + +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:188 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:57 msgid "Some nodes are not ready" msgstr "Algunos nodos aún no están listos." -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:209 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:116 msgid "Some nodes are not ready for upgrade <0/>Check node details for more info" msgstr "Algunos nodos aún no están listos para ser actualizados. <0/>Consulte el botón \"Ver nodos\" para obtener más información." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:18 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx:19 msgid "Some nodes are still downloading the firmware<0/>check network page for more information" msgstr "Algunos nodos todavía están descargando el firmware<0/>consulte la página de red para obtener más información." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:85 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:224 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:88 msgid "Some nodes don't upgraded properly" msgstr "Algunos nodos no se actualizan correctamente." -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:226 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:103 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:133 msgid "Some nodes have errors" msgstr "Algunos nodos tienen errores." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx:36 +#: src/components/mesh-wide-wizard/StepState.tsx:36 msgid "Some nodes have errors:" msgstr "Algunos nodos tienen errores:" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:91 +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:44 +msgid "Some nodes have not the new configuration yet or are not ready for apply it.<0/>Check network page for more information" +msgstr "Algunos nodos no estan listos todavía" + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:92 msgid "Source IP" msgstr "IP de origen" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:197 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:106 msgid "Start" msgstr "Distribuir" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:189 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx:52 +msgid "Start Lime Config update" +msgstr "Iniciar la el cambio de la configuración" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:98 msgid "Start mesh upgrade" msgstr "Iniciar descarga" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:74 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx:43 +msgid "Start mesh wide configuration update" +msgstr "Ya es posible iniciar la el cambio de la configuración en toda la red" + +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:146 +msgid "Start mesh wide configuration update again" +msgstr "Iniciar la el cambio de la configuración en toda la red nuevamente" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:75 msgid "Start mesh wide firmware upgrade again" msgstr "Es recomendable Iniciar la actualización en toda la red nuevamente." @@ -1503,6 +1662,10 @@ msgstr "Es recomendable Iniciar la actualización en toda la red nuevamente." msgid "Start mesh wide upgrade" msgstr "Distribuir la actualización en todos los nodos de la red" +#: plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx:27 +msgid "Starting mesh wide configuration change" +msgstr "Iniciando el proceso de cambio de la configuración" + #: plugins/lime-plugin-rx/src/rxMenu.js:9 msgid "Status" msgstr "Estado" @@ -1511,8 +1674,7 @@ msgstr "Estado" msgid "Status: {0}" msgstr "Estado: {0}" -#: src/components/Modal/Modal.tsx:60 -#: src/components/Modal/Modal.tsx:126 +#: src/components/Modal/Modal.tsx:106 msgid "Success" msgstr "Completado" @@ -1532,11 +1694,16 @@ msgstr "El portal comunitario permite mostrar una pantalla de bienvenida en el n msgid "The are not mesh interfaces available" msgstr "No hay interfaces mesh disponibles." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:88 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:161 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:89 msgid "The become main node process is starting on this node" msgstr "El proceso para convertir este nodo en el principal está comenzando." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:135 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:123 +msgid "The configuration seems to be updated successfully. Confirm that the node is working properly or will be downgraded to the previous version" +msgstr "La configuración se actualizó, confirme que el nodo esta funcionando correctamente. En caso de no confirmar, el nodo reiniciará con la configuración anterior." + +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:136 msgid "The difference between chains is too big" msgstr "La diferencia entre cadenas es demasiado grande." @@ -1548,7 +1715,7 @@ msgstr "La descarga falló." msgid "The firmware is being upgraded..." msgstr "La actualización se está realizando..." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:52 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:53 msgid "The firmware seems to be installed successfully. Confirm that the node is working properly or will be downgraded to the previous version" msgstr "El firmware parece haberse instalado correctamente. Confirme que el nodo funciona correctamente o se volverá a la versión anterior." @@ -1572,7 +1739,7 @@ msgstr "El punto de acceso no se encuentra disponible. Por favor, revisa las ins msgid "The name should have at least 3 characters" msgstr "El nombre tiene que tener al menos 3 caracteres." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:77 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:79 msgid "The node is down" msgstr "El nodo no está activo." @@ -1601,11 +1768,15 @@ msgstr "La imagen seleccionada no es válida para este dispositivo." msgid "The shared password has been chosen by the community when the network was created. You can ask other community members for it." msgstr "La contraseña compartida fue elegida por la comunidad al iniciar la red. Pregúntale a quienes gestionan la red cuál es." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:123 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:124 msgid "The signal is X below the reference state" msgstr "La señal está X por debajo del estado de referencia." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:44 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:112 +msgid "The update is scheduled" +msgstr "La actualización esta programada" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:45 msgid "The upgrade is scheduled" msgstr "La actualización ha comenzado." @@ -1641,11 +1812,18 @@ msgstr "Este dispositivo está habilitado para revertir la actualización en cas msgid "This device supports secure rollback to previous version if something goes wrong" msgstr "En este dispositivo sí se puede revertir la actualización en caso de errores." +#: plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx:78 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx:115 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:111 +msgid "This field cannot be empty" +msgstr "Este campo no puede estar vacío" + #: src/components/form/index.js:21 msgid "This field is required" msgstr "Este campo es requerido" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:92 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:165 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:93 msgid "This is a main node" msgstr "Este es un nodo principal" @@ -1653,48 +1831,56 @@ msgstr "Este es un nodo principal" msgid "This link has errors" msgstr "Este enlace tiene errores." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:169 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:170 msgid "This link seems down" msgstr "Este enlace parece estar caído." -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:73 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:63 msgid "This link seems down, remove them from the reference state?" msgstr "Este enlace parece caído, ¿desea eliminarlo del estado de referencia?" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:111 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:113 msgid "This macs are not on the actual state" msgstr "Estos macs no están en el estado actual." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:129 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:131 msgid "This macs are not on the reference state" msgstr "Estas MACs no están en el estado de referencia" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:73 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:144 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:74 msgid "This node aborted" -msgstr "Actualización interrumpida." +msgstr "Este nodo interrumpió su proceso." -#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:86 -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:21 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:89 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:22 +#: src/components/mesh-wide-wizard/StepState.tsx:69 msgid "This node aborted successfully" -msgstr "La actualización fue interrumpida con éxito." +msgstr "Este nodo interrumpió su proceso." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:41 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:42 msgid "This node es ready for upgrade" msgstr "Este nodo está listo para actualizarse." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:20 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:88 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:21 msgid "This node has an error" msgstr "Este nodo tiene un error." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:69 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:140 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:70 msgid "This node has an error!" msgstr "Este nodo tiene un error!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:36 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:108 +msgid "This node is awaiting to apply the configuration" +msgstr "Este nodo esta esperando para aplicar la configuración" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:37 msgid "This node is downloading a new firmware" msgstr "Este nodo está descargando un nuevo archivo de sistema (firmware)." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:225 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:220 msgid "This node is not registered on the reference state" msgstr "Este nodo no está registrado en el estado de referencia." @@ -1702,11 +1888,11 @@ msgstr "Este nodo no está registrado en el estado de referencia." msgid "This node is the gateway" msgstr "Este nodo es el gateway." -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:36 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:38 msgid "This node seems down" msgstr "Este nodo parece inactivo." -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:24 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:21 msgid "This node seems down, remove them from the reference state?" msgstr "Este nodo parece inactivo, ¿desea eliminarlo del estado de referencia?" @@ -1718,11 +1904,15 @@ msgstr "Versión de este nodo<0/>{0}" msgid "This radio is not associated with other nodes" msgstr "Esta radio no está enlazada a otros nodos." -#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:63 +#: plugins/lime-plugin-mesh-wide/src/components/modals.tsx:53 msgid "This will set the reference state of this link:" msgstr "Esto establecerá el estado de referencia de este enlace:" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:104 +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:154 +msgid "This will the abort current configuration update process on all nodes. Are you sure you want to proceed?" +msgstr "Esta a punto de interrumpir todo el proceso de cambio de configuración. ¿Está seguro que desea proceder?" + +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx:117 msgid "This will the abort current upgrade process on all nodes. Are you sure you want to proceed?" msgstr "Esto cancelará el proceso de actualización actual en todos los nodos. ¿Está seguro que deseas continuar?" @@ -1742,11 +1932,15 @@ msgstr "Hasta Internet" msgid "To enable remote access an internet connection is needed" msgstr "Para posibilitar el acceso remoto es necesaria una conexión a internet." +#: plugins/lime-plugin-rx/src/rxPage.js:103 +#~ msgid "Traffic" +#~ msgstr "Tráfico" + #: plugins/lime-plugin-rx/src/sections/alignment.tsx:78 msgid "Traffic:" msgstr "Tráfico:" -#: plugins/lime-plugin-mesh-wide-upgrade/src/hooks/useStepper.tsx:248 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter.tsx:155 msgid "Try last step again" msgstr "Intente el último paso nuevamente" @@ -1754,7 +1948,7 @@ msgstr "Intente el último paso nuevamente" msgid "Try reloading the app" msgstr "Intentar recargar la app" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:148 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:149 msgid "TxRate" msgstr "TxRate" @@ -1762,14 +1956,10 @@ msgstr "TxRate" msgid "Unknown error" msgstr "Error desconocido" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:226 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx:227 msgid "Unknown link type" msgstr "Tipo de enlace desconocido" -#: plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx:16 -msgid "Updating shared state {0}" -msgstr "Actualizando shared state" - #: plugins/lime-plugin-firmware/src/upgradePage/upgradePage.js:229 msgid "Upgrade" msgstr "Confirmar" @@ -1778,19 +1968,19 @@ msgstr "Confirmar" msgid "Upgrade Now" msgstr "Actualizar ahora" -#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:74 +#: plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx:20 msgid "Upgrade all network nodes at once. This proces will take a while and will require user interaction." msgstr "Actualice todos los nodos de la red a la vez. Este proceso llevará un tiempo y requerirá la interacción del usuario." -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:16 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:17 msgid "Upgrade is scheduled!" msgstr "La actualización está iniciada!" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:17 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:18 msgid "Upgrade scheduled" msgstr "La actualización está iniciada" -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:60 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:61 msgid "Upgrade successful" msgstr "La actualización fue exitosa" @@ -1803,7 +1993,7 @@ msgstr "Actualizar a la última version del firwmare" msgid "Upgrade to {versionName}" msgstr "Actualizar a {versionName}" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:12 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx:13 msgid "Upgraded!<0/>Awaiting confirmation" msgstr "Actualizado!<0/>Esperando confirmación" @@ -1811,8 +2001,8 @@ msgstr "Actualizado!<0/>Esperando confirmación" msgid "Upload firmware image from your device" msgstr "Suba un archivo de sistema (imagen del firmware) desde tu dispositivo" -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:72 -#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:76 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:74 +#: plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx:78 #: plugins/lime-plugin-rx/src/sections/system.tsx:45 msgid "Uptime" msgstr "Tiempo en actividad" @@ -1821,7 +2011,7 @@ msgstr "Tiempo en actividad" msgid "Use vouchers for access" msgstr "Usar cupones de acceso" -#: plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx:49 +#: plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx:120 msgid "Value" msgstr "Valor" @@ -1858,7 +2048,7 @@ msgstr "Lista de cupones" msgid "Vouchers can be used to limit access through the Community Portal to those who have an authorization code" msgstr "Los cupones sirven para limitar el acceso a través del Portal Comunitario a quienes posean un código de autorización." -#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:37 +#: plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx:38 msgid "Wait until the download is finished!" msgstr "¡Espere hasta que finalice la descarga!" @@ -1917,6 +2107,10 @@ msgstr "Está conectado a otro nodo de la red, intente conectarse a" msgid "You are now part of" msgstr "Usted es ahora parte de" +#: plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx:65 +msgid "You can change shared network configuration" +msgstr "Puedes cambiar la configuración de la red" + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:83 msgid "You can share your mobile connection to the node by setting up a mobile hotspot" msgstr "Puede compartir tu conexión de datos con el nodo a través de un Punto de Acceso Móvil (hotspot)." @@ -1945,6 +2139,10 @@ msgstr "Intente conectarse a la red wifi {wifiSsid} para completar la instalaci msgid "Your Alignment" msgstr "Su alineación" +#: plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm.tsx:74 +msgid "Your Lime Community file seems empty! Please add some configurations." +msgstr "Tu archivo de configuración parece vacío! Debes agregar una configuración." + #: plugins/lime-plugin-remotesupport/src/remoteSupportPage.js:74 msgid "Your node has no internet connection" msgstr "Su nodo no tiene conexión a internet" @@ -1969,6 +2167,10 @@ msgstr "para los siguientes nodos: {nodes}" msgid "hide community" msgstr "Esconder comunidad" +#: plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx:116 +msgid "key" +msgstr "Clave" + #: plugins/lime-plugin-locate/src/locatePage.tsx:230 msgid "locate my node" msgstr "Ubicar mi nodo" @@ -1993,12 +2195,17 @@ msgstr "a la versión anterior" msgid "{0, plural, =0 {No one has joined yet.} one {One person has joined.} other {# people have joined.}}" msgstr "{0, plural, =0 {Nadie se ha unido aún.} one {Una persona se ha unido.} other {# personas se han unido.}}" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:66 -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:70 -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:74 +#: plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx:54 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:44 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:48 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx:52 msgid "{0}" msgstr "{0}" +#: plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx:23 +msgid "{0} of {totalNodes} will be upgraded" +msgstr "{0} de {totalNodes} nodos serán actualizados" + #: plugins/lime-plugin-rx/src/sections/system.tsx:22 msgid "{days, plural, one {# day} other {# days}}" msgstr "{days, plural, one {# día} other {# días}}" @@ -2011,7 +2218,7 @@ msgstr "{hours, plural, one {# hora} other {# horas}}" msgid "{mins, plural, one {# minute} other {# minutes}}" msgstr "{mins, plural, one {# minuto} other {# minutos}}" -#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:18 +#: plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx:19 msgid "{nodesToBeUpgraded} of {totalNodes} will be upgraded" msgstr "{nodesToBeUpgraded} de {totalNodes} serán actualizados, espere." diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx index 85881c2b5..b0a69ecc6 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/Components.tsx @@ -51,8 +51,8 @@ export const EditOrDelete = ({ onEdit, onDelete, }: { - onEdit: (e) => void; - onDelete: (e) => void; + onEdit?: (e) => void; + onDelete?: (e) => void; }) => { const runCb = (e, cb) => { e.stopPropagation(); @@ -60,14 +60,18 @@ export const EditOrDelete = ({ }; return (
- runCb(e, onEdit)} - /> - runCb(e, onDelete)} - /> + {!!onEdit && ( + runCb(e, onEdit)} + /> + )} + {!!onDelete && ( + runCb(e, onDelete)} + /> + )}
); }; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx deleted file mode 100644 index 0862d8008..000000000 --- a/plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { Trans } from "@lingui/macro"; - -import { useDisclosure } from "components/Modal/useDisclosure"; -import { Button } from "components/buttons/button"; -import { Collapsible } from "components/collapsible"; -import { useToast } from "components/toast/toastProvider"; - -import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; -import { OptionContainer } from "plugins/lime-plugin-mesh-wide-config/src/components/OptionForm"; -import { - AddNewSectionFormProps, - AddNewSectionModal, - DeletePropModal, - EditPropModal, -} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; -import { IMeshWideSection } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; - -export const ConfigSection = ({ dropdown }: { dropdown: IMeshWideSection }) => { - return ( - } - > - {Object.entries(dropdown.options).map(([key, value]) => ( - - ))} - - ); -}; - -export const SectionEditOrDelete = ({ name }) => { - const { - open: isEditOpen, - onOpen: openEdit, - onClose: onCloseEdit, - } = useDisclosure(); - const { - open: isDeleteModalOpen, - onOpen: openDeleteModal, - onClose: onCloseDeleteModal, - } = useDisclosure(); - const { showToast } = useToast(); - - const onEdit = async () => { - console.log("edit stuff"); - onCloseEdit(); - showToast({ - text: ( - - Edited {name} - {new Date().toDateString()} - - ), - onAction: () => { - console.log("Undo action"); - }, - }); - }; - - const onDelete = async () => { - console.log("delete stuff"); - onCloseDeleteModal(); - showToast({ - text: ( - - Deleted {name} - {new Date().toDateString()} - - ), - onAction: () => { - console.log("Undo action"); - }, - }); - }; - - return ( - <> - - - - - ); -}; - -export const AddNewSectionBtn = () => { - const { open, onOpen, onClose } = useDisclosure(); - const { showToast } = useToast(); - - const onSuccess = (data: AddNewSectionFormProps) => { - console.log(`Added`, data); - onClose(); - showToast({ - text: ( - - Added section {data.name} - {new Date().toDateString()} - - ), - }); - }; - return ( - <> - - - - ); -}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx new file mode 100644 index 000000000..37028ad24 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx @@ -0,0 +1,185 @@ +import { Trans, t } from "@lingui/macro"; +import { useEffect, useState } from "preact/hooks"; +import { Controller, useFormContext } from "react-hook-form"; +import { v4 as uuidv4 } from "uuid"; + +import { useDisclosure } from "components/Modal/useDisclosure"; +import { Button, ButtonProps } from "components/buttons/button"; +import InputField from "components/inputs/InputField"; +import { useToast } from "components/toast/toastProvider"; + +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; +import { + AddNewSectionFormProps, + AddNewSectionModal, +} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +export const EditableField = ({ + isList, + name, +}: { + isList: boolean; + name: string; +}) => { + const { control, setValue, watch, getValues } = useFormContext(); + + const value = watch(name); + // Hack to force re-render when the list changes + const [uniqueKeys, setUniqueKeys] = useState( + isList && value?.length ? value.map(() => uuidv4()) : [] + ); + + const syncKeysWithValues = () => { + // Ensure uniqueKeys matches the length of value array + setUniqueKeys((keys) => [ + ...keys, + ...Array(value.length - keys.length) + .fill(null) + .map(() => uuidv4()), + ]); + }; + + const removeListItem = (index) => { + const updatedValues = value.filter((_, i) => i !== index); + setValue(name, updatedValues); + setUniqueKeys((keys) => keys.filter((_, i) => i !== index)); + }; + + const addListItem = () => { + setValue(name, [...value, ""]); + setUniqueKeys((keys) => [...keys, uuidv4()]); + }; + + // Ensure the list has at least one item at the start + useEffect(() => { + if (isList && value.length === 0) { + setValue(name, [""]); + setUniqueKeys([uuidv4()]); // Reset keys for new list + } else if (isList) { + // Sync keys with values length on every render + syncKeysWithValues(); + } + }, [isList, value, name, setValue]); + + if (isList) { + return ( +
+ {uniqueKeys.map((item, index) => ( + { + return ( +
+ + removeListItem(index)} + /> +
+ ); + }} + /> + ))} + +
+ ); + } + + return ( + ( + Value} + className="w-100" + error={error?.message} + {...field} + /> + )} + /> + ); +}; + +export const AddNewConfigSection = ({ + sectionName, +}: { + sectionName?: string; +}) => { + const { watch, setValue } = useFormContext(); + + const { open, onOpen, onClose } = useDisclosure(); + const { showToast } = useToast(); + + const section = watch(sectionName); + + const onSuccess = (data: AddNewSectionFormProps) => { + if (!sectionName) { + setValue(data.name, {}); + } else { + let value: string | string[] = data.value; + if (data.isList) { + value = data.values; + } + setValue(sectionName, { + ...section, + [data.name]: value, + }); + } + onClose(); + showToast({ + text: Added section {data.name}, + }); + }; + + return ( + <> + + + + ); +}; + +export const AddElementButton = (props: ButtonProps) => { + return ( +
+ +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx new file mode 100644 index 000000000..81e00f2f0 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/FormFooter.tsx @@ -0,0 +1,63 @@ +import { Trans } from "@lingui/macro"; +import { useFormContext } from "react-hook-form"; + +import { IFullScreenModalProps } from "components/Modal/FullScreenModal"; +import { FooterStatus } from "components/status/footer"; +import { useToast } from "components/toast/toastProvider"; + +import { useSetCommunityConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; +import { jsonToConfig } from "plugins/lime-plugin-mesh-wide-config/src/utils/jsonParser"; + +export const FormFooter = ({ + onClose, + isDirty, +}: { isDirty: boolean } & Pick) => { + const { showToast } = useToast(); + const { handleSubmit } = useFormContext(); + const { mutate, isLoading } = useSetCommunityConfig({ + onError: () => { + showToast({ + text: Error updating the new configuration, + }); + }, + onSuccess: () => { + onClose(); + showToast({ + text: Starting mesh wide configuration change, + }); + }, + }); + const onSubmit = (data: IMeshWideConfig) => { + const newConfig = jsonToConfig(data); + mutate({ file_contents: newConfig }); + }; + + let message = No changes made; + if (isDirty) { + message = ( + <> + Changes made +
+ + Start mesh wide configuration update + + + ); + } + return ( + Start Lime Config update} + btnProps={{ + disabled: !isDirty || isLoading, + }} + onClick={() => { + handleSubmit(onSubmit)(); + }} + > +
{message}
+
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx new file mode 100644 index 000000000..0c2c5c548 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/FormOption.tsx @@ -0,0 +1,120 @@ +import { Trans } from "@lingui/macro"; +import { useState } from "preact/hooks"; +import { FormProvider, useForm, useFormContext } from "react-hook-form"; + +import { useDisclosure } from "components/Modal/useDisclosure"; +import { Button } from "components/buttons/button"; +import Divider from "components/divider"; +import { useToast } from "components/toast/toastProvider"; + +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; +import { EditableField } from "plugins/lime-plugin-mesh-wide-config/src/components/FormEdit"; +import { DeletePropModal } from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +type OptionContainerProps = { + sectionName: string; + keyString: string; +}; + +export const OptionContainer = ({ + keyString, + sectionName, +}: OptionContainerProps) => { + const { watch, setValue } = useFormContext(); + const [isEditing, setIsEditing] = useState(false); + const { + open: isDeleteModalOpen, + onOpen: openDeleteModal, + onClose: onCloseDeleteModal, + } = useDisclosure(); + + const { showToast } = useToast(); + + const onDelete = async () => { + const newValues = { ...section }; + delete newValues[keyString]; + setValue(sectionName, newValues); + onCloseDeleteModal(); + showToast({ + text: Deleted {keyString}, + onAction: () => { + setValue(sectionName, section); + }, + }); + }; + + const name = `${sectionName}[${keyString}]`; + const value = watch(name); + const section = watch(sectionName); + + let _value = value; + const isList = Array.isArray(value); + if (isList) { + _value = value.join(", "); + } + + const fmethods = useForm({ + defaultValues: { [sectionName]: { [keyString]: value } }, + }); + + const onSubmit = (data: IMeshWideConfig) => { + const newSectionValues = { ...section, ...data[sectionName] }; + setValue(sectionName, newSectionValues); + setIsEditing(false); + }; + + return ( +
+
+ +
+
+
+
+ {isList && (List)} {keyString} +
+ setIsEditing((prev) => !prev)} + onDelete={openDeleteModal} + /> +
+ {!isEditing &&
{_value}
} + {isEditing && ( + +
+ +
+ + +
+ +
+ )} +
+ +
+ ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/FormSection.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/FormSection.tsx new file mode 100644 index 000000000..63f32421c --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/FormSection.tsx @@ -0,0 +1,80 @@ +import { Trans } from "@lingui/macro"; +import { useFormContext } from "react-hook-form"; + +import { useDisclosure } from "components/Modal/useDisclosure"; +import { Collapsible } from "components/collapsible"; +import { useToast } from "components/toast/toastProvider"; + +import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; +import { AddNewConfigSection } from "plugins/lime-plugin-mesh-wide-config/src/components/FormEdit"; +import { OptionContainer } from "plugins/lime-plugin-mesh-wide-config/src/components/FormOption"; +import { + DeletePropModal, + EditPropModal, +} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; +import { IMeshWideSection } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +export const FormSection = ({ + title, + dropdown, +}: { + title: string; + dropdown: IMeshWideSection; +}) => { + return ( + } + > + {Object.entries(dropdown).map(([key, value]) => ( + + ))} + + + ); +}; + +export const SectionEditOrDelete = ({ name }) => { + const { + open: isDeleteModalOpen, + onOpen: openDeleteModal, + onClose: onCloseDeleteModal, + } = useDisclosure(); + const { showToast } = useToast(); + const { watch, setValue, reset } = useFormContext(); + + const onDelete = async () => { + const form = watch(); + const newForm = { ...form }; + delete newForm[name]; + reset(newForm); + onCloseDeleteModal(); + showToast({ + text: ( + + Deleted {name} - {new Date().toDateString()} + + ), + onAction: () => { + reset(form); + }, + }); + }; + + return ( + <> + + + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx deleted file mode 100644 index 361e2081a..000000000 --- a/plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Trans } from "@lingui/macro"; - -import { FooterStatus } from "components/status/footer"; -import { useToast } from "components/toast/toastProvider"; - -export const MeshStatus = () => { - const { showToast } = useToast(); - return ( - { - showToast({ - text: ( - <> - - Updating shared state{" "} - {new Date().toDateString()} - - - ), - }); - }} - > -
- 10 of 12 node are ready to update -
- - Last update: 30 second ago - -
-
- ); -}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx deleted file mode 100644 index 5e805fb88..000000000 --- a/plugins/lime-plugin-mesh-wide-config/src/components/OptionForm.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import { Trans } from "@lingui/macro"; -import { useState } from "preact/hooks"; -import { SubmitHandler, useForm } from "react-hook-form"; - -import { useDisclosure } from "components/Modal/useDisclosure"; -import { Button } from "components/buttons/button"; -import Divider from "components/divider"; -import InputField from "components/inputs/InputField"; -import { useToast } from "components/toast/toastProvider"; - -import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components"; -import { - DeletePropModal, - EditPropModal, -} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; - -const EditOptionForm = ({ - keyString, - value, - onSubmit, -}: { - keyString: string; - value: string; - onSubmit?: (data) => void; -}) => { - const { - register, - handleSubmit, - formState: { errors }, - } = useForm({ - defaultValues: { key: keyString, value }, - }); - - const _onSubmit: SubmitHandler = (data) => { - onSubmit(data); - }; - - return ( -
- Key} - register={register} - /> - Value} - register={register} - /> - - - ); -}; - -export const OptionContainer = ({ - keyString, - value, -}: { - keyString: string; - value: string; -}) => { - const { - open: isDeleteModalOpen, - onOpen: openDeleteModal, - onClose: onCloseDeleteModal, - } = useDisclosure(); - const { showToast } = useToast(); - - const onDelete = async () => { - console.log("delete stuff"); - onCloseDeleteModal(); - showToast({ - text: ( - - Deleted {keyString} - {new Date().toDateString()} - - ), - onAction: () => { - console.log("Undo action"); - }, - }); - }; - const [isEditing, setIsEditing] = useState(false); - - const toggleIsEditing = () => setIsEditing(!isEditing); - - return ( -
-
- -
-
- {!isEditing ? ( - <> -
-
{keyString}
- -
-
{value}
- - ) : ( - { - console.log("edited stuff", data); - toggleIsEditing(); - showToast({ - text: Edited {data.key}, - }); - }} - /> - )} -
- -
- ); -}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx new file mode 100644 index 000000000..67bef8055 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/components/StepStates.tsx @@ -0,0 +1,108 @@ +import { Trans } from "@lingui/macro"; + +import { + MeshUpgradeErrorIcon, + MeshUpgradeSuccessIcon, + ParallelErrors, + StepState, +} from "components/mesh-wide-wizard/StepState"; + +import { + useParallelConfirmConfig, + useParallelReadyForApply, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { useMeshConfig } from "plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider"; + +export const RestartScheduled = () => { + const { totalNodes } = useMeshConfig(); + const { errors, results } = useParallelReadyForApply(); + + return ( + Restart is scheduled!}> + <> + + {results?.length} of {totalNodes} will be upgraded + + {errors?.length > 0 && } + + + ); +}; + +export const RadyForApply = () => { + const { allNodesReadyForApply } = useMeshConfig(); + const title = ( +
+ Ready for apply new configuration +
+ ); + + return ( + + {!allNodesReadyForApply && ( +
+ + Some nodes have not the new configuration yet or are not + ready for apply it. +
+ Check network page for more information +
+
+ )} +
+ ); +}; + +export const Confirmed = () => { + const { errors } = useParallelConfirmConfig(); + let icon = ; + let title = Confirmed!; + let desc = New configuration confirmed successfully; + if (errors?.length > 0) { + icon = ; + title = Confirmed with some errors; + desc = New configuration was confirmed with some errors; + } + + return ( + + {desc} + {errors?.length > 0 && } + + ); +}; + +export const ConfirmationPending = () => { + const { errors } = useParallelConfirmConfig(); + const title = ( + + Configuration applied! +
+ Awaiting confirmation +
+ ); + + return ( + + <> + + Check if network is working properly and confirm the new + configuration +
+ If not confirmed, the new configuration will be rolled back + after a while +
+ {errors?.length > 0 && } + +
+ ); +}; + +export const DefaultState = () => { + return ( + Apply mesh wide new configuration!} + icon={} + /> + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx index 82ee1fd77..c17063e36 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx @@ -1,14 +1,27 @@ -import { Trans } from "@lingui/macro"; -import { useForm } from "react-hook-form"; +import { Trans, t } from "@lingui/macro"; +import { Label } from "@tanstack/react-query-devtools/build/lib/Explorer"; +import { Controller, FormProvider, useForm } from "react-hook-form"; import { Modal, ModalProps } from "components/Modal/Modal"; import InputField from "components/inputs/InputField"; +import switchStyle from "components/switch"; + +import { EditableField } from "plugins/lime-plugin-mesh-wide-config/src/components/FormEdit"; +import { + useParallelConfirmConfig, + useParallelReadyForApply, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { useMeshConfig } from "plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider"; +import { + IUseParallelQueriesModalProps, + ParallelQueriesModal, +} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/modals"; export const DeletePropModal = ({ prop, ...rest }: { prop: string } & Pick) => ( - Delete property} {...rest}> + Delete property} cancelBtn {...rest}>
Are you sure you want to delete the {prop}{" "} @@ -39,37 +52,193 @@ export const EditPropModal = ({ export interface AddNewSectionFormProps { name: string; + value?: string; + values?: string[]; + isList?: boolean; } export const AddNewSectionModal = ({ onSuccess, + sectionName, ...rest -}: { onSuccess: (data: AddNewSectionFormProps) => void } & Pick< - ModalProps, - "isOpen" | "onClose" ->) => { +}: { + onSuccess: (data: AddNewSectionFormProps) => void; + sectionName?: string; +} & Pick) => { + const fmethods = useForm({ + defaultValues: { name: "", value: "", values: [], isList: false }, + }); + + const handleSuccess = (data: AddNewSectionFormProps) => { + onSuccess(data); // Call the parent onSuccess handler + reset(); // Reset the form after successful submission + }; + const { register, handleSubmit, formState: { errors }, - } = useForm({ - defaultValues: { name: "" }, - }); + watch, + reset, + control, + } = fmethods; + + let title = Add new section; + if (sectionName) { + title = Add new section for {sectionName}; + } + + const isList = watch("isList"); + return ( + +
+ Add} + cancelBtn + {...rest} + onSuccess={handleSubmit(handleSuccess)} + > + ( + key} + className="w-100" + error={error?.message} + {...field} + /> + )} + /> + {sectionName && ( + <> +
+ + +
+ + + + )} +
+
+
+ ); +}; + +export const AbortModal = ({ + ...props +}: Pick) => { + const { abort } = useMeshConfig(); + const title = Abort current mesh wide configuration update?; + const content = ( + + This will the abort current configuration update process on all + nodes. Are you sure you want to proceed? + + ); + const btnTxt = Abort; return ( Add new section
} - successBtnText={Add} - {...rest} - onSuccess={handleSubmit(onSuccess)} + title={title} + deleteBtnText={btnTxt} + onDelete={() => { + abort(); + props.onClose(); + }} + {...props} > -
- Name} - register={register} - /> -
+ {content} ); }; + +export const ScheduleSafeRebootModal = ( + props: IUseParallelQueriesModalProps +) => { + const { callMutations: startScheduleMeshUpgrade } = + useParallelReadyForApply(); + + let title = All nodes are ready; + let content = ( + + Apply configuration on all of them with a scheduled safe reboot? + + ); + if (!props.isSuccess) { + title = Some nodes are not ready; + content = ( + + Are you sure you want to apply the configuration to the nodes + that are ready?
+ This will make some of them to reboot +
+ Check node list to see the network status +
+ ); + } + + return ( + { + startScheduleMeshUpgrade(); + props.onClose(); + }} + title={title} + {...props} + > + {content} + + ); +}; + +export const ConfirmModal = (props: IUseParallelQueriesModalProps) => { + const { callMutations } = useParallelConfirmConfig(); + let title = All nodes applied the configuration; + let content = ( + + Confirm configuration works properlly for al updated nodes + + ); + // this is not yet imlemented since we are not storing any information of mesh previous state + if (!props.isSuccess) { + title = Some nodes don't upgraded properly; + content = ( + + Are you sure you want to confirm the upgrade?
+ Check node list to see the network status +
+ ); + } + return ( + { + callMutations(); + props.onClose(); + }} + title={title} + {...props} + > + {content} + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx b/plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx deleted file mode 100644 index d922c7233..000000000 --- a/plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Trans } from "@lingui/macro"; - -import { - FullScreenModal, - IFullScreenModalProps, -} from "components/Modal/FullScreenModal"; - -import { - AddNewSectionBtn, - ConfigSection, -} from "plugins/lime-plugin-mesh-wide-config/src/components/ConfigSection"; -import { MeshStatus } from "plugins/lime-plugin-mesh-wide-config/src/components/MeshStatus"; -import { useMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; - -const EditConfiguration = (props: Partial) => { - const { data: meshWideConfig, isLoading } = useMeshWideConfig({}); - - return ( - Mesh wide config} - isLoading={isLoading} - {...props} - > - {meshWideConfig && ( - <> -
- {meshWideConfig.map((dropdown, index) => ( - - ))} - -
- - - )} -
- ); -}; - -export default EditConfiguration; diff --git a/plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm.tsx b/plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm.tsx new file mode 100644 index 000000000..e905e77e1 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm.tsx @@ -0,0 +1,87 @@ +import { Trans } from "@lingui/macro"; +import { useEffect, useRef, useState } from "preact/hooks"; +import { FormProvider, useForm } from "react-hook-form"; + +import { + FullScreenModal, + IFullScreenModalProps, +} from "components/Modal/FullScreenModal"; + +import { AddNewConfigSection } from "plugins/lime-plugin-mesh-wide-config/src/components/FormEdit"; +import { FormFooter } from "plugins/lime-plugin-mesh-wide-config/src/components/FormFooter"; +import { FormSection } from "plugins/lime-plugin-mesh-wide-config/src/components/FormSection"; +import { useCommunityConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +import { isEmpty } from "utils/utils"; + +const LimeConfigEditForm = (props: Partial) => { + const { data: meshWideConfig, isLoading } = useCommunityConfig({}); + + return ( + Mesh wide config} + isLoading={isLoading} + {...props} + > + {!!meshWideConfig && ( + + )} + + ); +}; + +const EditConfigForm = ({ + meshWideConfig, + onClose, +}: { + meshWideConfig: IMeshWideConfig; +} & Pick) => { + const [isDirty, setIsDirty] = useState(false); + const fMethods = useForm({ + defaultValues: meshWideConfig, + }); + const defaultValuesRef = useRef(meshWideConfig); + + const formData = fMethods.watch(); + + // compare values on each change + useEffect(() => { + setIsDirty( + JSON.stringify(formData) !== + JSON.stringify(defaultValuesRef.current) + ); + }, [formData]); + + return ( + +
+
+ {Object.entries(formData).map( + ([title, dropdown], index) => ( + + ) + )} + {!formData || + (isEmpty(formData) && ( + + Your Lime Community file seems empty! Please add + some configurations. + + ))} + +
+ + +
+ ); +}; + +export default LimeConfigEditForm; diff --git a/plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx b/plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx new file mode 100644 index 000000000..67b06b3be --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter.tsx @@ -0,0 +1,161 @@ +import { Trans } from "@lingui/macro"; +import { useState } from "preact/hooks"; +import { useMemo } from "react"; + +import { useDisclosure } from "components/Modal/useDisclosure"; +import { StatusIcons } from "components/icons/status"; +import { FooterStatus } from "components/status/footer"; +import { IStatusAndButton } from "components/status/statusAndButton"; + +import { + AbortModal, + ConfirmModal, + ScheduleSafeRebootModal, +} from "plugins/lime-plugin-mesh-wide-config/src/components/modals"; +import LimeConfigEditForm from "plugins/lime-plugin-mesh-wide-config/src/containers/LimeConfigEditForm"; +import { useParallelReadyForApply } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { ConfigUpdateState } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; +import { useMeshConfig } from "plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider"; + +function isShowAbortButtonState(value: string): value is ConfigUpdateState { + return [ + "READY_FOR_APPLY", + "RESTART_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + ].includes(value); +} + +const NextStepFooter = () => { + const { + open: showAbort, + onOpen: openAbort, + onClose: closeAbort, + } = useDisclosure(); + const { + open: showScheduleModal, + onOpen: openScheduleModal, + onClose: closeScheduleModal, + } = useDisclosure(); + + const { + open: showConfirmationModal, + onOpen: openConfirmationModal, + onClose: closeConfirmationModal, + } = useDisclosure(); + const [showEditConfig, setShowEditConfig] = useState(false); + + const { wizardState, allNodesReadyForApply } = useMeshConfig(); + const { errors: scheduleErrors } = useParallelReadyForApply(); + + const step: IStatusAndButton | null = useMemo(() => { + let step: IStatusAndButton | null = null; + if (showEditConfig) return null; + + switch (wizardState) { + case "ABORTED": + case "DEFAULT": + step = { + status: "success", + onClick: () => { + setShowEditConfig(true); + }, + btn: Change LiMe Config, + children: ( + + You can change shared network configuration + + ), + }; + break; + case "READY_FOR_APPLY": { + let status: StatusIcons = "success"; + let text = ( + + All nodes have the configuration ready to apply + + ); + if (!allNodesReadyForApply) { + status = "warning"; + text = ( + + Some nodes are not marked as ready to apply + + ); + } + step = { + status, + onClick: openScheduleModal, + btn: Apply new configuration, + children: text, + }; + break; + } + case "RESTART_SCHEDULED": { + const data: Omit = { + onClick: openScheduleModal, + btn: Schedule again, + }; + if (scheduleErrors?.length) { + step = { + ...data, + status: "warning", + children: Some nodes have errors, + }; + } + step = { + ...data, + status: "success", + children: All nodes scheduled successful, + }; + break; + } + case "CONFIRMATION_PENDING": + step = { + status: "success", + onClick: openConfirmationModal, + children: Confirm configuration on all nodes, + btn: Confirm, + }; + break; + } + if (isShowAbortButtonState(wizardState)) { + const showAbort: Pick< + IStatusAndButton, + "btnCancel" | "onClickCancel" + > = { + btnCancel: Abort, + onClickCancel: openAbort, + }; + step = { ...step, ...showAbort }; + } + return step; + }, [allNodesReadyForApply, openAbort, showEditConfig, wizardState]); + + if (showEditConfig) { + return setShowEditConfig(false)} />; + } + + return ( + <> + {step && ( + + {step.children} + + )} + + + + + ); +}; + +export default NextStepFooter; diff --git a/plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx b/plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx new file mode 100644 index 000000000..4a7b68f84 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage.tsx @@ -0,0 +1,166 @@ +import { Trans } from "@lingui/macro"; +import { ComponentChildren } from "preact"; + +import { StatusIcons } from "components/icons/status"; +import NodeInfoListItem, { + INodeInfoBodyItemProps, +} from "components/mesh-wide-wizard/NodeInfoListItem"; +import { NodesListWrapper } from "components/mesh-wide-wizard/NodesListWrapper"; + +import { useMeshWideConfigState } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { meshConfigStateKey } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys"; +import { + ConfigUpdateState, + MainNodeStatusType, + MeshWideNodeConfigInfo, + NodeMeshConfigInfo, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +const NodeConfigItem = ({ + info, + name, +}: { + info: MeshWideNodeConfigInfo; + name: string; +}) => { + const status: StatusIcons = + info.transaction_state === "ERROR" || + info.transaction_state === "ABORTED" + ? "warning" + : "success"; + + // Description under node name + let descriptionMsg = InfoStatusMessageMap[info.transaction_state] ?? ( + Error retrieving the status + ); + + // Firt info when opening the accordion + const nodeStatusInfo: INodeInfoBodyItemProps = + detailedInfoStatusMessageMap(info)[info.transaction_state] ?? + detailedInfoStatusMessageMap()["DEFAULT"]; + + // Main node status message + const mainNodeStatusInfo = mainNodeStatusMessageMap[info.main_node]; + if (mainNodeStatusInfo) { + descriptionMsg = (Main Node) {descriptionMsg}; + } + + // Extra information from the state + const extraInfoItems: Array = [ + nodeStatusInfo, + ...(mainNodeStatusInfo ? [mainNodeStatusInfo] : []), + { + title: Ip, + description: {info.node_ip}, + }, + ]; + return ( + + ); +}; + +const NodesListPage = () => { + const { data, isLoading } = useMeshWideConfigState({}); + return ( + + ); +}; + +export const InfoStatusMessageMap: { + [status in ConfigUpdateState]: ComponentChildren; +} = { + DEFAULT: No update in progres, + READY_FOR_APPLY: Ready for apply, + RESTART_SCHEDULED: Restart scheduled, + CONFIRMATION_PENDING: Confirmation pending, + CONFIRMED: Confirmed, + ERROR: This node has an error, + ABORTED: This node aborted successfully, +}; + +type DetailedInfoStatusMessageMapType = { + [status in ConfigUpdateState]: INodeInfoBodyItemProps; +}; +export const detailedInfoStatusMessageMap = ( + nodeInfo?: NodeMeshConfigInfo +): DetailedInfoStatusMessageMapType => { + return { + DEFAULT: { + title: Everything is up to date!, + description: ( + Mesh configuration is on the last version + ), + }, + READY_FOR_APPLY: { + title: New configuration is on the node, + description: ( + This node is awaiting to apply the configuration + ), + }, + RESTART_SCHEDULED: { + title: The update is scheduled, + description: ( + + After a time the new configuration will be installed and the + node will reboot + + ), + }, + CONFIRMATION_PENDING: { + title: Awaiting confirmation, + description: ( + + The configuration seems to be updated successfully. Confirm + that the node is working properly or will be downgraded to + the previous version + + ), + }, + CONFIRMED: { + title: Configuration applied, + description: ( + + Congratulations, this node has the new configuration working + on it + + ), + }, + ERROR: { + title: This node has an error!, + description: nodeInfo.error, + }, + ABORTED: { + title: This node aborted, + description: ( + Start mesh wide configuration update again + ), + }, + }; +}; + +type MainNodeInfoStatusMessageMapType = { + [status in MainNodeStatusType]: INodeInfoBodyItemProps; +}; + +export const mainNodeStatusMessageMap: MainNodeInfoStatusMessageMapType = { + NO: null, + MAIN_NODE: { + title: This is a main node, + description: ( + This node is sending new configuration to others + ), + }, +}; + +export default NodesListPage; diff --git a/plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx b/plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx new file mode 100644 index 000000000..d56f84bc6 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage.tsx @@ -0,0 +1,69 @@ +import { Trans } from "@lingui/macro"; + +import { ErrorState } from "components/mesh-wide-wizard/ErrorState"; +import { LoadingPage } from "components/mesh-wide-wizard/LoadingPage"; + +import { + ConfirmationPending, + Confirmed, + DefaultState, + RadyForApply, + RestartScheduled, +} from "plugins/lime-plugin-mesh-wide-config/src/components/StepStates"; +import { useMeshConfig } from "plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider"; + +const StatusPage = () => { + const { wizardState, nodeInfo } = useMeshConfig(); + + switch (wizardState) { + case "ERROR": + return ; + case "READY_FOR_APPLY": + return ; + case "RESTART_SCHEDULED": + return ; + case "CONFIRMED": + return ; + case "ABORTING": + return ( + Aborting} + description={ + + Sending abort message to this node. The abort order + will be propagated to all nodes. + + } + /> + ); + case "CONFIRMATION_PENDING": + return ; + case "SENDING_START_SCHEDULE": + return ( + Scheduling apply configuration} + description={ + + Schedule apply configuration to all available nodes + + } + /> + ); + case "SENDING_CONFIRMATION": + return ( + Sending confirmation} + description={ + + Confirming new configuration to available nodes + + } + /> + ); + case "DEFAULT": + default: + return ; + } +}; + +export default StatusPage; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts b/plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts deleted file mode 100644 index fc92ad20c..000000000 --- a/plugins/lime-plugin-mesh-wide-config/src/meshConfigApi.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; - -export const getMeshWideConfig = async () => meshWideConfig; - -const options = { - primary_interface: "eth0", - main_ipv4_address: "10.170.128.0/16/17", -}; - -const meshWideConfig: IMeshWideConfig = [ - { - name: "lime system", - options, - }, - { - name: "lime network", - options, - }, - { - name: "lime wifi", - options, - }, - { - name: "generic_uci_config prometheus", - options, - }, - { - name: "run_asset prometheus_enable", - options, - }, -]; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx index e77b07a37..34d1e15cf 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigPage.tsx @@ -1,19 +1,46 @@ -import { useState } from "preact/hooks"; import React from "react"; -import { Button } from "components/elements/button"; +import { AbortedNotification } from "components/mesh-wide-wizard/StepState"; +import WizardWrapper from "components/mesh-wide-wizard/WizardWrapper"; -import EditConfiguration from "plugins/lime-plugin-mesh-wide-config/src/containers/EditConfiguration"; +import NextStepFooter from "plugins/lime-plugin-mesh-wide-config/src/containers/NextStepFooter"; +import NodesListPage from "plugins/lime-plugin-mesh-wide-config/src/containers/NodesListPage"; +import StatusPage from "plugins/lime-plugin-mesh-wide-config/src/containers/StatusPage"; +import { + ConfigProvider, + useMeshConfig, +} from "plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider"; -const MeshConfigPage = () => { - // State to show modal - const [showEditConfig, setShowEditConfig] = useState(false); +const MeshConfig = () => { + const { + isLoading: meshConfigLoading, + meshInfo, + nodeInfo, + wizardState, + isError, + error, + } = useMeshConfig(); - if (showEditConfig) { - return setShowEditConfig(false)} />; - } + const isLoading = + meshConfigLoading || nodeInfo === undefined || meshInfo === undefined; - return ; + return ( + + ); }; +const MeshConfigPage = () => ( + + + +); + export default MeshConfigPage; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx index 396d49afd..f4afb82c9 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries.tsx @@ -1,14 +1,213 @@ -import { useQuery } from "@tanstack/react-query"; - -import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigApi"; -import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; - -export function useMeshWideConfig(params) { - return useQuery( - ["lime-meshwide", "get_mesh_config"], - getMeshWideConfig, - { - ...params, - } +import { + UseMutationOptions, + UseQueryOptions, + useMutation, + useQuery, +} from "@tanstack/react-query"; + +import { + RemoteNodeCallError, + callToRemoteNode, + doSharedStateApiCall, +} from "components/shared-state/SharedStateApi"; +import { sharedStateQueries } from "components/shared-state/SharedStateQueriesKeys"; + +import { + MeshConfigQueryKeys, + meshConfigStateKey, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys"; +import { + GetCommunityConfigResponse, + IMeshWideConfig, + MeshWideConfigState, + NodeMeshConfigInfo, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; +import { parseConfigFile } from "plugins/lime-plugin-mesh-wide-config/src/utils/jsonParser"; +import { MeshWideRPCReturnTypes } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { getNodeIpsByConfigCondition } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; + +import { + IMutationFnVariables, + useMeshWideSyncCall, +} from "utils/meshWideSyncCall"; +import { + ApiServiceParamsType, + StandarizedApiError, + standarizedApiCall, +} from "utils/standarizedApi"; + +export const useCommunityConfig = ( + params?: Omit< + UseQueryOptions, + "queryFn" | "queryKey" + > +) => { + return useQuery({ + queryKey: MeshConfigQueryKeys.getCommunityConfig, + queryFn: () => + standarizedApiCall({ + args: MeshConfigQueryKeys.getCommunityConfig, + }), + select: (data) => parseConfigFile(data.file_contents), + ...params, + }); +}; + +interface SetCommunityConfigParams { + file_contents: string; +} + +export const useSetCommunityConfig = ( + params?: Omit< + UseMutationOptions< + MeshWideRPCReturnTypes, + StandarizedApiError, + SetCommunityConfigParams + >, + "mutationFn" | "mutationKey" + > +) => { + return useMutation< + MeshWideRPCReturnTypes, + StandarizedApiError, + SetCommunityConfigParams + >({ + mutationKey: MeshConfigQueryKeys.setCommunityConfig, + mutationFn: (args) => + standarizedApiCall({ + args: [...MeshConfigQueryKeys.setCommunityConfig, args], + }), + ...params, + }); +}; + +export const useMeshWideConfigState = ( + params?: Omit, "queryFn" | "queryKey"> +) => { + const queryKey = sharedStateQueries.getFromSharedState( + meshConfigStateKey + ) as ApiServiceParamsType; + return useQuery({ + queryKey, + queryFn: () => doSharedStateApiCall<"mesh_config">(queryKey), + ...params, + }); +}; + +export const useConfigNodeState = ( + params?: Omit, "queryFn" | "queryKey"> +) => { + return useQuery({ + queryKey: MeshConfigQueryKeys.getNodeStatus, + queryFn: () => + standarizedApiCall({ + args: MeshConfigQueryKeys.getNodeStatus, + }), + ...params, + }); +}; + +export const useParallelAbort = (opts?) => { + // State to store the errors + const { data: nodes } = useMeshWideConfigState(); + const ips = getNodeIpsByConfigCondition(nodes, (node) => + [ + "UPGRADE_SCHEDULED", + "CONFIRMATION_PENDING", + "ERROR", + "READY_FOR_APPLY", + "RESTART_SCHEDULED", + ].includes(node.transaction_state) ); + return useMeshWideSyncCall({ + mutationKey: MeshConfigQueryKeys.remoteAbort, + // mutationFn: remoteAbort, + mutationFn: ({ ip }) => + callToRemoteNode({ + ip, + apiCall: (customApi) => + standarizedApiCall({ + apiService: customApi, + args: MeshConfigQueryKeys.remoteAbort, + }), + }), + ips, + options: opts, + }); +}; + +// Parallel queries + +interface StartSafeRebootParams { + confirm_timeout: number; + start_delay: number; } +export type UseParallelReadyForApplyType = ReturnType< + typeof useParallelReadyForApply +>; +export const useParallelReadyForApply = ( + opts?: UseMutationOptions< + MeshWideRPCReturnTypes, + RemoteNodeCallError, + IMutationFnVariables + > +) => { + // State to store the errors + const { data: nodes } = useMeshWideConfigState({}); + const ips = getNodeIpsByConfigCondition( + nodes, + (node) => node.transaction_state === "READY_FOR_APPLY" + ); + return useMeshWideSyncCall({ + mutationKey: MeshConfigQueryKeys.startSafeReboot, + mutationFn: ({ ip, variables }) => + callToRemoteNode({ + ip, + apiCall: (customApi) => + standarizedApiCall({ + apiService: customApi, + args: [ + ...MeshConfigQueryKeys.startSafeReboot, + variables ?? { + confirm_timeout: 2001, + start_delay: 63, + }, + ], + }), + }), + ips, + options: opts, + }); +}; + +export type UseParallelConfirmConfig = ReturnType< + typeof useParallelConfirmConfig +>; +export const useParallelConfirmConfig = ( + opts?: UseMutationOptions< + MeshWideRPCReturnTypes, + RemoteNodeCallError, + IMutationFnVariables + > +) => { + // State to store the errors + const { data: nodes } = useMeshWideConfigState({}); + const ips = getNodeIpsByConfigCondition( + nodes, + (node) => node.transaction_state === "CONFIRMATION_PENDING" + ); + return useMeshWideSyncCall({ + mutationKey: MeshConfigQueryKeys.confirm, + mutationFn: ({ ip }) => + callToRemoteNode({ + ip, + apiCall: (customApi) => + standarizedApiCall({ + apiService: customApi, + args: [...MeshConfigQueryKeys.confirm], + }), + }), + ips, + options: opts, + }); +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys.tsx new file mode 100644 index 000000000..123cab948 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys.tsx @@ -0,0 +1,15 @@ +import { MeshConfigTypes } from "components/shared-state/SharedStateTypes"; + +export const MeshConfigQueryKeys: { + [key: string]: [string, string]; +} = { + getNodeStatus: ["lime-mesh-config", "get_node_status"], + getCommunityConfig: ["lime-mesh-config", "get_community_config"], + remoteConfirmUpgrade: ["lime-mesh-config", "start_config_transaction"], + startSafeReboot: ["lime-mesh-config", "start_safe_reboot"], + confirm: ["lime-mesh-config", "confirm"], + remoteAbort: ["lime-mesh-config", "abort"], + setCommunityConfig: ["lime-mesh-config", "start_config_transaction"], +}; + +export const meshConfigStateKey: keyof MeshConfigTypes = "mesh_config"; diff --git a/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx b/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx index d6e35770f..a8e24d546 100644 --- a/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx +++ b/plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes.tsx @@ -1,6 +1,55 @@ +export type ConfigItemType = string | string[]; + export interface IMeshWideSection { - name: string; - options: { [key: string]: string }; + [key: string]: ConfigItemType; +} + +export type IMeshWideConfig = { + [section: string]: IMeshWideSection; +}; + +export type GetCommunityConfigResponse = { + file_contents: string; +}; + +export type MainNodeStatusType = "NO" | "MAIN_NODE"; + +export type ConfigUpdateState = + | "DEFAULT" // When no config has changed + | "READY_FOR_APPLY" //the config is set in the node and is ready to reboot + | "RESTART_SCHEDULED" // the node will reboot in xx seconds + | "CONFIRMATION_PENDING" // the node rebooted and the configuration is not confirmed + | "CONFIRMED" // the configuration has been set and the user was able to confirm the change + | "ERROR" + | "ABORTED"; + +export interface NodeMeshConfigInfo { + timestamp: string; + main_node: MainNodeStatusType; + error: string; + node_ip: string; + transaction_state: ConfigUpdateState; + current_config_hash: string; + safe_restart_remaining: number; + retry_count: number; + safe_restart_start_time_out: number; + safe_restart_start_mark: number; + board_name: string; + safe_restart_confirm_timeout: number; +} + +export type MeshWideNodeConfigInfo = { + bleachTTL: number; + author: string; +} & NodeMeshConfigInfo; + +export interface MeshWideConfigState { + [key: string]: MeshWideNodeConfigInfo; } -export type IMeshWideConfig = IMeshWideSection[]; +export type StepperWizardState = + | "ABORTING" + | "APPLYING" // the node is applying the configuration + | "SENDING_START_SCHEDULE" + | "SENDING_CONFIRMATION" + | ConfigUpdateState; diff --git a/plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider.tsx b/plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider.tsx new file mode 100644 index 000000000..c4f2f5ed7 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/providers/useMeshConfigProvider.tsx @@ -0,0 +1,192 @@ +import { ComponentChildren, createContext } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import { useCallback, useContext, useMemo } from "react"; + +import { + UseParallelConfirmConfig, + UseParallelReadyForApplyType, + useConfigNodeState, + useMeshWideConfigState, + useParallelAbort, + useParallelConfirmConfig, + useParallelReadyForApply, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueries"; +import { MeshConfigQueryKeys } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigQueriesKeys"; +import { + NodeMeshConfigInfo, + StepperWizardState, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +import queryCache from "utils/queryCache"; + +const NODE_STATUS_REFETCH_INTERVAL = 5000; + +const getWizardState = ( + nodeInfo: NodeMeshConfigInfo | undefined, + isAborting: boolean, + scheduleSafeReboot: UseParallelReadyForApplyType | undefined, + confirmConfig: UseParallelConfirmConfig | undefined, + isNodeInfoError: boolean +): StepperWizardState => { + if (!nodeInfo) return; + if (isAborting) return "ABORTING"; + if (scheduleSafeReboot?.isLoading) { + return "SENDING_START_SCHEDULE"; + } + if ( + scheduleSafeReboot?.results?.length || + scheduleSafeReboot?.errors?.length + ) { + return "RESTART_SCHEDULED"; + } + if ( + nodeInfo.transaction_state === "CONFIRMATION_PENDING" || + nodeInfo.transaction_state === "CONFIRMED" + ) { + if (confirmConfig?.isLoading) { + return "SENDING_CONFIRMATION"; + } + if (confirmConfig?.errors?.length) { + return "CONFIRMATION_PENDING"; + } + } + // We suppose that if the upgrade is scheduled, and we lost the connection is because is upgrading + if (nodeInfo.transaction_state === "RESTART_SCHEDULED" && isNodeInfoError) { + return "APPLYING"; + } + return nodeInfo?.transaction_state ?? "DEFAULT"; +}; + +export const useMeshConfigProvider = () => { + // UseCallback to invalidate queries + const invalidateQueries = useCallback(() => { + return queryCache.invalidateQueries({ + queryKey: MeshConfigQueryKeys.getNodeStatus, + }); + }, []); + + const invalidateLogin = useCallback(() => { + queryCache.invalidateQueries({ + queryKey: ["session", "get"], + }); + }, []); + + const scheduleSafeReboot = useParallelReadyForApply(); + const confirmConfig = useParallelConfirmConfig(); + + const { + data: meshInfo, + isLoading: meshInfoLoading, + isError: isMeshInfoQueryError, + error: meshInfoQueryError, + } = useMeshWideConfigState({ + refetchInterval: NODE_STATUS_REFETCH_INTERVAL, + }); + const { + data: nodeInfo, + isLoading: nodeInfoLoading, + + isError: isNodeInfoError, + } = useConfigNodeState({ + refetchInterval: NODE_STATUS_REFETCH_INTERVAL, + }); + + // Inner state to control is aborting callback awaiting until query invalidation + const [isAborting, setIsAborting] = useState(false); + const { callMutations: abortMutation } = useParallelAbort(); + + const allNodesReadyForApply = useMemo(() => { + return Object.values(meshInfo || {}).every( + (node) => node.transaction_state === "READY_FOR_APPLY" + ); + }, [meshInfo]); + + const allNodesConfirmed = useMemo(() => { + return Object.values(meshInfo || {}).every( + (node) => node.transaction_state === "CONFIRMED" + ); + }, [meshInfo]); + + const isLoading = meshInfoLoading || nodeInfoLoading; + + const abort = useCallback(async () => { + setIsAborting(true); + abortMutation() + .then(() => { + return invalidateQueries(); + }) + .finally(() => { + setIsAborting(false); + }); + }, [abortMutation, invalidateQueries]); + + const wizardState: StepperWizardState = useMemo( + () => + getWizardState( + nodeInfo, + isAborting, + scheduleSafeReboot, + confirmConfig, + isNodeInfoError + ), + [nodeInfo, isAborting] + ); + + const totalNodes = meshInfo && Object.entries(meshInfo).length; + + let isError; + let error; + // If the state is upgrading, ignore the errors because is normal to lose the connection + if (wizardState !== "APPLYING") { + isError = isMeshInfoQueryError; + error = meshInfoQueryError; + } + + useEffect(() => { + if ( + meshInfoQueryError && + (meshInfoQueryError as any).code != null && + (meshInfoQueryError as any).code === -32002 // Auth failed error code + ) { + invalidateLogin(); + } + }, [invalidateLogin, meshInfoQueryError, wizardState]); + + return { + nodeInfo, + meshInfo, + isLoading, + allNodesReadyForApply, + allNodesConfirmed, + abort, + wizardState, + totalNodes, + isError, + error, + }; +}; + +export const ConfigContext = createContext< + ReturnType | undefined +>(undefined); + +export const ConfigProvider = ({ + children, +}: { + children: ComponentChildren; +}) => { + const config = useMeshConfigProvider(); + return ( + + {children} + + ); +}; + +export const useMeshConfig = () => { + const context = useContext(ConfigContext); + if (!context) { + throw new Error("useConfig must be used within an ConfigProvider"); + } + return context; +}; diff --git a/plugins/lime-plugin-mesh-wide-config/src/utils/jsonParser.ts b/plugins/lime-plugin-mesh-wide-config/src/utils/jsonParser.ts new file mode 100644 index 000000000..c4004911e --- /dev/null +++ b/plugins/lime-plugin-mesh-wide-config/src/utils/jsonParser.ts @@ -0,0 +1,71 @@ +import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; + +export const jsonToConfig = (json: IMeshWideConfig): string => { + let configFileContent = ""; + + for (const section in json) { + configFileContent += `config lime '${section}'\n`; + + for (const key in json[section]) { + const value = json[section][key]; + + if (Array.isArray(value)) { + // Handle lists + value.forEach((item) => { + configFileContent += `\tlist ${key} '${item}'\n`; + }); + } else { + // Handle single values (option) + configFileContent += `\toption ${key} '${value}'\n`; + } + } + configFileContent += "\n"; // Add a new line after each section + } + return configFileContent; +}; + +export const parseConfigFile = (data: string): IMeshWideConfig => { + // Replace escaped newlines with actual newlines + const lines = data.replace(/\\n/g, "\n").split("\n"); + const config: IMeshWideConfig = {}; + let configTitle = ""; + let sectionName = ""; + + lines.forEach((line) => { + line = line.trim(); + line = line.replace(/\\t/g, ""); + + // Ignore comments or empty lines + if (!line || line.startsWith("#")) { + return; + } + + if (line.startsWith("config")) { + // Extract the section name + const parts = line.split(" "); + configTitle = parts[1]; + sectionName = parts[2].replace(/'/g, ""); // remove single quotes + config[sectionName] = {}; + } else if (line.startsWith("option") || line.startsWith("list")) { + // Parse key-value pairs + const parts = line.split(" "); + const key = parts[1]; + const value = line + .split(/ (.+)/)[1] + .split(/ (.+)/)[1] + .replace(/'/g, ""); // strip quotes + + if (line.startsWith("list")) { + // Add value to list + if (!config[sectionName][key]) { + config[sectionName][key] = []; + } + (config[sectionName][key] as string[]).push(value); + } else { + // Assign value to option + config[sectionName][key] = value; + } + } + }); + return config; +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx index efa5464a9..a5ff57a2d 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/modals.tsx @@ -1,13 +1,7 @@ import { Trans } from "@lingui/macro"; -import { ComponentChildren, VNode } from "preact"; -import { useCallback } from "react"; +import { ComponentChildren } from "preact"; -import { - CallbackFn, - Modal, - ModalProps, - useModal, -} from "components/Modal/Modal"; +import { CallbackFn, Modal, ModalProps } from "components/Modal/Modal"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; import { @@ -15,7 +9,7 @@ import { useParallelScheduleUpgrade, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; -type IUseParallelQueriesModalProps = { +export type IUseParallelQueriesModalProps = { isSuccess: boolean; } & Pick; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx index e574d7a38..b36f3f91e 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo.tsx @@ -1,10 +1,11 @@ import { Trans } from "@lingui/macro"; -import { ComponentChildren } from "preact"; -import { StatusIcon, StatusIcons } from "components/icons/status"; -import { ListItemCollapsible } from "components/list-material"; -import UpdateSharedStateBtn from "components/shared-state/UpdateSharedStateBtn"; +import { StatusIcons } from "components/icons/status"; +import NodeInfoListItem, { + INodeInfoBodyItemProps, +} from "components/mesh-wide-wizard/NodeInfoListItem"; +import { meshUpgradeSharedStateKey } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys"; import { MeshWideNodeUpgradeInfo } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; import { InfoStatusMessageMap, @@ -12,18 +13,6 @@ import { mainNodeStatusMessageMap, } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages"; -export interface INodeInfoBodyItemProps { - title: ComponentChildren; - description: ComponentChildren; -} - -const NodeInfoBodyItem = ({ title, description }: INodeInfoBodyItemProps) => ( -
-
{title}
-
{description}
-
-); - const NodeUpgradeInfoItem = ({ info, name, @@ -34,46 +23,45 @@ const NodeUpgradeInfoItem = ({ const status: StatusIcons = info.upgrade_state === "ERROR" ? "warning" : "success"; - const nodeStatusInfo = + const nodeStatusInfo: INodeInfoBodyItemProps = detailedInfoStatusMessageMap(info)[info.upgrade_state] ?? detailedInfoStatusMessageMap()["DEFAULT"]; - const mainNodeStatusInfo = mainNodeStatusMessageMap[info.main_node]; let descriptionMsg = InfoStatusMessageMap[info.upgrade_state] ?? ( Error retrieving the status, is this node outdated? ); + + const mainNodeStatusInfo = mainNodeStatusMessageMap[info.main_node]; if (mainNodeStatusInfo) { descriptionMsg = (Main Node) {descriptionMsg}; } + + const extraInfoItems: Array = [ + nodeStatusInfo, + ...(mainNodeStatusInfo ? [mainNodeStatusInfo] : []), + { + title: Board, + description: {info.board_name}, + }, + { + title: Firmware version, + description: {info.current_fw}, + }, + { + title: Ip, + description: {info.node_ip}, + }, + ]; + return ( - } - rightText={ - - } - > - - {mainNodeStatusInfo && } - Board} - description={{info.board_name}} - /> - Firmware version} - description={{info.current_fw}} - /> - Ip} - description={{info.node_ip}} - /> - + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx index 6e10cb934..d510c9cec 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending.tsx @@ -2,8 +2,9 @@ import { Trans } from "@lingui/macro"; import { ParallelErrors, - UpgradeState, -} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + StepState, +} from "components/mesh-wide-wizard/StepState"; + import { useParallelConfirmUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; export const ConfirmationPending = () => { @@ -17,7 +18,7 @@ export const ConfirmationPending = () => { ); return ( - + <> Check if network is working properly and confirm the upgrade @@ -27,6 +28,6 @@ export const ConfirmationPending = () => { {errors?.length > 0 && } - + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx index a8e22df13..50a2d70f1 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed.tsx @@ -4,8 +4,9 @@ import { MeshUpgradeErrorIcon, MeshUpgradeSuccessIcon, ParallelErrors, - UpgradeState, -} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + StepState, +} from "components/mesh-wide-wizard/StepState"; + import { useParallelConfirmUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; export const Confirmed = () => { @@ -21,9 +22,9 @@ export const Confirmed = () => { } return ( - + {desc} {errors?.length > 0 && } - + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx index 1fa267cc4..dc893bace 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable.tsx @@ -1,9 +1,9 @@ import { Trans } from "@lingui/macro"; import LineChart, { LineChartStep } from "components/PathChart"; +import { StepState } from "components/mesh-wide-wizard/StepState"; import { useNewVersion } from "plugins/lime-plugin-firmware/src/firmwareQueries"; -import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; import { useBoardData } from "utils/queries"; @@ -73,10 +73,10 @@ export const NewVersionAvailable = ({ } return ( - +
-
+ ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx index 4b1638b4c..ed6199b14 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion.tsx @@ -2,12 +2,12 @@ import { Trans } from "@lingui/macro"; import { MeshUpgradeSuccessIcon, - UpgradeState, -} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + StepState, +} from "components/mesh-wide-wizard/StepState"; export const NoNewVersionAvailable = () => { return ( - No new version available!} icon={} /> diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx index 50d72f2fb..d9495ee90 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted.tsx @@ -1,6 +1,7 @@ import { Trans } from "@lingui/macro"; -import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; +import { StepState } from "components/mesh-wide-wizard/StepState"; + import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; export const TransactionStarted = () => { @@ -12,7 +13,7 @@ export const TransactionStarted = () => { ); return ( - + {someNodeDownloading && (
@@ -22,6 +23,6 @@ export const TransactionStarted = () => {
)} -
+ ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx index ed9d15efb..b76c8a622 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled.tsx @@ -2,8 +2,9 @@ import { Trans } from "@lingui/macro"; import { ParallelErrors, - UpgradeState, -} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + StepState, +} from "components/mesh-wide-wizard/StepState"; + import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; import { useParallelScheduleUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueries"; @@ -13,13 +14,13 @@ export const UpgradeScheduled = () => { const nodesToBeUpgraded = results?.length; return ( - Upgrade is scheduled!}> + Upgrade is scheduled!}> <> {nodesToBeUpgraded} of {totalNodes} will be upgraded {errors?.length > 0 && } - + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx index 8588d8d16..71fda0b31 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus.tsx @@ -1,17 +1,17 @@ import { Trans } from "@lingui/macro"; +import { ErrorState } from "components/mesh-wide-wizard/ErrorState"; +import { LoadingPage } from "components/mesh-wide-wizard/LoadingPage"; + import { ConfirmationPending } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ConfirmationPending"; import { Confirmed } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/Confirmed"; -import { ErrorState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState"; -import { LoadingPage } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage"; import { NewVersionAvailable } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NewVersionAvailable"; import { NoNewVersionAvailable } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/NoNewVersion"; import { TransactionStarted } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/TransactionStarted"; import { UpgradeScheduled } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeScheduled"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; -import { CenterFlex } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs"; -const MeshWideUpgradeStatusState = () => { +export const MeshWideUpgradeStatus = () => { const { stepperState, meshWideError } = useMeshUpgrade(); switch (stepperState) { @@ -71,11 +71,3 @@ const MeshWideUpgradeStatusState = () => { return ; } }; - -export const MeshWideUpgradeStatus = () => { - return ( - - - - ); -}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx index 4703c6857..b4345b9f2 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList.tsx @@ -1,47 +1,15 @@ -import { Trans } from "@lingui/macro"; - -import Loading from "components/loading"; +import { NodesListWrapper } from "components/mesh-wide-wizard/NodesListWrapper"; import NodeUpgradeInfoItem from "plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo"; -import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; import { useMeshUpgrade } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; -import { CenterFlex } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs"; export const NodesList = () => { const { data, isLoading } = useMeshUpgrade(); - - if (isLoading) { - return ; - } - - if (!data || (data && Object.keys(data).length === 0)) { - return ( - - - No nodes present on the
- mesh wide upgrade state yet! - - } - /> -
- ); - } - return ( - <> - {data && - Object.entries(data).map(([key, nodeInfo], index) => { - return ( - - ); - })} - + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx index 24fa6921b..384e517d5 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeApi.tsx @@ -1,27 +1,23 @@ -import { - MeshUpgradeApiError, - callToRemoteNode, -} from "components/shared-state/SharedStateApi"; +import { callToRemoteNode } from "components/shared-state/SharedStateApi"; import { sharedStateQueries } from "components/shared-state/SharedStateQueriesKeys"; +import { meshUpgradeSharedStateKey } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys"; import { MeshWideRPCReturnTypes, MeshWideUpgradeInfo, NodeMeshUpgradeInfo, } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; +import { ApiServiceParamsType, standarizedApiCall } from "utils/standarizedApi"; import api, { UhttpdService } from "utils/uhttpd.service"; -// todo(kon): refactor this to use doSharedStateApiCall?? export const getMeshWideUpgradeInfo = async () => { - const query = sharedStateQueries.getFromSharedState("mesh_wide_upgrade"); - const res = await api.call(...query); - if (res.error) { - throw new Error( - `Error getting mesh wide upgrade info from shared state async, code error ${res.error}` - ); - } - return res.data as MeshWideUpgradeInfo; + const query = sharedStateQueries.getFromSharedState( + meshUpgradeSharedStateKey + ); + return standarizedApiCall({ + args: query as ApiServiceParamsType, + }); }; export const getMeshUpgradeNodeStatus = async () => { @@ -73,13 +69,10 @@ const meshUpgradeApiCall = async ( customApi?: UhttpdService ) => { const httpService = customApi || api; - const res = (await httpService.call( - "lime-mesh-upgrade", - method, - {} - )) as MeshWideRPCReturnTypes; - if (res.error) { - throw new MeshUpgradeApiError(res.error, res.code); - } - return res.code; + return ( + (await standarizedApiCall({ + apiService: httpService, + args: ["lime-mesh-upgrade", method, {}], + })) as MeshWideRPCReturnTypes + ).code; }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx index 923008a35..d77767068 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage.tsx @@ -1,104 +1,56 @@ import { Trans } from "@lingui/macro"; -import { useState } from "preact/hooks"; -import { StatusIcon } from "components/icons/status"; -import Loading from "components/loading"; +import { AbortedNotification } from "components/mesh-wide-wizard/StepState"; +import WizardWrapper from "components/mesh-wide-wizard/WizardWrapper"; import Notification from "components/notifications/notification"; -import Tabs from "components/tabs"; import NextStepFooter from "plugins/lime-plugin-mesh-wide-upgrade/src/components/nextStepFooter"; -import { ErrorState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState"; import { MeshWideUpgradeStatus } from "plugins/lime-plugin-mesh-wide-upgrade/src/containers/meshWideUpgradeStatus"; import { NodesList } from "plugins/lime-plugin-mesh-wide-upgrade/src/containers/nodesList"; import { MeshWideUpgradeProvider, useMeshUpgrade, } from "plugins/lime-plugin-mesh-wide-upgrade/src/hooks/meshWideUpgradeProvider"; -import { CenterFlex } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs"; + +const BannerNotification = () => { + const { thisNode } = useMeshUpgrade(); + return ( + <> + + + Upgrade all network nodes at once. This proces will take a + while and will require user interaction. + + + {thisNode.upgrade_state === "ABORTED" && } + + ); +}; const MeshWideUpgrade = () => { const { data: meshWideNodes, - isLoading, + isLoading: meshUpgradeLoading, thisNode, isError, error, } = useMeshUpgrade(); - const [showNodeList, setShowNodeList] = useState(0); - - if (isError) { - return ( - - - Errors found getting mesh info! - {error &&
{error.toString()}
} -
- } - /> - - ); - } - - if (isLoading || meshWideNodes === undefined || thisNode === undefined) { - return ( - - - - ); - } - const tabs = [ - { - key: 0, - repr: ( -
- Show state -
- ), - }, - { - key: 1, - repr: ( -
- Show nodes -
- ), - }, - ]; + const isLoading = + meshUpgradeLoading || + meshWideNodes === undefined || + thisNode === undefined; return ( -
- - - Upgrade all network nodes at once. This proces will take a - while and will require user interaction. - - - {thisNode.upgrade_state === "ABORTED" && ( -
- - This node aborted successfully -
- )} -
- -
- {showNodeList === 0 && } - {showNodeList === 1 && } -
-
- -
+ ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx index 1e991e11e..22aaa6990 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys.tsx @@ -1,26 +1,26 @@ import { QueryKey } from "@tanstack/react-query"; import { sharedStateQueries } from "components/shared-state/SharedStateQueriesKeys"; +import { MeshUpgradeTypes } from "components/shared-state/SharedStateTypes"; -interface MeshUpgradeQueryKeysProps { - [key: string]: QueryKey; -} - -const MeshUpgradeQueryKeys: MeshUpgradeQueryKeysProps = { +const MeshUpgradeQueryKeys: { [key: string]: QueryKey } = { getMeshUpgradeNodeStatus: ["lime-mesh-upgrade", "get_node_status"], remoteScheduleUpgrade: ["lime-mesh-upgrade", "schedule_upgrade"], remoteConfirmUpgrade: ["lime-mesh-upgrade", "confirm_boot_partition"], remoteAbort: ["lime-mesh-upgrade", "abort"], }; +export const meshUpgradeSharedStateKey: keyof MeshUpgradeTypes = + "mesh_wide_upgrade"; + export const meshUpgradeQueryKeys = { getMeshWideUpgradeInfo: (): QueryKey => - sharedStateQueries.getFromSharedState("mesh_wide_upgrade"), + sharedStateQueries.getFromSharedState(meshUpgradeSharedStateKey), getMeshUpgradeNodeStatus: (): QueryKey => MeshUpgradeQueryKeys.getMeshUpgradeNodeStatus, remoteScheduleUpgrade: (): QueryKey => MeshUpgradeQueryKeys.remoteScheduleUpgrade, remoteConfirmUpgrade: (): QueryKey => MeshUpgradeQueryKeys.remoteConfirmUpgrade, - remoteAbort: (): QueryKey => MeshUpgradeQueryKeys.remoteConfirmUpgrade, + remoteAbort: (): QueryKey => MeshUpgradeQueryKeys.remoteAbort, }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts index dfa1fc9ea..a0b90dbde 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/api.ts @@ -1,3 +1,7 @@ +import { + MeshWideConfigState, + NodeMeshConfigInfo, +} from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; import { MeshWideUpgradeInfo, NodeMeshUpgradeInfo, @@ -24,3 +28,22 @@ export const getNodeIpsByCondition = ( ) .map((node) => node.node_ip as string); // 'as string' is safe here due to the filter condition }; + +// todo: merge with the upper and move it to util library +// Use TS to know the type you are going to return on the condition callback using only the nodes type +export const getNodeIpsByConfigCondition = ( + nodes: MeshWideConfigState, + // status: UpgradeStatusType + condition: (node: NodeMeshConfigInfo) => boolean +) => { + if (!nodes) return []; + return Object.values(nodes) + .filter( + (node) => + node.node_ip !== null && + node.node_ip !== undefined && + node.node_ip.trim() !== "" && + condition(node) + ) + .map((node) => node.node_ip as string); // 'as string' is safe here due to the filter condition +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx deleted file mode 100644 index 4b4e94b44..000000000 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/divs.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { VNode } from "preact"; - -export const CenterFlex = ({ children }: { children: VNode }) => { - return ( -
- {children} -
- ); -}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx index 049f96ea9..8ff194a6c 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/utils/upgradeStatusMessages.tsx @@ -1,7 +1,8 @@ import { Trans } from "@lingui/macro"; import { ComponentChildren } from "preact"; -import { INodeInfoBodyItemProps } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/nodeUpgradeInfo"; +import { INodeInfoBodyItemProps } from "components/mesh-wide-wizard/NodeInfoListItem"; + import { MainNodeStatusType, MeshWideNodeUpgradeInfo, diff --git a/plugins/lime-plugin-rx/src/sections/alignment.tsx b/plugins/lime-plugin-rx/src/sections/alignment.tsx index ffaa09fe0..358bee69b 100644 --- a/plugins/lime-plugin-rx/src/sections/alignment.tsx +++ b/plugins/lime-plugin-rx/src/sections/alignment.tsx @@ -1,6 +1,6 @@ import { Trans } from "@lingui/macro"; -import { Button } from "components/elements/button"; +import { Button } from "components/buttons/button"; import { IconsClassName, diff --git a/plugins/lime-plugin-rx/src/sections/internetPath.tsx b/plugins/lime-plugin-rx/src/sections/internetPath.tsx index 559872961..6d51cf256 100644 --- a/plugins/lime-plugin-rx/src/sections/internetPath.tsx +++ b/plugins/lime-plugin-rx/src/sections/internetPath.tsx @@ -1,7 +1,7 @@ import { Trans } from "@lingui/macro"; import { useCallback } from "react"; -import { Button } from "components/elements/button"; +import { Button } from "components/buttons/button"; import { GlobeIcon } from "components/icons/globeIcon"; import Loading from "components/loading"; diff --git a/src/components/Modal/FullScreenModal.tsx b/src/components/Modal/FullScreenModal.tsx index 31a1a4ce5..43fc2e387 100644 --- a/src/components/Modal/FullScreenModal.tsx +++ b/src/components/Modal/FullScreenModal.tsx @@ -1,5 +1,4 @@ import { ComponentChildren } from "preact"; -import { route } from "preact-router"; import Loading from "components/loading"; @@ -20,8 +19,8 @@ export const FullScreenModal = ({ onClose, }: IFullScreenModalProps) => { return ( -
-
+
+
{title}
- {isLoading ? ( -
- -
- ) : ( -
- {children} -
- )} +
+ {isLoading ? : children} +
); }; diff --git a/src/components/buttons/button.tsx b/src/components/buttons/button.tsx index b92e8fdec..2b6598360 100644 --- a/src/components/buttons/button.tsx +++ b/src/components/buttons/button.tsx @@ -1,7 +1,7 @@ import { useState } from "preact/hooks"; import React, { useCallback } from "react"; -export interface ButtonProps { +export type ButtonProps = { onClick?: ((e) => void) | ((e) => Promise); children?: any; // type error with Trans component size?: "sm" | "md" | "lg"; @@ -9,7 +9,7 @@ export interface ButtonProps { href?: string; outline?: boolean; disabled?: boolean; -} +} & Omit, "size">; export const Button = ({ size = "md", @@ -72,10 +72,9 @@ export const Button = ({ const cls = `cursor-pointer font-semibold rounded-xl text-center place-content-center transition-all duration-300 justify-center border-0 ${sizeClasses} ${colorClasses}`; - // useCallback for button click const handleClick = useCallback( async (e) => { - if (innerIsLoading || disabled) return; + if (innerIsLoading || disabled || !onClick) return; setInnerIsLoading(true); try { await onClick(e); @@ -83,10 +82,10 @@ export const Button = ({ setInnerIsLoading(false); } }, - [disabled, innerIsLoading, onClick] + [innerIsLoading, disabled, onClick] ); - const Btn = () => ( + const btn = (
handleClick(e)} @@ -96,11 +95,10 @@ export const Button = ({ {children}
); - return href ? ( - - - - ) : ( - - ); + + if (href) { + return {btn}; + } + + return <>{btn}; }; diff --git a/src/components/elements/button.tsx b/src/components/elements/button.tsx deleted file mode 100644 index 1e1a871b7..000000000 --- a/src/components/elements/button.tsx +++ /dev/null @@ -1,57 +0,0 @@ -interface ButtonProps { - onClick?: () => void; - children?: any; // type error with Trans component - size?: "sm" | "md" | "lg"; - color?: "primary" | "secondary"; - href?: string; -} - -export const Button = ({ - size = "md", - color = "primary", - onClick, - children, - href, - ...props -}: ButtonProps) => { - let sizeClasses = "", - colorClasses = ""; - switch (size) { - case "sm": - sizeClasses = "py-2 px-4 text-sm"; - break; - case "md": - sizeClasses = "py-4 px-6 min-w-[theme('spacing[52]')]"; - break; - case "lg": - sizeClasses = "py-6 px-8"; - break; - } - - switch (color) { - case "primary": - colorClasses = "bg-button-primary"; - break; - case "secondary": - colorClasses = "bg-button-secondary"; - break; - } - - const cls = `cursor-pointer text-white font-semibold rounded-xl text-center place-content-center - justify-center border-0 ${sizeClasses} ${colorClasses}`; - - if (href) { - return ( - -
- {children} -
-
- ); - } - return ( -
- {children} -
- ); -}; diff --git a/src/components/inputs/InputField.tsx b/src/components/inputs/InputField.tsx index 2adc49556..ceb60e6e4 100644 --- a/src/components/inputs/InputField.tsx +++ b/src/components/inputs/InputField.tsx @@ -1,29 +1,32 @@ import { ComponentChild } from "preact"; +import { JSXInternal } from "preact/src/jsx"; import { FieldValues, Path } from "react-hook-form"; -import { UseFormRegister } from "react-hook-form/dist/types/form"; -import { RegisterOptions } from "react-hook-form/dist/types/validator"; const InputField = ({ id, label, - register, - options, + error, + ...inputProps }: { id: Path; - label: string | ComponentChild; - register?: UseFormRegister; - options?: RegisterOptions; -}) => { + label?: string | ComponentChild; + error?: string | ComponentChild; +} & Partial< + Omit, "label"> & { + defaultValue?: string; + } +>) => { return ( -
- +
+ {label && } + {error &&

{error}

}
); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx b/src/components/mesh-wide-wizard/ErrorState.tsx similarity index 67% rename from plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx rename to src/components/mesh-wide-wizard/ErrorState.tsx index bb8391712..16a810240 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/ErrorState.tsx +++ b/src/components/mesh-wide-wizard/ErrorState.tsx @@ -3,16 +3,16 @@ import { VNode } from "preact"; import { MeshUpgradeErrorIcon, - UpgradeState, -} from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; + StepState, +} from "components/mesh-wide-wizard/StepState"; export const ErrorState = ({ msg }: { msg: string | VNode }) => { return ( - Error!} icon={} > {msg} - + ); }; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx b/src/components/mesh-wide-wizard/LoadingPage.tsx similarity index 55% rename from plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx rename to src/components/mesh-wide-wizard/LoadingPage.tsx index c17078fe4..9fc4c636a 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/LoadingPage.tsx +++ b/src/components/mesh-wide-wizard/LoadingPage.tsx @@ -1,8 +1,7 @@ import { VNode } from "preact"; import Loading from "components/loading"; - -import { UpgradeState } from "plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState"; +import { StepState } from "components/mesh-wide-wizard/StepState"; export const LoadingPage = ({ title, @@ -12,8 +11,8 @@ export const LoadingPage = ({ description?: VNode; }) => { return ( - }> + }> {description} - + ); }; diff --git a/src/components/mesh-wide-wizard/NodeInfoListItem.tsx b/src/components/mesh-wide-wizard/NodeInfoListItem.tsx new file mode 100644 index 000000000..9b4d66c87 --- /dev/null +++ b/src/components/mesh-wide-wizard/NodeInfoListItem.tsx @@ -0,0 +1,67 @@ +import { ComponentChildren } from "preact"; + +import { StatusIcon, StatusIcons } from "components/icons/status"; +import { ListItemCollapsible } from "components/list-material"; +import UpdateSharedStateBtn from "components/shared-state/UpdateSharedStateBtn"; +import { ISyncWithNodeProps } from "components/shared-state/useSharedStateSync"; + +export interface INodeInfoBodyItemProps { + title: ComponentChildren; + description: ComponentChildren; +} + +const NodeInfoBodyItem = ({ title, description }: INodeInfoBodyItemProps) => ( +
+
{title}
+
{description}
+
+); + +export interface INodeUpgradeInfoItemProps { + extraInfoItems?: Array; + status?: StatusIcons; + name: string; + descriptionMsg?: ComponentChildren; + ip: string; + sharedStateUpdateTypes: Pick["types"]; +} + +const NodeInfoListItem = ({ + extraInfoItems, + status, + name, + descriptionMsg, + ip, + sharedStateUpdateTypes, +}: INodeUpgradeInfoItemProps) => { + const showUpdateBtn = sharedStateUpdateTypes.length && !!ip; + return ( + } + rightText={ + <> + {showUpdateBtn && ( + + )} + + } + > + {extraInfoItems?.map((item, index) => ( + + ))} + + ); +}; + +export default NodeInfoListItem; diff --git a/src/components/mesh-wide-wizard/NodesListWrapper.tsx b/src/components/mesh-wide-wizard/NodesListWrapper.tsx new file mode 100644 index 000000000..609d93d82 --- /dev/null +++ b/src/components/mesh-wide-wizard/NodesListWrapper.tsx @@ -0,0 +1,47 @@ +import { Trans } from "@lingui/macro"; +import { ComponentType } from "preact"; + +import Loading from "components/loading"; +import { StepState } from "components/mesh-wide-wizard/StepState"; +import { CenterFlex } from "components/mesh-wide-wizard/WizardWrapper"; + +type NodesListProps = { + data: Record | null; + isLoading: boolean; + NodeInfoComponent: ComponentType<{ name: string; info: T }>; +}; + +export const NodesListWrapper = ({ + data, + isLoading, + NodeInfoComponent, +}: NodesListProps) => { + if (isLoading) { + return ; + } + + if (!data || (data && Object.keys(data).length === 0)) { + return ( + + + No nodes present on the
+ mesh wide upgrade state yet! + + } + /> +
+ ); + } + + return ( + <> + {data && + Object.entries(data).map(([key, nodeInfo]) => ( + + ))} + + ); +}; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx b/src/components/mesh-wide-wizard/StepState.tsx similarity index 83% rename from plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx rename to src/components/mesh-wide-wizard/StepState.tsx index 7bbb83284..1bf3d6cc2 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/components/upgradeState/UpgradeState.tsx +++ b/src/components/mesh-wide-wizard/StepState.tsx @@ -2,7 +2,7 @@ import { Trans } from "@lingui/macro"; import { ComponentChildren } from "preact"; import { GlobeIcon } from "components/icons/globeIcon"; -import { Tick, Warning } from "components/icons/status"; +import { StatusIcon, Tick, Warning } from "components/icons/status"; import { RemoteNodeCallError } from "components/shared-state/SharedStateApi"; import { StatusMessage } from "components/status/statusMessage"; @@ -14,7 +14,7 @@ interface UpgradeStateProps { children?: ComponentChildren; } -export const UpgradeState = ({ +export const StepState = ({ icon = , title, children, @@ -58,3 +58,14 @@ export const MeshUpgradeSuccessIcon = () => { export const MeshUpgradeErrorIcon = () => { return ; }; + +export const AbortedNotification = () => ( +
+ + This node aborted successfully +
+); diff --git a/src/components/mesh-wide-wizard/WizardWrapper.tsx b/src/components/mesh-wide-wizard/WizardWrapper.tsx new file mode 100644 index 000000000..6276e89ab --- /dev/null +++ b/src/components/mesh-wide-wizard/WizardWrapper.tsx @@ -0,0 +1,103 @@ +import { Trans } from "@lingui/macro"; +import { ComponentType, VNode } from "preact"; +import { useState } from "preact/hooks"; + +import Loading from "components/loading"; +import { ErrorState } from "components/mesh-wide-wizard/ErrorState"; +import Tabs from "components/tabs"; + +interface WrapperProps { + isError?: boolean; + error?: unknown; + isLoading?: boolean; + banner?: ComponentType; + statusPage: ComponentType; + nodesList: ComponentType; + footer?: ComponentType; +} + +const WizardWrapper = ({ + isError, + error, + isLoading, + banner: Banner, + statusPage: StatusPage, + nodesList: NodesList, + footer: Footer, +}: WrapperProps) => { + const [showNodeList, setShowNodeList] = useState(0); + + if (isError) { + return ( + + + Errors found getting info! + {error &&
{error.toString()}
} +
+ } + /> + + ); + } + + if (isLoading) { + return ( + + + + ); + } + + const tabs = [ + { + key: 0, + repr: ( +
+ Show state +
+ ), + }, + { + key: 1, + repr: ( +
+ Show nodes +
+ ), + }, + ]; + + return ( +
+ {Banner && } +
+ +
+ {showNodeList === 0 && ( + + + + )} + {showNodeList === 1 && } +
+
+ {Footer &&
} +
+ ); +}; + +export const CenterFlex = ({ children }: { children: VNode }) => { + return ( +
+ {children} +
+ ); +}; + +export default WizardWrapper; diff --git a/src/components/shared-state/SharedStateApi.ts b/src/components/shared-state/SharedStateApi.ts index 0b6743a9d..3437d7e86 100644 --- a/src/components/shared-state/SharedStateApi.ts +++ b/src/components/shared-state/SharedStateApi.ts @@ -7,9 +7,8 @@ import { SharedStateReturnType, } from "components/shared-state/SharedStateTypes"; -import { MeshUpgradeApiErrorTypes } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; - import { login } from "utils/queries"; +import { StandarizedApiError } from "utils/standarizedApi"; import { UhttpdService, default as defaultApi } from "utils/uhttpd.service"; async function syncDataType({ @@ -92,7 +91,7 @@ export async function callToRemoteNode({ return await apiCall(customApi); } catch (error) { let additionalInfo = ""; - if (error instanceof MeshUpgradeApiError) { + if (error instanceof StandarizedApiError) { additionalInfo = `: ${error.message}`; } throw new RemoteNodeCallError( @@ -116,15 +115,3 @@ export class RemoteNodeCallError extends Error { Object.setPrototypeOf(this, RemoteNodeCallError.prototype); } } - -export class MeshUpgradeApiError extends Error { - message: string; - code: MeshUpgradeApiErrorTypes; - constructor(message: string, code: MeshUpgradeApiErrorTypes) { - super(message); // Pass the message to the Error constructor - this.name = "MeshUpgradeApiError"; // Set the name of the error - this.message = message; - this.code = code; - Object.setPrototypeOf(this, MeshUpgradeApiError.prototype); - } -} diff --git a/src/components/shared-state/SharedStateQueriesKeys.ts b/src/components/shared-state/SharedStateQueriesKeys.ts index 2c39e82cb..c284379cc 100644 --- a/src/components/shared-state/SharedStateQueriesKeys.ts +++ b/src/components/shared-state/SharedStateQueriesKeys.ts @@ -3,10 +3,24 @@ import { SharedStateDataTypeKeys, } from "components/shared-state/SharedStateTypes"; -const getFromSharedStateKey = ["shared-state-async", "get"]; -const insertIntoSharedStateKey = ["shared-state-async", "insert"]; -export const syncFromSharedStateKey = ["shared-state-async", "sync"]; -const publishAllFromSharedStateKey = ["shared-state-async", "publish_all"]; +import { ApiServiceParamsType } from "utils/standarizedApi"; + +const getFromSharedStateKey: ApiServiceParamsType = [ + "shared-state-async", + "get", +]; +const insertIntoSharedStateKey: ApiServiceParamsType = [ + "shared-state-async", + "insert", +]; +export const syncFromSharedStateKey: ApiServiceParamsType = [ + "shared-state-async", + "sync", +]; +const publishAllFromSharedStateKey: ApiServiceParamsType = [ + "shared-state-async", + "publish_all", +]; /** * Use this constant to get the query keys to be used as api call parameters. diff --git a/src/components/shared-state/SharedStateTypes.ts b/src/components/shared-state/SharedStateTypes.ts index 6f2496666..0395ca798 100644 --- a/src/components/shared-state/SharedStateTypes.ts +++ b/src/components/shared-state/SharedStateTypes.ts @@ -1,3 +1,4 @@ +import { MeshWideConfigState } from "plugins/lime-plugin-mesh-wide-config/src/meshConfigTypes"; import { MeshWideUpgradeInfo } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; import { IBabelLinks, @@ -6,6 +7,10 @@ import { IWifiLinks, } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; +export type MeshConfigTypes = { + mesh_config: MeshWideConfigState; +}; + export type MeshUpgradeTypes = { mesh_wide_upgrade: MeshWideUpgradeInfo; }; @@ -25,7 +30,8 @@ export type MeshWideMapReferenceTypes = AppendRef; export type AllSharedStateTypes = MeshWideMapTypes & MeshUpgradeTypes & - MeshWideMapReferenceTypes; + MeshWideMapReferenceTypes & + MeshConfigTypes; export type SharedStateDataTypeKeys = keyof AllSharedStateTypes; diff --git a/src/components/status/statusAndButton.tsx b/src/components/status/statusAndButton.tsx index 632c3e87e..3967b7264 100644 --- a/src/components/status/statusAndButton.tsx +++ b/src/components/status/statusAndButton.tsx @@ -1,6 +1,6 @@ import { VNode } from "preact"; -import { Button } from "components/buttons/button"; +import { Button, ButtonProps } from "components/buttons/button"; import { IStatusMessage, StatusMessage } from "components/status/statusMessage"; export type IStatusAndButton = { @@ -8,6 +8,7 @@ export type IStatusAndButton = { btnCancel?: VNode | string; onClick?: () => void; onClickCancel?: () => void; + btnProps?: ButtonProps; } & IStatusMessage; export const StatusAndButton = ({ @@ -17,6 +18,7 @@ export const StatusAndButton = ({ btnCancel, onClick, onClickCancel, + btnProps, }: IStatusAndButton) => { const containerClasses = "flex flex-col items-center justify-center text-center bg-white py-5 gap-3"; @@ -26,11 +28,19 @@ export const StatusAndButton = ({ {children}
{btnCancel && ( - )} - {btn && } + {btn && ( + + )}
); diff --git a/src/utils/meshWideSyncCall.ts b/src/utils/meshWideSyncCall.ts index 3b3a84c41..49bcdcc8a 100644 --- a/src/utils/meshWideSyncCall.ts +++ b/src/utils/meshWideSyncCall.ts @@ -7,7 +7,7 @@ import { RemoteNodeCallError } from "components/shared-state/SharedStateApi"; import queryCache from "utils/queryCache"; import { useSharedData } from "utils/useSharedData"; -interface IMutationFnVariables { +export interface IMutationFnVariables { ip: string; variables?: TVariables; } diff --git a/src/utils/standarizedApi.ts b/src/utils/standarizedApi.ts new file mode 100644 index 000000000..7107990b4 --- /dev/null +++ b/src/utils/standarizedApi.ts @@ -0,0 +1,45 @@ +import { MeshUpgradeApiErrorTypes } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeTypes"; + +import api, { UhttpdService } from "utils/uhttpd.service"; + +export type ApiServiceParamsType = [string, string, object?]; + +// This a util function for standarizes API return calls +// During the development some methods are thought to have a specific return type: +// { +// data: T; +// error: number; +// } +// This is a wrapper function to do the calls to the methods that contains this return type +// Pass the array of arguments that api.call method needs. +export const standarizedApiCall = async ({ + apiService = api, + args, +}: { + apiService?: UhttpdService; + args: ApiServiceParamsType; +}) => { + if (args.length === 2) { + args.push({}); + } + const res = await apiService.call(...args); + if (res?.error && res?.error !== "0" && res?.error !== 0) { + throw new StandarizedApiError(res.error, res.code); + } + if (res.data) return res.data as T; + // Fallback to return the response if there is no data + return res as T; +}; + +export class StandarizedApiError extends Error { + message: string; + code: MeshUpgradeApiErrorTypes; + + constructor(message: string, code: MeshUpgradeApiErrorTypes) { + super(message); // Pass the message to the Error constructor + this.name = "MeshUpgradeApiError"; // Set the name of the error + this.message = message; + this.code = code; + Object.setPrototypeOf(this, StandarizedApiError.prototype); + } +} From 8baa7533707bef6d66ab9c8c5d1ce6f43ddf8c04 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 13 Dec 2024 05:48:07 -0500 Subject: [PATCH 21/22] Improve menu groups (#475) * chore(menu): improve menu groups * chore(menu): fix mesh wide upgrade path * chore(menu): delete commented --- .../src/upgradeAvailable.js | 2 +- plugins/lime-plugin-mesh-wide-config/index.ts | 5 +- .../src/meshConfigMenu.tsx | 12 ++++ .../lime-plugin-mesh-wide-upgrade/index.ts | 3 +- .../src/meshUpgradeMenu.tsx | 2 +- plugins/lime-plugin-mesh-wide/index.ts | 1 + src/components/icons/teenny/adjust.jsx | 14 +++++ src/config.ts | 2 +- src/containers/Menu/menu.js | 61 ++++++------------- src/types.d.ts | 9 +-- 10 files changed, 56 insertions(+), 55 deletions(-) create mode 100755 plugins/lime-plugin-mesh-wide-config/src/meshConfigMenu.tsx create mode 100644 src/components/icons/teenny/adjust.jsx diff --git a/plugins/lime-plugin-firmware/src/upgradeAvailable.js b/plugins/lime-plugin-firmware/src/upgradeAvailable.js index bc3cadfb7..82a865ba8 100644 --- a/plugins/lime-plugin-firmware/src/upgradeAvailable.js +++ b/plugins/lime-plugin-firmware/src/upgradeAvailable.js @@ -22,7 +22,7 @@ export const UpgradeAvailableBanner = () => { // @ts-ignore {({ path }) => - !["firmware", "releaseInfo", "meshwideupgrade"].includes( + !["firmware", "releaseInfo", "meshwide/upgrade"].includes( path.replace("/", "") ) && (
( + + + + Mesh Wide Config + + +); diff --git a/plugins/lime-plugin-mesh-wide-upgrade/index.ts b/plugins/lime-plugin-mesh-wide-upgrade/index.ts index 18c78799f..4a3b6e6fb 100644 --- a/plugins/lime-plugin-mesh-wide-upgrade/index.ts +++ b/plugins/lime-plugin-mesh-wide-upgrade/index.ts @@ -2,8 +2,9 @@ import { MeshUpgradeMenu } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshU import MeshUpgradePage from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradePage"; export default { - name: "MeshWideUpgrade", + name: "meshwide/upgrade", page: MeshUpgradePage, menu: MeshUpgradeMenu, isCommunityProtected: true, + menuGroup: "meshwide", } as LimePlugin; diff --git a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx index cb5d73711..3b27bdc67 100755 --- a/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx +++ b/plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeMenu.tsx @@ -5,7 +5,7 @@ import { GlobeAmericasIcon } from "components/icons/teenny/globe"; export const MeshUpgradeMenu = () => ( - + Mesh Wide Upgrade diff --git a/plugins/lime-plugin-mesh-wide/index.ts b/plugins/lime-plugin-mesh-wide/index.ts index 1837c2c72..0fe963120 100644 --- a/plugins/lime-plugin-mesh-wide/index.ts +++ b/plugins/lime-plugin-mesh-wide/index.ts @@ -5,4 +5,5 @@ export default { name: "MeshWide", page: MeshWidePage, menu: MeshWideMenu, + menuGroup: "meshwide", } as LimePlugin; diff --git a/src/components/icons/teenny/adjust.jsx b/src/components/icons/teenny/adjust.jsx new file mode 100644 index 000000000..1584768ed --- /dev/null +++ b/src/components/icons/teenny/adjust.jsx @@ -0,0 +1,14 @@ +export const AdjustVertical = () => ( + + + +); diff --git a/src/config.ts b/src/config.ts index fd1219a79..9e0e6f8b2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -29,6 +29,6 @@ export const plugins: LimePlugin[] = [ ChangeNode, RemoteSupport, Pirania, + MeshConfigPage, Fbw, // does not have menu item - MeshConfigPage, // does not have menu item ]; diff --git a/src/containers/Menu/menu.js b/src/containers/Menu/menu.js index ce6e7a4d1..dc53b9d51 100644 --- a/src/containers/Menu/menu.js +++ b/src/containers/Menu/menu.js @@ -1,18 +1,18 @@ -import { Trans } from "@lingui/macro"; -import { useState } from "preact/hooks"; - import { plugins } from "../../config"; import style from "./style.less"; export const Menu = ({ opened, toggle }) => { - const [currentView, setCurrentView] = useState("node"); - const hasCommunityPlugins = () => - plugins.filter((p) => p.menuView && p.menuView === "community").length > - 0; - function changeCurrentView(e) { - e.preventDefault(); - setCurrentView(currentView === "node" ? "community" : "node"); - } + // Group plugins by menuGroup + const groupedPlugins = plugins + .filter((plugin) => plugin.page && plugin.menu) // Only include plugins with both `page` and `menu` + .reduce((groups, plugin) => { + const group = plugin.menuGroup || "default"; // Use "default" for plugins without a menuGroup + if (!groups[group]) { + groups[group] = []; + } + groups[group].push(plugin.menu); + return groups; + }, {}); return (
{ } d-flex flex-column`} > - {hasCommunityPlugins() && ( - - )}
); }; diff --git a/src/types.d.ts b/src/types.d.ts index 349bdbbf3..71fabd784 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -12,15 +12,8 @@ interface LimePlugin { name: string; page: typeof JSX.Element; menu: typeof JSX.Element; - menuView?: string; isCommunityProtected?: boolean; additionalRoutes?: LimeRoutes[]; additionalProtectedRoutes?: LimeRoutes[]; - store?: { - name: string; - epics?: any; // FIXME - reducer?: any; // FIXME - selector?: any; // FIXME - constants?: any; // FIXME - }; + menuGroup?: string; } From b82876945781891f86d57008cbb8ae93b8f1fccf Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 13 Dec 2024 12:22:03 +0100 Subject: [PATCH 22/22] chore(locate): delete floatting button because is not used anymore --- .../src/meshWidePage.tsx | 3 --- src/components/buttons/floatting-button.tsx | 24 ------------------- 2 files changed, 27 deletions(-) delete mode 100644 src/components/buttons/floatting-button.tsx diff --git a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx index bf2fb0a90..27e368f2b 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWidePage.tsx @@ -1,8 +1,6 @@ import { Trans } from "@lingui/macro"; -import { route } from "preact-router"; import React from "react"; -import FloatingButton from "components/buttons/floatting-button"; import Loading from "components/loading"; import { useLoadLeaflet } from "plugins/lime-plugin-locate/src/locateQueries"; @@ -48,7 +46,6 @@ const MeshWide = () => { - route("/meshwide/config")} /> ); }; diff --git a/src/components/buttons/floatting-button.tsx b/src/components/buttons/floatting-button.tsx deleted file mode 100644 index aac72bae0..000000000 --- a/src/components/buttons/floatting-button.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { ComponentChildren } from "preact"; -import React from "react"; - -import { Button, ButtonProps } from "components/buttons/button"; - -interface FloatingButtonProps { - children?: ComponentChildren | string; -} - -const FloatingButton = ({ - size = "sm", - children = "+", - ...rest -}: FloatingButtonProps & ButtonProps) => { - return ( -
- -
- ); -}; - -export default FloatingButton;