mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-10-28 17:02:21 +00:00
[WIFI-13282] Add support for OLS
Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
340
package-lock.json
generated
340
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "3.0.0(6)",
|
||||
"version": "3.0.1(2)",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ucentral-client",
|
||||
"version": "3.0.0(6)",
|
||||
"version": "3.0.1(2)",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "^2.1.1",
|
||||
@@ -88,6 +88,7 @@
|
||||
"lint-staged": "^13.2.1",
|
||||
"prettier": "^2.8.7",
|
||||
"vite-plugin-pwa": "^0.14.7",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"vite-tsconfig-paths": "^4.2.0"
|
||||
}
|
||||
},
|
||||
@@ -3955,9 +3956,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
|
||||
"integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
|
||||
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
@@ -3968,7 +3969,7 @@
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0"
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
@@ -3997,6 +3998,245 @@
|
||||
"sourcemap-codec": "^1.4.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
|
||||
"integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-remove-jsx-attribute": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz",
|
||||
"integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz",
|
||||
"integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz",
|
||||
"integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-svg-dynamic-title": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz",
|
||||
"integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-svg-em-dimensions": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz",
|
||||
"integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-transform-react-native-svg": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz",
|
||||
"integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-transform-svg-component": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz",
|
||||
"integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-preset": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz",
|
||||
"integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@svgr/babel-plugin-add-jsx-attribute": "8.0.0",
|
||||
"@svgr/babel-plugin-remove-jsx-attribute": "8.0.0",
|
||||
"@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0",
|
||||
"@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0",
|
||||
"@svgr/babel-plugin-svg-dynamic-title": "8.0.0",
|
||||
"@svgr/babel-plugin-svg-em-dimensions": "8.0.0",
|
||||
"@svgr/babel-plugin-transform-react-native-svg": "8.1.0",
|
||||
"@svgr/babel-plugin-transform-svg-component": "8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/core": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@svgr/babel-preset": "8.1.0",
|
||||
"camelcase": "^6.2.0",
|
||||
"cosmiconfig": "^8.1.3",
|
||||
"snake-case": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/core/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/@svgr/hast-util-to-babel-ast": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz",
|
||||
"integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.21.3",
|
||||
"entities": "^4.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/plugin-jsx": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz",
|
||||
"integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@svgr/babel-preset": "8.1.0",
|
||||
"@svgr/hast-util-to-babel-ast": "8.0.0",
|
||||
"svg-parser": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svgr/core": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "4.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.1.tgz",
|
||||
@@ -4969,6 +5209,18 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001480",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz",
|
||||
@@ -5399,6 +5651,16 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
|
||||
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"no-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"license": "MIT"
|
||||
@@ -5431,6 +5693,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@@ -6408,14 +6682,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
@@ -7945,6 +8220,15 @@
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lower-case": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"dev": true,
|
||||
@@ -8084,6 +8368,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/no-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
||||
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lower-case": "^2.0.2",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"license": "MIT",
|
||||
@@ -9368,6 +9662,16 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/snake-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
||||
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dot-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
@@ -9695,6 +9999,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/svg-parser": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
|
||||
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/temp": {
|
||||
"version": "0.9.4",
|
||||
"license": "MIT",
|
||||
@@ -10208,6 +10518,20 @@
|
||||
"workbox-window": "^6.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-svgr": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz",
|
||||
"integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.5",
|
||||
"@svgr/core": "^8.1.0",
|
||||
"@svgr/plugin-jsx": "^8.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^2.6.0 || 3 || 4 || 5"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-tsconfig-paths": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.0.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "3.0.0(6)",
|
||||
"version": "3.0.1(2)",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.tsx",
|
||||
@@ -94,6 +94,7 @@
|
||||
"lint-staged": "^13.2.1",
|
||||
"prettier": "^2.8.7",
|
||||
"vite-plugin-pwa": "^0.14.7",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"vite-tsconfig-paths": "^4.2.0"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
BIN
public/devices/edgecore_ecs4125.png
Normal file
BIN
public/devices/edgecore_ecs4125.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -54,6 +54,7 @@ const DeviceActionDropdown = ({
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const toast = useToast();
|
||||
const deviceType = device?.deviceType ?? 'AP';
|
||||
const connectColor = useColorModeValue('blackAlpha', 'gray');
|
||||
const addEventListeners = useControllerStore((state) => state.addEventListeners);
|
||||
const { refetch: getRtty, isFetching: isRtty } = useGetDeviceRtty({
|
||||
@@ -172,7 +173,7 @@ const DeviceActionDropdown = ({
|
||||
isLoading={isRtty}
|
||||
onClick={handleConnectClick}
|
||||
colorScheme={connectColor}
|
||||
hidden={isCompact}
|
||||
hidden={isCompact || deviceType !== 'AP'}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip label={t('controller.configure.title')}>
|
||||
@@ -205,7 +206,7 @@ const DeviceActionDropdown = ({
|
||||
isDisabled={isDisabled}
|
||||
onClick={handleOpenScan}
|
||||
colorScheme="teal"
|
||||
hidden={isCompact}
|
||||
hidden={isCompact || deviceType !== 'AP'}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Menu>
|
||||
@@ -221,7 +222,7 @@ const DeviceActionDropdown = ({
|
||||
<Portal>
|
||||
<MenuList maxH="315px" overflowY="auto">
|
||||
<MenuItem onClick={handleBlinkClick}>{t('commands.blink')}</MenuItem>
|
||||
<MenuItem onClick={handleOpenConfigure} hidden={!isCompact}>
|
||||
<MenuItem onClick={handleOpenConfigure} hidden={!isCompact || deviceType !== 'AP'}>
|
||||
{t('controller.configure.title')}
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleConnectClick} hidden={!isCompact}>
|
||||
@@ -239,7 +240,7 @@ const DeviceActionDropdown = ({
|
||||
<MenuItem onClick={handleUpdateToLatest} hidden>
|
||||
{t('premium.toolbox.upgrade_to_latest')}
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleOpenScan} hidden={!isCompact}>
|
||||
<MenuItem onClick={handleOpenScan} hidden={!isCompact || deviceType !== 'AP'}>
|
||||
{t('commands.wifiscan')}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
|
||||
@@ -26,7 +26,7 @@ export const ResponsiveTag = React.memo(({ label, icon, tooltip, isCompact, ...p
|
||||
return (
|
||||
<Tooltip label={tooltip ?? label}>
|
||||
<Tag size="lg" colorScheme="blue" {...props}>
|
||||
<TagLeftIcon boxSize="18px" as={icon} />
|
||||
<TagLeftIcon boxSize="18px" as={icon} mt={-0.5} />
|
||||
<TagLabel>{label}</TagLabel>
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
|
||||
1
src/custom.d.ts
vendored
1
src/custom.d.ts
vendored
@@ -8,3 +8,4 @@ declare module '*.png' {
|
||||
const value: string;
|
||||
export = value;
|
||||
}
|
||||
/// <reference types="vite-plugin-svgr/client" />
|
||||
|
||||
@@ -10,14 +10,19 @@ import { DeviceRttyApiResponse, GatewayDevice, WifiScanCommand, WifiScanResult }
|
||||
import { Note } from 'models/Note';
|
||||
import { PageInfo } from 'models/Table';
|
||||
|
||||
const getDeviceCount = () =>
|
||||
axiosGw.get('devices?countOnly=true').then((response) => response.data) as Promise<{ count: number }>;
|
||||
export const DEVICE_PLATFORMS = ['ALL', 'AP', 'SWITCH'] as const;
|
||||
export type DevicePlatform = (typeof DEVICE_PLATFORMS)[number];
|
||||
|
||||
export const useGetDeviceCount = ({ enabled }: { enabled: boolean }) => {
|
||||
const getDeviceCount = (platform: DevicePlatform) =>
|
||||
axiosGw.get(`devices?countOnly=true&platform=${platform}`).then((response) => response.data) as Promise<{
|
||||
count: number;
|
||||
}>;
|
||||
|
||||
export const useGetDeviceCount = ({ enabled, platform = 'ALL' }: { enabled: boolean; platform?: DevicePlatform }) => {
|
||||
const { t } = useTranslation();
|
||||
const toast = useToast();
|
||||
|
||||
return useQuery(['devices', 'count'], getDeviceCount, {
|
||||
return useQuery(['devices', 'count', { platform }], () => getDeviceCount(platform), {
|
||||
enabled,
|
||||
onError: (e: AxiosError) => {
|
||||
if (!toast.isActive('inventory-fetching-error'))
|
||||
@@ -96,25 +101,27 @@ export const getSingleDeviceWithStatus = (serialNumber: string) =>
|
||||
})
|
||||
.catch(() => undefined);
|
||||
|
||||
const getDevices = (limit: number, offset: number) =>
|
||||
const getDevices = (limit: number, offset: number, platform: DevicePlatform) =>
|
||||
axiosGw
|
||||
.get(`devices?deviceWithStatus=true&limit=${limit}&offset=${offset}`)
|
||||
.get(`devices?deviceWithStatus=true&limit=${limit}&offset=${offset}&platform=${platform}`)
|
||||
.then((response) => response.data) as Promise<{ devicesWithStatus: DeviceWithStatus[] }>;
|
||||
|
||||
export const useGetDevices = ({
|
||||
pageInfo,
|
||||
enabled,
|
||||
onError,
|
||||
platform = 'ALL',
|
||||
}: {
|
||||
pageInfo?: PageInfo;
|
||||
enabled: boolean;
|
||||
onError?: (e: AxiosError) => void;
|
||||
platform?: DevicePlatform;
|
||||
}) => {
|
||||
const offset = pageInfo?.limit !== undefined ? pageInfo.limit * pageInfo.index : 0;
|
||||
|
||||
return useQuery(
|
||||
['devices', 'all', { limit: pageInfo?.limit, offset }],
|
||||
() => getDevices(pageInfo?.limit || 0, offset),
|
||||
['devices', 'all', { limit: pageInfo?.limit, offset, platform }],
|
||||
() => getDevices(pageInfo?.limit || 0, offset, platform),
|
||||
{
|
||||
keepPreviousData: true,
|
||||
enabled: enabled && pageInfo !== undefined,
|
||||
@@ -124,22 +131,28 @@ export const useGetDevices = ({
|
||||
);
|
||||
};
|
||||
|
||||
const getAllDevices = async () => {
|
||||
const getAllDevices = async (platform: DevicePlatform) => {
|
||||
let offset = 0;
|
||||
let devices: DeviceWithStatus[] = [];
|
||||
let devicesResponse: { devicesWithStatus: DeviceWithStatus[] };
|
||||
do {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
devicesResponse = await getDevices(500, offset);
|
||||
devicesResponse = await getDevices(500, offset, platform);
|
||||
devices = devices.concat(devicesResponse.devicesWithStatus);
|
||||
offset += 500;
|
||||
} while (devicesResponse.devicesWithStatus.length === 500);
|
||||
return devices;
|
||||
};
|
||||
|
||||
export const useGetAllDevicesWithStatus = ({ onError }: { onError?: (e: AxiosError) => void }) => {
|
||||
export const useGetAllDevicesWithStatus = ({
|
||||
onError,
|
||||
platform = 'ALL',
|
||||
}: {
|
||||
onError?: (e: AxiosError) => void;
|
||||
platform?: DevicePlatform;
|
||||
}) => {
|
||||
const { isReady } = useEndpointStatus('owgw');
|
||||
return useQuery(['devices', 'all', 'full'], getAllDevices, {
|
||||
return useQuery(['devices', 'all', 'full', { platform }], () => getAllDevices(platform), {
|
||||
enabled: isReady && false,
|
||||
onError,
|
||||
});
|
||||
@@ -432,3 +445,19 @@ export const useUpdateDevice = ({ serialNumber }: { serialNumber: string }) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const deleteDeviceBatch = async (pattern: string) => {
|
||||
if (pattern.length < 6) throw new Error('Pattern must be at least 6 characters long');
|
||||
|
||||
axiosGw.delete(`devices?macPattern=${pattern}`);
|
||||
};
|
||||
|
||||
export const useDeleteDeviceBatch = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation(deleteDeviceBatch, {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(['devices']);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,7 +2,24 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { axiosGw } from 'constants/axiosInstances';
|
||||
import { AxiosError } from 'models/Axios';
|
||||
|
||||
type DeviceInterfaceStatistics = {
|
||||
export type DeviceLinkState = {
|
||||
carrier?: number;
|
||||
counters?: {
|
||||
collisions: number;
|
||||
multicast: number;
|
||||
rx_bytes: number;
|
||||
rx_dropped: number;
|
||||
rx_errors: number;
|
||||
rx_packets: number;
|
||||
tx_bytes: number;
|
||||
tx_dropped: number;
|
||||
tx_errors: number;
|
||||
tx_packets: number;
|
||||
};
|
||||
duplex?: string;
|
||||
speed?: number;
|
||||
};
|
||||
export type DeviceInterfaceStatistics = {
|
||||
clients: {
|
||||
ipv4_addresses?: string[];
|
||||
ipv6_addresses?: string[];
|
||||
@@ -138,18 +155,10 @@ export type DeviceStatistics = {
|
||||
};
|
||||
'link-state'?: {
|
||||
downstream: {
|
||||
eth1?: {
|
||||
carrier?: number;
|
||||
duplex?: string;
|
||||
speed?: number;
|
||||
};
|
||||
[key: string]: DeviceLinkState;
|
||||
};
|
||||
upstream: {
|
||||
eth0?: {
|
||||
carrier?: number;
|
||||
duplex?: string;
|
||||
speed?: number;
|
||||
};
|
||||
[key: string]: DeviceLinkState;
|
||||
};
|
||||
};
|
||||
'lldp-peers'?: {
|
||||
@@ -190,6 +199,7 @@ export const useGetDeviceLastStats = ({
|
||||
useQuery(['device', serialNumber, 'last-statistics'], () => getLastStats(serialNumber), {
|
||||
enabled: serialNumber !== undefined && serialNumber !== '',
|
||||
staleTime: 1000 * 60,
|
||||
refetchInterval: 1000 * 60,
|
||||
onError,
|
||||
});
|
||||
|
||||
|
||||
182
src/pages/Device/SwitchPortExamination/LinkStateTable.tsx
Normal file
182
src/pages/Device/SwitchPortExamination/LinkStateTable.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
import * as React from 'react';
|
||||
import { Alert, AlertDescription, AlertIcon, Center } from '@chakra-ui/react';
|
||||
import { DeviceLinkState } from 'hooks/Network/Statistics';
|
||||
import DataCell from 'components/TableCells/DataCell';
|
||||
import { DataGridColumn, useDataGrid } from 'components/DataTables/DataGrid/useDataGrid';
|
||||
import { DataGrid } from 'components/DataTables/DataGrid';
|
||||
import { uppercaseFirstLetter } from 'helpers/stringHelper';
|
||||
|
||||
type Row = DeviceLinkState & { name: string };
|
||||
const dataCell = (v: number) => <DataCell bytes={v} />;
|
||||
|
||||
type Props = {
|
||||
statistics?: Row[];
|
||||
refetch: () => void;
|
||||
isFetching: boolean;
|
||||
type: 'upstream' | 'downstream';
|
||||
};
|
||||
|
||||
const LinkStateTable = ({ statistics, refetch, isFetching, type }: Props) => {
|
||||
const tableController = useDataGrid({
|
||||
tableSettingsId: 'switch.link-state.table',
|
||||
defaultOrder: [
|
||||
'carrier',
|
||||
'name',
|
||||
'duplex',
|
||||
'speed',
|
||||
'rx_bytes',
|
||||
'rx_dropped',
|
||||
'rx_error',
|
||||
'rx_packets',
|
||||
'tx_bytes',
|
||||
'tx_dropped',
|
||||
'tx_error',
|
||||
],
|
||||
defaultSortBy: [{ id: 'name', desc: false }],
|
||||
});
|
||||
|
||||
const columns: DataGridColumn<Row>[] = React.useMemo(
|
||||
(): DataGridColumn<Row>[] => [
|
||||
{
|
||||
id: 'carrier',
|
||||
header: '',
|
||||
accessorKey: '',
|
||||
cell: ({ cell }) => (cell.row.original.carrier ? '🟢' : '🔴'),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'name',
|
||||
header: 'Name',
|
||||
accessorKey: 'name',
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'duplex',
|
||||
header: 'Duplex',
|
||||
accessorKey: 'duplex',
|
||||
cell: ({ cell }) => (cell.row.original.duplex ? uppercaseFirstLetter(cell.row.original.duplex) : '-'),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'speed',
|
||||
header: 'Speed',
|
||||
accessorKey: 'speed',
|
||||
cell: ({ cell }) => `${(cell.row.original.speed ?? 0) / 1000} Gbps`,
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_bytes',
|
||||
header: 'Rx',
|
||||
accessorKey: 'rx_bytes',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.rx_bytes ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_dropped',
|
||||
header: 'Rx Dropped',
|
||||
accessorKey: 'rx_dropped',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.rx_dropped ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_error',
|
||||
header: 'Rx Errors',
|
||||
accessorKey: 'rx_error',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.rx_errors ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_packets',
|
||||
header: 'Rx Packets',
|
||||
accessorKey: 'counters.rx_packets',
|
||||
cell: ({ cell }) => (cell.row.original.counters?.rx_packets ?? 0).toLocaleString(),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_bytes',
|
||||
header: 'Tx',
|
||||
accessorKey: 'tx_bytes',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.tx_bytes ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_dropped',
|
||||
header: 'Tx Dropped',
|
||||
accessorKey: 'tx_dropped',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.tx_dropped ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_error',
|
||||
header: 'Tx Errors',
|
||||
accessorKey: 'tx_error',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.tx_errors ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_packets',
|
||||
header: 'Tx Packets',
|
||||
accessorKey: 'counters.tx_packets',
|
||||
cell: ({ cell }) => (cell.row.original.counters?.tx_packets ?? 0).toLocaleString(),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
if (!statistics || statistics?.length === 0) {
|
||||
return (
|
||||
<Center>
|
||||
<Alert status="info">
|
||||
<AlertIcon />
|
||||
<AlertDescription>
|
||||
There are currently no {type} link-states provided in this devices statistics
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DataGrid<Row>
|
||||
controller={tableController}
|
||||
header={{
|
||||
title: '',
|
||||
objectListed: 'Statistics',
|
||||
}}
|
||||
columns={columns}
|
||||
isLoading={isFetching}
|
||||
data={statistics ?? []}
|
||||
options={{
|
||||
refetch,
|
||||
isHidingControls: true,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default LinkStateTable;
|
||||
170
src/pages/Device/SwitchPortExamination/SwitchInterfaceTable.tsx
Normal file
170
src/pages/Device/SwitchPortExamination/SwitchInterfaceTable.tsx
Normal file
@@ -0,0 +1,170 @@
|
||||
import * as React from 'react';
|
||||
import { Alert, AlertDescription, AlertIcon, Center } from '@chakra-ui/react';
|
||||
import { DeviceInterfaceStatistics, DeviceStatistics } from 'hooks/Network/Statistics';
|
||||
import DataCell from 'components/TableCells/DataCell';
|
||||
import { DataGridColumn, useDataGrid } from 'components/DataTables/DataGrid/useDataGrid';
|
||||
import DurationCell from 'components/TableCells/DurationCell';
|
||||
import { DataGrid } from 'components/DataTables/DataGrid';
|
||||
|
||||
const dataCell = (v: number) => <DataCell bytes={v} />;
|
||||
|
||||
type Props = {
|
||||
statistics: DeviceStatistics;
|
||||
refetch: () => void;
|
||||
isFetching: boolean;
|
||||
};
|
||||
|
||||
const SwitchInterfaceTable = ({ statistics, refetch, isFetching }: Props) => {
|
||||
const tableController = useDataGrid({
|
||||
tableSettingsId: 'switch.interfaces.table',
|
||||
defaultOrder: [
|
||||
'name',
|
||||
'uptime',
|
||||
'clients',
|
||||
'rx_bytes',
|
||||
'rx_dropped',
|
||||
'rx_error',
|
||||
'rx_packets',
|
||||
'tx_bytes',
|
||||
'tx_dropped',
|
||||
'tx_error',
|
||||
],
|
||||
defaultSortBy: [{ id: 'name', desc: false }],
|
||||
});
|
||||
|
||||
const columns: DataGridColumn<DeviceInterfaceStatistics>[] = React.useMemo(
|
||||
(): DataGridColumn<DeviceInterfaceStatistics>[] => [
|
||||
{
|
||||
id: 'name',
|
||||
header: 'Name',
|
||||
accessorKey: 'name',
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'uptime',
|
||||
header: 'Uptime',
|
||||
|
||||
accessorKey: 'uptime',
|
||||
cell: ({ cell }) => <DurationCell seconds={cell.row.original.uptime} />,
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'clients',
|
||||
header: 'Clients',
|
||||
|
||||
accessorKey: 'clients',
|
||||
cell: ({ cell }) => cell.row.original.clients?.length ?? 0,
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_bytes',
|
||||
header: 'Rx',
|
||||
accessorKey: 'rx_bytes',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.rx_bytes ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_dropped',
|
||||
header: 'Rx Dropped',
|
||||
accessorKey: 'rx_dropped',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.rx_dropped ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_error',
|
||||
header: 'Rx Errors',
|
||||
accessorKey: 'rx_error',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.rx_errors ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rx_packets',
|
||||
header: 'Rx Packets',
|
||||
accessorKey: 'counters.rx_packets',
|
||||
cell: ({ cell }) => (cell.row.original.counters?.rx_packets ?? 0).toLocaleString(),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_bytes',
|
||||
header: 'Tx',
|
||||
accessorKey: 'tx_bytes',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.tx_bytes ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_dropped',
|
||||
header: 'Tx Dropped',
|
||||
accessorKey: 'tx_dropped',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.tx_dropped ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_error',
|
||||
header: 'Tx Errors',
|
||||
accessorKey: 'tx_error',
|
||||
cell: ({ cell }) => dataCell(cell.row.original.counters?.tx_errors ?? 0),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tx_packets',
|
||||
header: 'Tx Packets',
|
||||
accessorKey: 'counters.tx_packets',
|
||||
cell: ({ cell }) => (cell.row.original.counters?.tx_packets ?? 0).toLocaleString(),
|
||||
meta: {
|
||||
customWidth: '35px',
|
||||
},
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
if (!statistics.interfaces) {
|
||||
return (
|
||||
<Center>
|
||||
<Alert status="info">
|
||||
<AlertIcon />
|
||||
<AlertDescription>There are currently no interfaces provided in this devices statistics</AlertDescription>
|
||||
</Alert>
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DataGrid<DeviceInterfaceStatistics>
|
||||
controller={tableController}
|
||||
header={{
|
||||
title: '',
|
||||
objectListed: 'Statistics',
|
||||
}}
|
||||
columns={columns}
|
||||
isLoading={isFetching}
|
||||
data={statistics.interfaces ?? []}
|
||||
options={{
|
||||
refetch,
|
||||
isHidingControls: true,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SwitchInterfaceTable;
|
||||
96
src/pages/Device/SwitchPortExamination/index.tsx
Normal file
96
src/pages/Device/SwitchPortExamination/index.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import * as React from 'react';
|
||||
import { Spinner, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react';
|
||||
import LinkStateTable from './LinkStateTable';
|
||||
import SwitchInterfaceTable from './SwitchInterfaceTable';
|
||||
import { DeviceLinkState, useGetDeviceLastStats } from 'hooks/Network/Statistics';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { CardBody } from 'components/Containers/Card/CardBody';
|
||||
|
||||
type Props = {
|
||||
serialNumber: string;
|
||||
};
|
||||
|
||||
const SwitchPortExamination = ({ serialNumber }: Props) => {
|
||||
const [tabIndex, setTabIndex] = React.useState(0);
|
||||
|
||||
const handleTabsChange = React.useCallback((index: number) => {
|
||||
setTabIndex(index);
|
||||
}, []);
|
||||
const getStats = useGetDeviceLastStats({ serialNumber });
|
||||
|
||||
const upLinkStates: (DeviceLinkState & { name: string })[] = React.useMemo(() => {
|
||||
if (!getStats.data || !getStats.data['link-state']?.upstream) return [];
|
||||
|
||||
return Object.entries(getStats.data['link-state']?.upstream).map(([name, value]) => ({
|
||||
...value,
|
||||
name,
|
||||
}));
|
||||
}, [getStats.data]);
|
||||
const downLinkStates: (DeviceLinkState & { name: string })[] = React.useMemo(() => {
|
||||
if (!getStats.data || !getStats.data['link-state']?.downstream) return [];
|
||||
|
||||
return Object.entries(getStats.data['link-state']?.downstream).map(([name, value]) => ({
|
||||
...value,
|
||||
name,
|
||||
}));
|
||||
}, [getStats.data]);
|
||||
|
||||
return (
|
||||
<Card p={0} mb={4}>
|
||||
<CardBody p={0} display="block">
|
||||
<Tabs index={tabIndex} onChange={handleTabsChange} variant="enclosed" w="100%">
|
||||
<TabList>
|
||||
<Tab fontSize="lg" fontWeight="bold">
|
||||
Interfaces
|
||||
</Tab>
|
||||
<Tab fontSize="lg" fontWeight="bold">
|
||||
Link-State (Up)
|
||||
</Tab>
|
||||
<Tab fontSize="lg" fontWeight="bold">
|
||||
Link-State (Down)
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
<TabPanel>
|
||||
{getStats.data ? (
|
||||
<SwitchInterfaceTable
|
||||
statistics={getStats.data}
|
||||
refetch={getStats.refetch}
|
||||
isFetching={getStats.isFetching}
|
||||
/>
|
||||
) : (
|
||||
<Spinner size="xl" />
|
||||
)}
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
{getStats.data ? (
|
||||
<LinkStateTable
|
||||
statistics={upLinkStates}
|
||||
refetch={getStats.refetch}
|
||||
isFetching={getStats.isFetching}
|
||||
type="upstream"
|
||||
/>
|
||||
) : (
|
||||
<Spinner size="xl" />
|
||||
)}
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
{getStats.data ? (
|
||||
<LinkStateTable
|
||||
statistics={downLinkStates}
|
||||
refetch={getStats.refetch}
|
||||
isFetching={getStats.isFetching}
|
||||
type="downstream"
|
||||
/>
|
||||
) : (
|
||||
<Spinner size="xl" />
|
||||
)}
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default SwitchPortExamination;
|
||||
@@ -42,10 +42,13 @@ import FactoryResetModal from 'components/Modals/FactoryResetModal';
|
||||
import { FirmwareUpgradeModal } from 'components/Modals/FirmwareUpgradeModal';
|
||||
import { RebootModal } from 'components/Modals/RebootModal';
|
||||
import { useScriptModal } from 'components/Modals/ScriptModal/useScriptModal';
|
||||
import ethernetConnected from './ethernetIconConnected.svg?react';
|
||||
import ethernetDisconnected from './ethernetIconDisconnected.svg?react';
|
||||
import { TelemetryModal } from 'components/Modals/TelemetryModal';
|
||||
import { TraceModal } from 'components/Modals/TraceModal';
|
||||
import { WifiScanModal } from 'components/Modals/WifiScanModal';
|
||||
import { useDeleteDevice, useGetDevice, useGetDeviceHealthChecks, useGetDeviceStatus } from 'hooks/Network/Devices';
|
||||
import SwitchPortExamination from './SwitchPortExamination';
|
||||
|
||||
type Props = {
|
||||
serialNumber: string;
|
||||
@@ -119,11 +122,15 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
|
||||
);
|
||||
}
|
||||
|
||||
let icon = getStatus.data.connected ? WifiHigh : WifiSlash;
|
||||
if (getDevice.data?.deviceType === 'SWITCH')
|
||||
icon = getStatus.data.connected ? ethernetConnected : ethernetDisconnected;
|
||||
|
||||
return (
|
||||
<ResponsiveTag
|
||||
label={getStatus?.data?.connected ? t('common.connected') : t('common.disconnected')}
|
||||
colorScheme={getStatus?.data?.connected ? 'green' : 'red'}
|
||||
icon={getStatus.data.connected ? WifiHigh : WifiSlash}
|
||||
icon={icon}
|
||||
/>
|
||||
);
|
||||
}, [getStatus.data, getDevice.data]);
|
||||
@@ -318,7 +325,11 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
|
||||
<DeviceSummary serialNumber={serialNumber} />
|
||||
<DeviceDetails serialNumber={serialNumber} />
|
||||
<DeviceStatisticsCard serialNumber={serialNumber} />
|
||||
<WifiAnalysisCard serialNumber={serialNumber} />
|
||||
{getDevice.data?.deviceType === 'AP' ? (
|
||||
<WifiAnalysisCard serialNumber={serialNumber} />
|
||||
) : (
|
||||
<SwitchPortExamination serialNumber={serialNumber} />
|
||||
)}
|
||||
<DeviceLogsCard serialNumber={serialNumber} />
|
||||
{getDevice.data && getDevice.data?.hasRADIUSSessions > 0 ? (
|
||||
<RadiusClientsCard serialNumber={serialNumber} />
|
||||
|
||||
2
src/pages/Device/ethernetIconConnected.svg
Normal file
2
src/pages/Device/ethernetIconConnected.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 24 24" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;stroke:#48BB78;stroke-miterlimit:10;stroke-width:1.91px;}</style></defs><rect class="cls-1" x="1.5" y="1.5" width="21" height="21" rx="1.91"/><polygon class="cls-1" points="5.32 6.27 5.32 13.91 7.23 13.91 7.23 15.82 10.09 15.82 10.09 17.73 13.91 17.73 13.91 15.82 16.77 15.82 16.77 13.91 18.68 13.91 18.68 6.27 5.32 6.27"/><line class="cls-1" x1="8.18" y1="9.14" x2="8.18" y2="6.27"/><line class="cls-1" x1="12" y1="9.14" x2="12" y2="6.27"/><line class="cls-1" x1="15.82" y1="9.14" x2="15.82" y2="6.27"/></svg>
|
||||
|
After Width: | Height: | Size: 673 B |
2
src/pages/Device/ethernetIconDisconnected.svg
Normal file
2
src/pages/Device/ethernetIconDisconnected.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 24 24" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;stroke:#FC8181;stroke-miterlimit:10;stroke-width:1.91px;}</style></defs><rect class="cls-1" x="1.5" y="1.5" width="21" height="21" rx="1.91"/><polygon class="cls-1" points="5.32 6.27 5.32 13.91 7.23 13.91 7.23 15.82 10.09 15.82 10.09 17.73 13.91 17.73 13.91 15.82 16.77 15.82 16.77 13.91 18.68 13.91 18.68 6.27 5.32 6.27"/><line class="cls-1" x1="8.18" y1="9.14" x2="8.18" y2="6.27"/><line class="cls-1" x1="12" y1="9.14" x2="12" y2="6.27"/><line class="cls-1" x1="15.82" y1="9.14" x2="15.82" y2="6.27"/></svg>
|
||||
|
After Width: | Height: | Size: 673 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -1,5 +1,16 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Center, Image, Link, Tag, TagLabel, TagRightIcon, Tooltip, useDisclosure } from '@chakra-ui/react';
|
||||
import {
|
||||
Box,
|
||||
Center,
|
||||
Image,
|
||||
Link,
|
||||
Select,
|
||||
Tag,
|
||||
TagLabel,
|
||||
TagRightIcon,
|
||||
Tooltip,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
CheckCircle,
|
||||
Heart,
|
||||
@@ -38,7 +49,7 @@ import { TraceModal } from 'components/Modals/TraceModal';
|
||||
import { WifiScanModal } from 'components/Modals/WifiScanModal';
|
||||
import DataCell from 'components/TableCells/DataCell';
|
||||
import NumberCell from 'components/TableCells/NumberCell';
|
||||
import { DeviceWithStatus, useGetDeviceCount, useGetDevices } from 'hooks/Network/Devices';
|
||||
import { DevicePlatform, DeviceWithStatus, useGetDeviceCount, useGetDevices } from 'hooks/Network/Devices';
|
||||
import { FirmwareAgeResponse, useGetFirmwareAges } from 'hooks/Network/Firmware';
|
||||
|
||||
const fourDigitNumber = (v?: number) => {
|
||||
@@ -72,6 +83,7 @@ const DeviceListCard = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [serialNumber, setSerialNumber] = React.useState<string>('');
|
||||
const [platform, setPlatform] = React.useState<DevicePlatform>('ALL');
|
||||
const scanModalProps = useDisclosure();
|
||||
const resetModalProps = useDisclosure();
|
||||
const upgradeModalProps = useDisclosure();
|
||||
@@ -110,13 +122,14 @@ const DeviceListCard = () => {
|
||||
'actions',
|
||||
],
|
||||
});
|
||||
const getCount = useGetDeviceCount({ enabled: true });
|
||||
const getCount = useGetDeviceCount({ enabled: true, platform });
|
||||
const getDevices = useGetDevices({
|
||||
pageInfo: {
|
||||
limit: tableController.pageInfo.pageSize,
|
||||
index: tableController.pageInfo.pageIndex,
|
||||
},
|
||||
enabled: true,
|
||||
platform,
|
||||
});
|
||||
const getAges = useGetFirmwareAges({
|
||||
serialNumbers: getDevices.data?.devicesWithStatus.map((device) => device.serialNumber),
|
||||
@@ -556,12 +569,7 @@ const DeviceListCard = () => {
|
||||
header: t('analytics.last_connected'),
|
||||
footer: '',
|
||||
accessorKey: 'lastRecordedContact',
|
||||
cell: (v) =>
|
||||
dateCell(
|
||||
v.cell.row.original.lastContact !== 0
|
||||
? v.cell.row.original.lastContact
|
||||
: v.cell.row.original.lastRecordedContact,
|
||||
),
|
||||
cell: (v) => dateCell(v.cell.row.original.lastRecordedContact),
|
||||
enableSorting: false,
|
||||
meta: {
|
||||
headerOptions: {
|
||||
@@ -719,7 +727,21 @@ const DeviceListCard = () => {
|
||||
header={{
|
||||
title: `${getCount.data?.count ?? 0} ${t('devices.title')}`,
|
||||
objectListed: t('devices.title'),
|
||||
leftContent: <GlobalSearchBar />,
|
||||
leftContent: (
|
||||
<>
|
||||
<GlobalSearchBar />
|
||||
<Select
|
||||
value={platform}
|
||||
onChange={(e) => setPlatform(e.target.value as DevicePlatform)}
|
||||
w="max-content"
|
||||
ml={2}
|
||||
>
|
||||
<option value="ALL">All</option>
|
||||
<option value="AP">APs</option>
|
||||
<option value="SWITCH">Switches</option>
|
||||
</Select>
|
||||
</>
|
||||
),
|
||||
otherButtons: (
|
||||
<ExportDevicesTableButton currentPageSerialNumbers={data.map((device) => device.serialNumber)} />
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineConfig } from 'vite';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
@@ -15,10 +16,11 @@ export default defineConfig({
|
||||
/* other options */
|
||||
},
|
||||
manifest: {
|
||||
name: 'OpenWiFi Controller App',
|
||||
short_name: 'OpenWiFiController',
|
||||
description: 'OpenWiFi Controller App',
|
||||
name: 'Arilia Controller App',
|
||||
short_name: 'AriController',
|
||||
description: 'Arilia Controller Work App',
|
||||
theme_color: '#000000',
|
||||
|
||||
icons: [
|
||||
{
|
||||
src: 'android-chrome-192x192.png',
|
||||
@@ -44,13 +46,14 @@ export default defineConfig({
|
||||
],
|
||||
},
|
||||
}),
|
||||
svgr(),
|
||||
],
|
||||
build: {
|
||||
outDir: './build',
|
||||
chunkSizeWarningLimit: 1000,
|
||||
},
|
||||
server: {
|
||||
port: 3000,
|
||||
port: 3001,
|
||||
open: true,
|
||||
},
|
||||
esbuild: {
|
||||
|
||||
Reference in New Issue
Block a user