mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-11-03 11:47:47 +00:00
Doing less requests for the device list
This commit is contained in:
179
package-lock.json
generated
179
package-lock.json
generated
@@ -1232,6 +1232,74 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz",
|
||||||
"integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg=="
|
"integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg=="
|
||||||
},
|
},
|
||||||
|
"@emotion/cache": {
|
||||||
|
"version": "11.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.1.3.tgz",
|
||||||
|
"integrity": "sha512-n4OWinUPJVaP6fXxWZD9OUeQ0lY7DvtmtSuqtRWT0Ofo/sBLCVSgb4/Oa0Q5eFxcwablRKjUXqXtNZVyEwCAuA==",
|
||||||
|
"requires": {
|
||||||
|
"@emotion/memoize": "^0.7.4",
|
||||||
|
"@emotion/sheet": "^1.0.0",
|
||||||
|
"@emotion/utils": "^1.0.0",
|
||||||
|
"@emotion/weak-memoize": "^0.2.5",
|
||||||
|
"stylis": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@emotion/hash": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
||||||
|
},
|
||||||
|
"@emotion/memoize": {
|
||||||
|
"version": "0.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
|
||||||
|
"integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
|
||||||
|
},
|
||||||
|
"@emotion/react": {
|
||||||
|
"version": "11.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.1.5.tgz",
|
||||||
|
"integrity": "sha512-xfnZ9NJEv9SU9K2sxXM06lzjK245xSeHRpUh67eARBm3PBHjjKIZlfWZ7UQvD0Obvw6ZKjlC79uHrlzFYpOB/Q==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.7.2",
|
||||||
|
"@emotion/cache": "^11.1.3",
|
||||||
|
"@emotion/serialize": "^1.0.0",
|
||||||
|
"@emotion/sheet": "^1.0.1",
|
||||||
|
"@emotion/utils": "^1.0.0",
|
||||||
|
"@emotion/weak-memoize": "^0.2.5",
|
||||||
|
"hoist-non-react-statics": "^3.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@emotion/serialize": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==",
|
||||||
|
"requires": {
|
||||||
|
"@emotion/hash": "^0.8.0",
|
||||||
|
"@emotion/memoize": "^0.7.4",
|
||||||
|
"@emotion/unitless": "^0.7.5",
|
||||||
|
"@emotion/utils": "^1.0.0",
|
||||||
|
"csstype": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@emotion/sheet": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-GbIvVMe4U+Zc+929N1V7nW6YYJtidj31lidSmdYcWozwoBIObXBnaJkKNDjZrLm9Nc0BR+ZyHNaRZxqNZbof5g=="
|
||||||
|
},
|
||||||
|
"@emotion/unitless": {
|
||||||
|
"version": "0.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||||
|
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||||
|
},
|
||||||
|
"@emotion/utils": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA=="
|
||||||
|
},
|
||||||
|
"@emotion/weak-memoize": {
|
||||||
|
"version": "0.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
|
||||||
|
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
||||||
|
},
|
||||||
"@eslint/eslintrc": {
|
"@eslint/eslintrc": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
|
||||||
@@ -1326,6 +1394,15 @@
|
|||||||
"@hapi/hoek": "^8.3.0"
|
"@hapi/hoek": "^8.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@hypnosphi/create-react-context": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==",
|
||||||
|
"requires": {
|
||||||
|
"gud": "^1.0.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@istanbuljs/load-nyc-config": {
|
"@istanbuljs/load-nyc-config": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||||
@@ -7386,6 +7463,11 @@
|
|||||||
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"gud": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
|
||||||
|
},
|
||||||
"gzip-size": {
|
"gzip-size": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
|
||||||
@@ -10324,6 +10406,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||||
},
|
},
|
||||||
|
"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=="
|
||||||
|
},
|
||||||
"memory-fs": {
|
"memory-fs": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||||
@@ -11459,6 +11546,11 @@
|
|||||||
"ts-pnp": "^1.1.6"
|
"ts-pnp": "^1.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"popper.js": {
|
||||||
|
"version": "1.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||||
|
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
|
||||||
|
},
|
||||||
"portfinder": {
|
"portfinder": {
|
||||||
"version": "1.0.28",
|
"version": "1.0.28",
|
||||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
|
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
|
||||||
@@ -12928,6 +13020,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
||||||
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
||||||
},
|
},
|
||||||
|
"react-input-autosize": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.5.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
@@ -12953,6 +13053,28 @@
|
|||||||
"warning": "^4.0.3"
|
"warning": "^4.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-paginate": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-paginate/-/react-paginate-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-yAl7taPNIUegS5b6kdNvEMh7iu9T3spuzOCUw+BB0ScTLaC4dfSl686Kl+rVCvkOr67qcbi6T8+tpo4hEVCC1Q==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-popper": {
|
||||||
|
"version": "1.3.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz",
|
||||||
|
"integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2",
|
||||||
|
"@hypnosphi/create-react-context": "^0.3.1",
|
||||||
|
"deep-equal": "^1.1.1",
|
||||||
|
"popper.js": "^1.14.4",
|
||||||
|
"prop-types": "^15.6.1",
|
||||||
|
"typed-styles": "^0.0.7",
|
||||||
|
"warning": "^4.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-redux": {
|
"react-redux": {
|
||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.3.tgz",
|
||||||
@@ -13083,6 +13205,20 @@
|
|||||||
"workbox-webpack-plugin": "5.1.4"
|
"workbox-webpack-plugin": "5.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-select": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-select/-/react-select-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-SBPD1a3TJqE9zoI/jfOLCAoLr/neluaeokjOixr3zZ1vHezkom8K0A9J4QG9IWDqIDE9K/Mv+0y1GjidC2PDtQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.0",
|
||||||
|
"@emotion/cache": "^11.0.0",
|
||||||
|
"@emotion/react": "^11.1.1",
|
||||||
|
"memoize-one": "^5.0.0",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"react-input-autosize": "^3.0.0",
|
||||||
|
"react-transition-group": "^4.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-transition-group": {
|
"react-transition-group": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||||
@@ -13094,6 +13230,39 @@
|
|||||||
"prop-types": "^15.6.2"
|
"prop-types": "^15.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"reactstrap": {
|
||||||
|
"version": "8.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.9.0.tgz",
|
||||||
|
"integrity": "sha512-pmf33YjpNZk1IfrjqpWCUMq9hk6GzSnMWBAofTBNIRJQB1zQ0Au2kzv3lPUAFsBYgWEuI9iYa/xKXHaboSiMkQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"classnames": "^2.2.3",
|
||||||
|
"prop-types": "^15.5.8",
|
||||||
|
"react-popper": "^1.3.6",
|
||||||
|
"react-transition-group": "^2.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dom-helpers": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-transition-group": {
|
||||||
|
"version": "2.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
|
||||||
|
"integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-helpers": "^3.4.0",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
||||||
@@ -14799,6 +14968,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"stylis": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg=="
|
||||||
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
@@ -15337,6 +15511,11 @@
|
|||||||
"mime-types": "~2.1.24"
|
"mime-types": "~2.1.24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typed-styles": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q=="
|
||||||
|
},
|
||||||
"typedarray": {
|
"typedarray": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
|||||||
@@ -22,9 +22,12 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-bootstrap": "^1.5.2",
|
"react-bootstrap": "^1.5.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-paginate": "^7.1.2",
|
||||||
"react-redux": "^7.2.3",
|
"react-redux": "^7.2.3",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
|
"react-select": "^4.3.0",
|
||||||
|
"reactstrap": "^8.9.0",
|
||||||
"sass": "^1.32.8",
|
"sass": "^1.32.8",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
CBadge,
|
CBadge,
|
||||||
CCardBody,
|
CCardBody,
|
||||||
CDataTable,
|
CDataTable,
|
||||||
CCollapse,
|
CCollapse,
|
||||||
CButton,
|
CButton,
|
||||||
CLink,
|
CLink,
|
||||||
CCard,
|
CCard,
|
||||||
CCardHeader
|
CCardHeader,
|
||||||
|
CRow,
|
||||||
|
CCol
|
||||||
} from '@coreui/react'
|
} from '@coreui/react'
|
||||||
|
import ReactPaginate from 'react-paginate';
|
||||||
|
import Select from 'react-select'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faSync, faInfo } from '@fortawesome/free-solid-svg-icons'
|
import { faInfo } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { getToken } from '../utils/authHelper';
|
import { getToken } from '../utils/authHelper';
|
||||||
import axiosInstance from '../utils/axiosInstance';
|
import axiosInstance from '../utils/axiosInstance';
|
||||||
import { cleanTimestamp, cleanBytesString } from '../utils/helper';
|
import { cleanTimestamp, cleanBytesString } from '../utils/helper';
|
||||||
@@ -20,256 +24,306 @@ import { cilRouter } from '@coreui/icons';
|
|||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
|
|
||||||
const DeviceList = () => {
|
const DeviceList = () => {
|
||||||
const [devices, setDevices] = useState([]);
|
const [loadedSerials, setLoadedSerials] = useState(false);
|
||||||
const [details, setDetails] = useState([]);
|
const [serialNumbers, setSerialNumbers] = useState([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [page, setPage] = useState(0);
|
||||||
const [lastRefresh, setLastRefresh] = useState([]);
|
const [pageCount, setPageCount] = useState(0);
|
||||||
|
const [devicesPerPage, setDevicesPerPage] = useState(10);
|
||||||
|
const [devices, setDevices] = useState([]);
|
||||||
|
const [details, setDetails] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [lastRefresh, setLastRefresh] = useState([]);
|
||||||
|
|
||||||
//Loading the devices
|
const getSerialNumbers = () => {
|
||||||
const refreshDevices = useCallback(() => {
|
const token = getToken();
|
||||||
const token = getToken();
|
setLoading(true);
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance.get('/devices', {
|
axiosInstance.get('/devices?serialOnly=true', {
|
||||||
headers: headers
|
headers: headers
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const date = new Date();
|
setSerialNumbers(response.data.serialNumbers);
|
||||||
const dateAsString = date.toLocaleString();
|
setLoadedSerials(true);
|
||||||
setLastRefresh(dateAsString);
|
})
|
||||||
addStatusToDeviceList(response.data.devices);
|
.catch(error => {
|
||||||
})
|
setLoading(false);
|
||||||
.catch(error => {
|
console.log(error.response);
|
||||||
setLoading(false);
|
});
|
||||||
console.log(error.response);
|
};
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
//Getting the status for each device
|
|
||||||
const addStatusToDeviceList = (devices) => {
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Authorization': `Bearer ${token}`
|
|
||||||
};
|
|
||||||
|
|
||||||
const promises = [];
|
const getDeviceInformation = () => {
|
||||||
|
const token = getToken();
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
for(let i = 0; i< devices.length; i++){
|
const headers = {
|
||||||
promises.push(
|
'Accept': 'application/json',
|
||||||
axiosInstance.get(`/device/${devices[i].serialNumber}/status`, {
|
'Authorization': `Bearer ${token}`
|
||||||
headers: headers
|
};
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
devices[i] = {...devices[i], ...response.data};
|
|
||||||
devices[i].ipAddress = devices[i].ipAddress.substr(0, devices[i].ipAddress.indexOf(':'));
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error.response);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Waiting for all requests to finish before setting the device array
|
const startIndex = page * devicesPerPage;
|
||||||
Promise.all(promises).then(() =>{
|
const serialsToGet = serialNumbers.slice(startIndex, (startIndex + devicesPerPage)).join(',');
|
||||||
setDevices(devices);
|
|
||||||
setLoading(false);
|
console.log(serialsToGet);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//Function called from the button on the table so that a user can see more details
|
axiosInstance.get(`/devices?deviceWithStatus=true&select=${serialsToGet}`, {
|
||||||
const toggleDetails = (index) => {
|
headers: headers
|
||||||
const position = details.indexOf(index)
|
})
|
||||||
let newDetails = details.slice()
|
.then((response) => {
|
||||||
if (position !== -1) {
|
setDevices(response.data.devicesWithStatus);
|
||||||
newDetails.splice(position, 1)
|
setLoading(false);
|
||||||
} else {
|
updateRefresh();
|
||||||
newDetails = [...details, index]
|
})
|
||||||
}
|
.catch(error => {
|
||||||
setDetails(newDetails)
|
setLoading(false);
|
||||||
}
|
console.log(error.response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//refreshDevice() has a semicolon after to make it run once on component loading
|
const updateRefresh = () => {
|
||||||
useEffect(() => {refreshDevices();},[refreshDevices]);
|
const date = new Date();
|
||||||
|
const dateAsString = date.toLocaleString();
|
||||||
|
setLastRefresh(dateAsString);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
//Function called from the button on the table so that a user can see more details
|
||||||
<DeviceListDisplay
|
const toggleDetails = (index) => {
|
||||||
devices={devices}
|
const position = details.indexOf(index)
|
||||||
refresh={refreshDevices}
|
let newDetails = details.slice()
|
||||||
toggleDetails={toggleDetails}
|
if (position !== -1) {
|
||||||
details={details}
|
newDetails.splice(position, 1)
|
||||||
loading={loading}
|
} else {
|
||||||
lastRefresh={lastRefresh}
|
newDetails = [...details, index]
|
||||||
/>
|
}
|
||||||
)
|
setDetails(newDetails)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateDevicesPerPage = (value) => {
|
||||||
|
console.log('update devices per page ' + value)
|
||||||
|
setDevicesPerPage(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatePageCount = ({ selected: selectedPage }) => {
|
||||||
|
setPage(selectedPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initial load
|
||||||
|
useEffect(() => {
|
||||||
|
getSerialNumbers();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
//Updating the devices only if serial numbers, page number or devices per page changes
|
||||||
|
useEffect(()=>{
|
||||||
|
console.log('in get device effect');
|
||||||
|
if(loadedSerials) getDeviceInformation();
|
||||||
|
}, [serialNumbers, page, devicesPerPage, loadedSerials]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(loadedSerials) {
|
||||||
|
const count = Math.ceil(serialNumbers.length / devicesPerPage);
|
||||||
|
setPageCount(count);
|
||||||
|
}
|
||||||
|
}, [devicesPerPage, loadedSerials]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DeviceListDisplay
|
||||||
|
devices={devices}
|
||||||
|
toggleDetails={toggleDetails}
|
||||||
|
details={details}
|
||||||
|
loading={loading}
|
||||||
|
updateDevicesPerPage={updateDevicesPerPage}
|
||||||
|
pageCount={pageCount}
|
||||||
|
updatePage={updatePageCount}
|
||||||
|
pageRangeDisplayed={5}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeviceListDisplay = ({ devices, refresh, toggleDetails, details, loading, lastRefresh }) => {
|
const DeviceListDisplay = ({ devices, toggleDetails, details, loading, updateDevicesPerPage, pageCount, updatePage }) => {
|
||||||
const columns = [
|
const columns = [
|
||||||
{ key: 'serialNumber'},
|
{ key: 'serialNumber'},
|
||||||
{ key: 'UUID', label: 'Config Id'},
|
{ key: 'UUID', label: 'Config Id'},
|
||||||
{
|
{
|
||||||
key: 'lastConfigurationChange'
|
key: 'lastConfigurationChange'
|
||||||
,filter: false
|
,filter: false
|
||||||
,label: 'Configuration Change'
|
,label: 'Configuration Change'
|
||||||
},
|
},
|
||||||
{ key: 'firmware', filter: false },
|
{ key: 'firmware', filter: false },
|
||||||
{ key: 'deviceType', filter: false, sorter: false},
|
{ key: 'deviceType', filter: false, sorter: false},
|
||||||
{ key: 'connected', _style: { width: '1%' }, sorter: false},
|
{ key: 'connected', _style: { width: '1%' }, sorter: false},
|
||||||
{ key: 'txBytes', filter: false },
|
{ key: 'txBytes', filter: false },
|
||||||
{ key: 'rxBytes', filter: false },
|
{ key: 'rxBytes', filter: false },
|
||||||
{ key: 'ipAddress'},
|
{ key: 'ipAddress'},
|
||||||
{
|
{
|
||||||
key: 'show_details',
|
key: 'show_details',
|
||||||
label: '',
|
label: '',
|
||||||
_style: { width: '1%' },
|
_style: { width: '1%' },
|
||||||
sorter: false,
|
sorter: false,
|
||||||
filter: false
|
filter: false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: '10', label: '10' },
|
||||||
|
{ value: '25', label: '25' },
|
||||||
|
{ value: '50', label: '50' }
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
const getDeviceIcon = (deviceType) =>{
|
const getDeviceIcon = (deviceType) =>{
|
||||||
if(deviceType === "AP_Default"){
|
if(deviceType === "AP_Default"){
|
||||||
return <CIcon name="cilRouter" size="2xl"></CIcon>;
|
return <CIcon name="cilRouter" size="2xl"></CIcon>;
|
||||||
}
|
}
|
||||||
else if(deviceType === "IOT"){
|
else if(deviceType === "IOT"){
|
||||||
return <img src={iotIcon} style={{height:'32px', width:'32px'}}/>;
|
return <img src={iotIcon} style={{height:'32px', width:'32px'}}/>;
|
||||||
}
|
}
|
||||||
else if(deviceType === "SWITCH"){
|
else if(deviceType === "SWITCH"){
|
||||||
return <img src={internetSwitch} style={{height:'32px', width:'32px'}}/>;
|
return <img src={internetSwitch} style={{height:'32px', width:'32px'}}/>;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStatusBadge = (status) => {
|
const getStatusBadge = (status) => {
|
||||||
if(status){
|
if(status){
|
||||||
return 'success';
|
return 'success';
|
||||||
}
|
}
|
||||||
return 'danger';
|
return 'danger';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CCard>
|
<CCard>
|
||||||
<CCardHeader>
|
<CCardHeader>
|
||||||
<div className='row'>
|
<CRow>
|
||||||
<div className='col'>
|
<CCol>
|
||||||
<CButton onClick={refresh}>
|
Device List
|
||||||
<FontAwesomeIcon icon={faSync} color='#007bff' size="2x"/>
|
</CCol>
|
||||||
</CButton>
|
<CCol xs={2}>
|
||||||
</div>
|
<Select
|
||||||
<div className='col'><div className='form-inline justify-content-sm-end'>
|
isClearable = { false }
|
||||||
Last refresh : {lastRefresh}
|
options = { selectOptions }
|
||||||
</div>
|
defaultValue = {{ value : '10', label: '10' }}
|
||||||
</div>
|
onChange={value => updateDevicesPerPage(value.value)}
|
||||||
</div>
|
/>
|
||||||
</CCardHeader>
|
</CCol>
|
||||||
<CCardBody>
|
</CRow>
|
||||||
<CDataTable
|
</CCardHeader>
|
||||||
items={devices}
|
<CCardBody>
|
||||||
fields={columns}
|
<CDataTable
|
||||||
itemsPerPageSelect
|
items={devices}
|
||||||
itemsPerPage={10}
|
fields={columns}
|
||||||
border
|
border
|
||||||
hover
|
hover
|
||||||
sorter
|
loading = {loading}
|
||||||
pagination
|
scopedSlots = {{
|
||||||
columnFilter
|
'lastConfigurationChange':
|
||||||
loading = {loading}
|
(item)=>(
|
||||||
scopedSlots = {{
|
<td>
|
||||||
'lastConfigurationChange':
|
{cleanTimestamp(item.lastConfigurationChange)}
|
||||||
(item)=>(
|
</td>
|
||||||
<td>
|
),
|
||||||
{cleanTimestamp(item.lastConfigurationChange)}
|
'deviceType':
|
||||||
</td>
|
(item)=>(
|
||||||
),
|
<td style={{textAlign: 'center'}}>
|
||||||
'deviceType':
|
{getDeviceIcon(item.deviceType) ?? item.deviceType}
|
||||||
(item)=>(
|
</td>
|
||||||
<td style={{textAlign: 'center'}}>
|
),
|
||||||
{getDeviceIcon(item.deviceType) ?? item.deviceType}
|
'firmware':
|
||||||
</td>
|
(item)=>(
|
||||||
),
|
<td>
|
||||||
'firmware':
|
{item.firmware && item.firmware !== "" ? item.firmware : 'N/A'}
|
||||||
(item)=>(
|
</td>
|
||||||
<td>
|
),
|
||||||
{item.firmware && item.firmware != "" ? item.firmware : 'N/A'}
|
'txBytes':
|
||||||
</td>
|
(item)=>(
|
||||||
),
|
<td>
|
||||||
'txBytes':
|
{cleanBytesString(item.txBytes)}
|
||||||
(item)=>(
|
</td>
|
||||||
<td>
|
),
|
||||||
{cleanBytesString(item.txBytes)}
|
'rxBytes':
|
||||||
</td>
|
(item)=>(
|
||||||
),
|
<td>
|
||||||
'rxBytes':
|
{cleanBytesString(item.rxBytes)}
|
||||||
(item)=>(
|
</td>
|
||||||
<td>
|
),
|
||||||
{cleanBytesString(item.rxBytes)}
|
'ipAddress':
|
||||||
</td>
|
(item)=>(
|
||||||
),
|
<td>
|
||||||
'ipAddress':
|
{item.ipAddress ?? 'N/A'}
|
||||||
(item)=>(
|
</td>
|
||||||
<td>
|
),
|
||||||
{item.ipAddress ?? 'N/A'}
|
'connected':
|
||||||
</td>
|
(item)=>(
|
||||||
),
|
<td>
|
||||||
'connected':
|
<CBadge color={getStatusBadge(item.connected)}>
|
||||||
(item)=>(
|
{item.connected ? 'Connected' : 'Not connected'}
|
||||||
<td>
|
</CBadge>
|
||||||
<CBadge color={getStatusBadge(item.connected)}>
|
</td>
|
||||||
{item.connected ? 'Connected' : 'Not connected'}
|
),
|
||||||
</CBadge>
|
'show_details':
|
||||||
</td>
|
(item, index)=>{
|
||||||
),
|
return (
|
||||||
'show_details':
|
<td className="py-2">
|
||||||
(item, index)=>{
|
<CButton
|
||||||
return (
|
color="primary"
|
||||||
<td className="py-2">
|
variant="outline"
|
||||||
<CButton
|
shape="square"
|
||||||
color="primary"
|
size="sm"
|
||||||
variant="outline"
|
onClick={()=>{toggleDetails(index)}}
|
||||||
shape="square"
|
>
|
||||||
size="sm"
|
<FontAwesomeIcon icon={faInfo}/>
|
||||||
onClick={()=>{toggleDetails(index)}}
|
</CButton>
|
||||||
>
|
</td>
|
||||||
<FontAwesomeIcon icon={faInfo}/>
|
)
|
||||||
</CButton>
|
},
|
||||||
</td>
|
'details':
|
||||||
)
|
(item, index)=>{
|
||||||
},
|
return (
|
||||||
'details':
|
<CCollapse show={details.includes(index)}>
|
||||||
(item, index)=>{
|
<CCardBody>
|
||||||
return (
|
<h4>
|
||||||
<CCollapse show={details.includes(index)}>
|
{item.notes}
|
||||||
<CCardBody>
|
</h4>
|
||||||
<h4>
|
<p className="text-muted">Last configuration change: {item.lastConfigurationChange.replace('T', ' ').replace('Z', '')}</p>
|
||||||
{item.notes}
|
<CLink
|
||||||
</h4>
|
className="c-subheader-nav-link"
|
||||||
<p className="text-muted">Last configuration change: {item.lastConfigurationChange.replace('T', ' ').replace('Z', '')}</p>
|
aria-current="page"
|
||||||
<CLink
|
to={() => `/devices/${item.serialNumber}`}
|
||||||
className="c-subheader-nav-link"
|
>
|
||||||
aria-current="page"
|
<CButton size="sm" color="info">
|
||||||
to={() => `/devices/${item.serialNumber}`}
|
Device Details
|
||||||
>
|
</CButton>
|
||||||
<CButton size="sm" color="info">
|
</CLink>
|
||||||
Device Details
|
</CCardBody>
|
||||||
</CButton>
|
</CCollapse>
|
||||||
</CLink>
|
)
|
||||||
</CCardBody>
|
}
|
||||||
</CCollapse>
|
}}/>
|
||||||
)
|
<ReactPaginate
|
||||||
}
|
previousLabel={"← Previous"}
|
||||||
}}/>
|
nextLabel={"Next →"}
|
||||||
</CCardBody>
|
pageCount={pageCount}
|
||||||
</CCard>
|
onPageChange={updatePage}
|
||||||
</>
|
breakClassName={'page-item'}
|
||||||
|
breakLinkClassName={'page-link'}
|
||||||
|
containerClassName={'pagination'}
|
||||||
|
pageClassName={'page-item'}
|
||||||
|
pageLinkClassName={'page-link'}
|
||||||
|
previousClassName={'page-item'}
|
||||||
|
previousLinkClassName={'page-link'}
|
||||||
|
nextClassName={'page-item'}
|
||||||
|
nextLinkClassName={'page-link'}
|
||||||
|
activeClassName={'active'}
|
||||||
|
/>
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user