Compare commits
2 Commits
0bac8d0f25
...
6691122c8f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6691122c8f | ||
| 8b95a620c2 |
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "smatec-frontend",
|
"name": "SMATEC-FRONTEND",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
123
pnpm-lock.yaml
generated
123
pnpm-lock.yaml
generated
@@ -26,6 +26,15 @@ importers:
|
|||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.19
|
specifier: ^1.11.19
|
||||||
version: 1.11.19
|
version: 1.11.19
|
||||||
|
moment:
|
||||||
|
specifier: ^2.30.1
|
||||||
|
version: 2.30.1
|
||||||
|
ol:
|
||||||
|
specifier: ^10.6.1
|
||||||
|
version: 10.7.0
|
||||||
|
reconnecting-websocket:
|
||||||
|
specifier: ^4.4.0
|
||||||
|
version: 4.4.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.0.33
|
specifier: ^18.0.33
|
||||||
@@ -1091,6 +1100,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, tarball: https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz}
|
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, tarball: https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
'@petamoriken/float16@3.9.3':
|
||||||
|
resolution: {integrity: sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==, tarball: https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.3.tgz}
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz}
|
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -1356,6 +1368,9 @@ packages:
|
|||||||
'@types/prop-types@15.7.15':
|
'@types/prop-types@15.7.15':
|
||||||
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==, tarball: https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz}
|
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==, tarball: https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz}
|
||||||
|
|
||||||
|
'@types/rbush@4.0.0':
|
||||||
|
resolution: {integrity: sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==, tarball: https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz}
|
||||||
|
|
||||||
'@types/react-dom@18.3.7':
|
'@types/react-dom@18.3.7':
|
||||||
resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==, tarball: https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz}
|
resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==, tarball: https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2746,6 +2761,9 @@ packages:
|
|||||||
react: 15.x || ^16.0.0-0
|
react: 15.x || ^16.0.0-0
|
||||||
react-dom: 15.x || ^16.0.0-0
|
react-dom: 15.x || ^16.0.0-0
|
||||||
|
|
||||||
|
earcut@3.0.2:
|
||||||
|
resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==, tarball: https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz}
|
||||||
|
|
||||||
eastasianwidth@0.2.0:
|
eastasianwidth@0.2.0:
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, tarball: https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, tarball: https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz}
|
||||||
|
|
||||||
@@ -3179,6 +3197,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, tarball: https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz}
|
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, tarball: https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
geotiff@2.1.3:
|
||||||
|
resolution: {integrity: sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==, tarball: https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz}
|
||||||
|
engines: {node: '>=10.19'}
|
||||||
|
|
||||||
get-caller-file@2.0.5:
|
get-caller-file@2.0.5:
|
||||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, tarball: https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz}
|
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, tarball: https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz}
|
||||||
engines: {node: 6.* || 8.* || >= 10.*}
|
engines: {node: 6.* || 8.* || >= 10.*}
|
||||||
@@ -3840,6 +3862,9 @@ packages:
|
|||||||
kolorist@1.8.0:
|
kolorist@1.8.0:
|
||||||
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==, tarball: https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz}
|
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==, tarball: https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz}
|
||||||
|
|
||||||
|
lerc@3.0.0:
|
||||||
|
resolution: {integrity: sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==, tarball: https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz}
|
||||||
|
|
||||||
less-loader@12.3.0:
|
less-loader@12.3.0:
|
||||||
resolution: {integrity: sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==, tarball: https://registry.npmjs.org/less-loader/-/less-loader-12.3.0.tgz}
|
resolution: {integrity: sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==, tarball: https://registry.npmjs.org/less-loader/-/less-loader-12.3.0.tgz}
|
||||||
engines: {node: '>= 18.12.0'}
|
engines: {node: '>= 18.12.0'}
|
||||||
@@ -4281,6 +4306,9 @@ packages:
|
|||||||
obuf@1.1.2:
|
obuf@1.1.2:
|
||||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==, tarball: https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz}
|
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==, tarball: https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz}
|
||||||
|
|
||||||
|
ol@10.7.0:
|
||||||
|
resolution: {integrity: sha512-122U5gamPqNgLpLOkogFJhgpywvd/5en2kETIDW+Ubfi9lPnZ0G9HWRdG+CX0oP8od2d6u6ky3eewIYYlrVczw==, tarball: https://registry.npmjs.org/ol/-/ol-10.7.0.tgz}
|
||||||
|
|
||||||
on-exit-leak-free@0.2.0:
|
on-exit-leak-free@0.2.0:
|
||||||
resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==, tarball: https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz}
|
resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==, tarball: https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz}
|
||||||
|
|
||||||
@@ -4352,6 +4380,9 @@ packages:
|
|||||||
pako@1.0.11:
|
pako@1.0.11:
|
||||||
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==, tarball: https://registry.npmjs.org/pako/-/pako-1.0.11.tgz}
|
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==, tarball: https://registry.npmjs.org/pako/-/pako-1.0.11.tgz}
|
||||||
|
|
||||||
|
pako@2.1.0:
|
||||||
|
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==, tarball: https://registry.npmjs.org/pako/-/pako-2.1.0.tgz}
|
||||||
|
|
||||||
param-case@3.0.4:
|
param-case@3.0.4:
|
||||||
resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==, tarball: https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz}
|
resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==, tarball: https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz}
|
||||||
|
|
||||||
@@ -4363,6 +4394,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==, tarball: https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz}
|
resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==, tarball: https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
|
||||||
|
parse-headers@2.0.6:
|
||||||
|
resolution: {integrity: sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==, tarball: https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz}
|
||||||
|
|
||||||
parse-json@5.2.0:
|
parse-json@5.2.0:
|
||||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, tarball: https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz}
|
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, tarball: https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -4421,6 +4455,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, tarball: https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz}
|
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, tarball: https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
pbf@4.0.1:
|
||||||
|
resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==, tarball: https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
pbkdf2@3.1.5:
|
pbkdf2@3.1.5:
|
||||||
resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==, tarball: https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz}
|
resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==, tarball: https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@@ -4835,6 +4873,9 @@ packages:
|
|||||||
prop-types@15.8.1:
|
prop-types@15.8.1:
|
||||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, tarball: https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz}
|
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, tarball: https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz}
|
||||||
|
|
||||||
|
protocol-buffers-schema@3.6.0:
|
||||||
|
resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==, tarball: https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz}
|
||||||
|
|
||||||
proxy-addr@2.0.7:
|
proxy-addr@2.0.7:
|
||||||
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, tarball: https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz}
|
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, tarball: https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@@ -4883,6 +4924,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==, tarball: https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz}
|
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==, tarball: https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
quick-lru@6.1.2:
|
||||||
|
resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==, tarball: https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
quickselect@3.0.0:
|
||||||
|
resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==, tarball: https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz}
|
||||||
|
|
||||||
randombytes@2.1.0:
|
randombytes@2.1.0:
|
||||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, tarball: https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz}
|
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, tarball: https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz}
|
||||||
|
|
||||||
@@ -4897,6 +4945,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==, tarball: https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz}
|
resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==, tarball: https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
rbush@4.0.1:
|
||||||
|
resolution: {integrity: sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==, tarball: https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz}
|
||||||
|
|
||||||
rc-align@4.0.15:
|
rc-align@4.0.15:
|
||||||
resolution: {integrity: sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==, tarball: https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz}
|
resolution: {integrity: sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==, tarball: https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5462,6 +5513,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==, tarball: https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz}
|
resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==, tarball: https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz}
|
||||||
engines: {node: '>= 12.13.0'}
|
engines: {node: '>= 12.13.0'}
|
||||||
|
|
||||||
|
reconnecting-websocket@4.4.0:
|
||||||
|
resolution: {integrity: sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==, tarball: https://registry.npmjs.org/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz}
|
||||||
|
|
||||||
redent@3.0.0:
|
redent@3.0.0:
|
||||||
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, tarball: https://registry.npmjs.org/redent/-/redent-3.0.0.tgz}
|
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, tarball: https://registry.npmjs.org/redent/-/redent-3.0.0.tgz}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -5538,6 +5592,9 @@ packages:
|
|||||||
resolve-pkg-maps@1.0.0:
|
resolve-pkg-maps@1.0.0:
|
||||||
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==, tarball: https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz}
|
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==, tarball: https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz}
|
||||||
|
|
||||||
|
resolve-protobuf-schema@2.1.0:
|
||||||
|
resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==, tarball: https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz}
|
||||||
|
|
||||||
resolve-url-loader@5.0.0:
|
resolve-url-loader@5.0.0:
|
||||||
resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==, tarball: https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz}
|
resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==, tarball: https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -6377,6 +6434,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==, tarball: https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz}
|
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==, tarball: https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
web-worker@1.5.0:
|
||||||
|
resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==, tarball: https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz}
|
||||||
|
|
||||||
webpack-5-chain@8.0.1:
|
webpack-5-chain@8.0.1:
|
||||||
resolution: {integrity: sha512-Tu1w80WA2Z+X6e7KzGy+cc0A0z+npVJA/fh55q2azMJ030gqz343Kx+yNAstDCeugsepmtDWY2J2IBRW/O+DEA==, tarball: https://registry.npmjs.org/webpack-5-chain/-/webpack-5-chain-8.0.1.tgz}
|
resolution: {integrity: sha512-Tu1w80WA2Z+X6e7KzGy+cc0A0z+npVJA/fh55q2azMJ030gqz343Kx+yNAstDCeugsepmtDWY2J2IBRW/O+DEA==, tarball: https://registry.npmjs.org/webpack-5-chain/-/webpack-5-chain-8.0.1.tgz}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -6454,6 +6514,9 @@ packages:
|
|||||||
utf-8-validate:
|
utf-8-validate:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
xml-utils@1.10.2:
|
||||||
|
resolution: {integrity: sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==, tarball: https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.2.tgz}
|
||||||
|
|
||||||
xtend@4.0.2:
|
xtend@4.0.2:
|
||||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, tarball: https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz}
|
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, tarball: https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz}
|
||||||
engines: {node: '>=0.4'}
|
engines: {node: '>=0.4'}
|
||||||
@@ -6501,6 +6564,9 @@ packages:
|
|||||||
zod@3.25.76:
|
zod@3.25.76:
|
||||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, tarball: https://registry.npmjs.org/zod/-/zod-3.25.76.tgz}
|
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, tarball: https://registry.npmjs.org/zod/-/zod-3.25.76.tgz}
|
||||||
|
|
||||||
|
zstddec@0.1.0:
|
||||||
|
resolution: {integrity: sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==, tarball: https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz}
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@ahooksjs/use-request@2.8.15(react@18.3.1)':
|
'@ahooksjs/use-request@2.8.15(react@18.3.1)':
|
||||||
@@ -7810,6 +7876,8 @@ snapshots:
|
|||||||
'@nodelib/fs.scandir': 2.1.5
|
'@nodelib/fs.scandir': 2.1.5
|
||||||
fastq: 1.20.1
|
fastq: 1.20.1
|
||||||
|
|
||||||
|
'@petamoriken/float16@3.9.3': {}
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -8095,6 +8163,8 @@ snapshots:
|
|||||||
|
|
||||||
'@types/prop-types@15.7.15': {}
|
'@types/prop-types@15.7.15': {}
|
||||||
|
|
||||||
|
'@types/rbush@4.0.0': {}
|
||||||
|
|
||||||
'@types/react-dom@18.3.7(@types/react@18.3.27)':
|
'@types/react-dom@18.3.7(@types/react@18.3.27)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.27
|
'@types/react': 18.3.27
|
||||||
@@ -10061,6 +10131,8 @@ snapshots:
|
|||||||
react-router-redux: 5.0.0-alpha.9(react@18.3.1)
|
react-router-redux: 5.0.0-alpha.9(react@18.3.1)
|
||||||
redux: 3.7.2
|
redux: 3.7.2
|
||||||
|
|
||||||
|
earcut@3.0.2: {}
|
||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
eastasianwidth@0.2.0: {}
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
@@ -10704,6 +10776,17 @@ snapshots:
|
|||||||
|
|
||||||
gensync@1.0.0-beta.2: {}
|
gensync@1.0.0-beta.2: {}
|
||||||
|
|
||||||
|
geotiff@2.1.3:
|
||||||
|
dependencies:
|
||||||
|
'@petamoriken/float16': 3.9.3
|
||||||
|
lerc: 3.0.0
|
||||||
|
pako: 2.1.0
|
||||||
|
parse-headers: 2.0.6
|
||||||
|
quick-lru: 6.1.2
|
||||||
|
web-worker: 1.5.0
|
||||||
|
xml-utils: 1.10.2
|
||||||
|
zstddec: 0.1.0
|
||||||
|
|
||||||
get-caller-file@2.0.5: {}
|
get-caller-file@2.0.5: {}
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
@@ -11398,6 +11481,8 @@ snapshots:
|
|||||||
|
|
||||||
kolorist@1.8.0: {}
|
kolorist@1.8.0: {}
|
||||||
|
|
||||||
|
lerc@3.0.0: {}
|
||||||
|
|
||||||
less-loader@12.3.0(less@4.5.1)(webpack@5.104.1):
|
less-loader@12.3.0(less@4.5.1)(webpack@5.104.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
less: 4.5.1
|
less: 4.5.1
|
||||||
@@ -11877,6 +11962,14 @@ snapshots:
|
|||||||
|
|
||||||
obuf@1.1.2: {}
|
obuf@1.1.2: {}
|
||||||
|
|
||||||
|
ol@10.7.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/rbush': 4.0.0
|
||||||
|
earcut: 3.0.2
|
||||||
|
geotiff: 2.1.3
|
||||||
|
pbf: 4.0.1
|
||||||
|
rbush: 4.0.1
|
||||||
|
|
||||||
on-exit-leak-free@0.2.0: {}
|
on-exit-leak-free@0.2.0: {}
|
||||||
|
|
||||||
on-finished@2.3.0:
|
on-finished@2.3.0:
|
||||||
@@ -11953,6 +12046,8 @@ snapshots:
|
|||||||
|
|
||||||
pako@1.0.11: {}
|
pako@1.0.11: {}
|
||||||
|
|
||||||
|
pako@2.1.0: {}
|
||||||
|
|
||||||
param-case@3.0.4:
|
param-case@3.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
dot-case: 3.0.4
|
dot-case: 3.0.4
|
||||||
@@ -11970,6 +12065,8 @@ snapshots:
|
|||||||
pbkdf2: 3.1.5
|
pbkdf2: 3.1.5
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
parse-headers@2.0.6: {}
|
||||||
|
|
||||||
parse-json@5.2.0:
|
parse-json@5.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.28.6
|
'@babel/code-frame': 7.28.6
|
||||||
@@ -12017,6 +12114,10 @@ snapshots:
|
|||||||
|
|
||||||
path-type@4.0.0: {}
|
path-type@4.0.0: {}
|
||||||
|
|
||||||
|
pbf@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
resolve-protobuf-schema: 2.1.0
|
||||||
|
|
||||||
pbkdf2@3.1.5:
|
pbkdf2@3.1.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
create-hash: 1.2.0
|
create-hash: 1.2.0
|
||||||
@@ -12396,6 +12497,8 @@ snapshots:
|
|||||||
object-assign: 4.1.1
|
object-assign: 4.1.1
|
||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
|
|
||||||
|
protocol-buffers-schema@3.6.0: {}
|
||||||
|
|
||||||
proxy-addr@2.0.7:
|
proxy-addr@2.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
forwarded: 0.2.0
|
forwarded: 0.2.0
|
||||||
@@ -12447,6 +12550,10 @@ snapshots:
|
|||||||
|
|
||||||
quick-lru@4.0.1: {}
|
quick-lru@4.0.1: {}
|
||||||
|
|
||||||
|
quick-lru@6.1.2: {}
|
||||||
|
|
||||||
|
quickselect@3.0.0: {}
|
||||||
|
|
||||||
randombytes@2.1.0:
|
randombytes@2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
@@ -12465,6 +12572,10 @@ snapshots:
|
|||||||
iconv-lite: 0.4.24
|
iconv-lite: 0.4.24
|
||||||
unpipe: 1.0.0
|
unpipe: 1.0.0
|
||||||
|
|
||||||
|
rbush@4.0.1:
|
||||||
|
dependencies:
|
||||||
|
quickselect: 3.0.0
|
||||||
|
|
||||||
rc-align@4.0.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
rc-align@4.0.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.28.6
|
'@babel/runtime': 7.28.6
|
||||||
@@ -13262,6 +13373,8 @@ snapshots:
|
|||||||
|
|
||||||
real-require@0.1.0: {}
|
real-require@0.1.0: {}
|
||||||
|
|
||||||
|
reconnecting-websocket@4.4.0: {}
|
||||||
|
|
||||||
redent@3.0.0:
|
redent@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
indent-string: 4.0.0
|
indent-string: 4.0.0
|
||||||
@@ -13340,6 +13453,10 @@ snapshots:
|
|||||||
|
|
||||||
resolve-pkg-maps@1.0.0: {}
|
resolve-pkg-maps@1.0.0: {}
|
||||||
|
|
||||||
|
resolve-protobuf-schema@2.1.0:
|
||||||
|
dependencies:
|
||||||
|
protocol-buffers-schema: 3.6.0
|
||||||
|
|
||||||
resolve-url-loader@5.0.0:
|
resolve-url-loader@5.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
adjust-sourcemap-loader: 4.0.0
|
adjust-sourcemap-loader: 4.0.0
|
||||||
@@ -14334,6 +14451,8 @@ snapshots:
|
|||||||
|
|
||||||
web-streams-polyfill@3.3.3: {}
|
web-streams-polyfill@3.3.3: {}
|
||||||
|
|
||||||
|
web-worker@1.5.0: {}
|
||||||
|
|
||||||
webpack-5-chain@8.0.1:
|
webpack-5-chain@8.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
deepmerge: 1.5.2
|
deepmerge: 1.5.2
|
||||||
@@ -14447,6 +14566,8 @@ snapshots:
|
|||||||
|
|
||||||
ws@8.19.0: {}
|
ws@8.19.0: {}
|
||||||
|
|
||||||
|
xml-utils@1.10.2: {}
|
||||||
|
|
||||||
xtend@4.0.2: {}
|
xtend@4.0.2: {}
|
||||||
|
|
||||||
y18n@5.0.8: {}
|
y18n@5.0.8: {}
|
||||||
@@ -14480,3 +14601,5 @@ snapshots:
|
|||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
|
|
||||||
zod@3.25.76: {}
|
zod@3.25.76: {}
|
||||||
|
|
||||||
|
zstddec@0.1.0: {}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
|||||||
contentWidth: 'Fluid',
|
contentWidth: 'Fluid',
|
||||||
navTheme: isDark ? 'realDark' : 'light',
|
navTheme: isDark ? 'realDark' : 'light',
|
||||||
splitMenus: true,
|
splitMenus: true,
|
||||||
iconfontUrl: '//at.alicdn.com/t/c/font_5096559_fvnh1x2eqer.js',
|
iconfontUrl: '//at.alicdn.com/t/c/font_5096559_pw36kpy0e7h.js',
|
||||||
contentStyle: {
|
contentStyle: {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
|
|||||||
@@ -13,17 +13,23 @@ import TreeGroup from './TreeGroup';
|
|||||||
|
|
||||||
const { Paragraph } = Typography;
|
const { Paragraph } = Typography;
|
||||||
type ThingsFilterProps = {
|
type ThingsFilterProps = {
|
||||||
|
title?: string;
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
thingIds?: string | string[] | null;
|
thingIds?: string | string[] | null;
|
||||||
|
extra?: React.ReactNode;
|
||||||
onSubmit?: (thingIds: string[]) => void;
|
onSubmit?: (thingIds: string[]) => void;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ThingsFilter = ({
|
const ThingsFilter = ({
|
||||||
|
title,
|
||||||
isOpen,
|
isOpen,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
thingIds,
|
thingIds,
|
||||||
|
extra,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
disabled = false,
|
||||||
}: ThingsFilterProps) => {
|
}: ThingsFilterProps) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { useBreakpoint } = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
@@ -93,6 +99,7 @@ const ThingsFilter = ({
|
|||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
title={title ? title : null}
|
||||||
open={isOpen}
|
open={isOpen}
|
||||||
centered
|
centered
|
||||||
width="80%"
|
width="80%"
|
||||||
@@ -104,7 +111,10 @@ const ThingsFilter = ({
|
|||||||
<FormattedMessage id="common.cancel" defaultMessage="Cancel" />
|
<FormattedMessage id="common.cancel" defaultMessage="Cancel" />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ProCard split={screens.md ? 'vertical' : 'horizontal'}>
|
<ProCard
|
||||||
|
split={screens.md ? 'vertical' : 'horizontal'}
|
||||||
|
extra={extra ? extra : null}
|
||||||
|
>
|
||||||
<ProCard colSpan={{ xs: 24, sm: 8, md: 8, lg: 6, xl: 6 }}>
|
<ProCard colSpan={{ xs: 24, sm: 8, md: 8, lg: 6, xl: 6 }}>
|
||||||
<TreeGroup
|
<TreeGroup
|
||||||
disable={isLoading}
|
disable={isLoading}
|
||||||
@@ -128,6 +138,15 @@ const ThingsFilter = ({
|
|||||||
alwaysShowAlert: true,
|
alwaysShowAlert: true,
|
||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
onChange: (keys) => setSelectedRowKeys(keys),
|
onChange: (keys) => setSelectedRowKeys(keys),
|
||||||
|
getCheckboxProps: (record) => ({
|
||||||
|
disabled:
|
||||||
|
disabled && thingIds && record.id
|
||||||
|
? (Array.isArray(thingIds)
|
||||||
|
? thingIds
|
||||||
|
: [thingIds]
|
||||||
|
).includes(record.id)
|
||||||
|
: false,
|
||||||
|
}),
|
||||||
}}
|
}}
|
||||||
pagination={{
|
pagination={{
|
||||||
size: 'small',
|
size: 'small',
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ export const API_ALARMS_CONFIRM = '/api/alarms/confirm';
|
|||||||
|
|
||||||
// Thing API Constants
|
// Thing API Constants
|
||||||
export const API_THINGS_SEARCH = '/api/things/search';
|
export const API_THINGS_SEARCH = '/api/things/search';
|
||||||
export const API_THINGS_POLICY = '/api/things/policy';
|
export const API_THING_POLICY = '/api/things/policy2';
|
||||||
|
export const API_SHARE_THING = '/api/things';
|
||||||
|
|
||||||
// Group API Constants
|
// Group API Constants
|
||||||
export const API_GROUPS = '/api/groups';
|
export const API_GROUPS = '/api/groups';
|
||||||
|
|||||||
@@ -3,4 +3,33 @@ export default {
|
|||||||
'master.thing.external_id': 'External ID',
|
'master.thing.external_id': 'External ID',
|
||||||
'master.thing.group': 'Group',
|
'master.thing.group': 'Group',
|
||||||
'master.thing.address': 'Address',
|
'master.thing.address': 'Address',
|
||||||
|
|
||||||
|
// Device translations
|
||||||
|
'master.devices.title': 'Devices',
|
||||||
|
'master.devices.name': 'Name',
|
||||||
|
'master.devices.name.tip': 'The device name',
|
||||||
|
'master.devices.external_id': 'External ID',
|
||||||
|
'master.devices.external_id.tip': 'The external identifier',
|
||||||
|
'master.devices.type': 'Type',
|
||||||
|
'master.devices.type.tip': 'The device type',
|
||||||
|
'master.devices.online': 'Online',
|
||||||
|
'master.devices.offline': 'Offline',
|
||||||
|
'master.devices.table.pagination': 'devices',
|
||||||
|
'master.devices.register': 'Add Device',
|
||||||
|
'master.devices.register.title': 'Add new device',
|
||||||
|
'master.devices.create.success': 'Device created successfully',
|
||||||
|
'master.devices.create.error': 'Device creation failed',
|
||||||
|
'master.devices.groups': 'Groups',
|
||||||
|
'master.devices.groups.required': 'Please select groups',
|
||||||
|
// Edit device modal
|
||||||
|
'master.devices.update.title': 'Update device',
|
||||||
|
'master.devices.ok': 'OK',
|
||||||
|
'master.devices.cancel': 'Cancel',
|
||||||
|
'master.devices.name.placeholder': 'Enter device name',
|
||||||
|
'master.devices.name.required': 'Please enter device name',
|
||||||
|
'master.devices.external_id.placeholder': 'Enter external ID',
|
||||||
|
'master.devices.external_id.required': 'Please enter external ID',
|
||||||
|
'master.devices.address': 'Address',
|
||||||
|
'master.devices.address.placeholder': 'Enter address',
|
||||||
|
'master.devices.address.required': 'Please enter address',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,7 +48,22 @@ export default {
|
|||||||
'master.users.unassign.fail': 'Unassign failed',
|
'master.users.unassign.fail': 'Unassign failed',
|
||||||
'master.users.assign.success': 'Assign group successful',
|
'master.users.assign.success': 'Assign group successful',
|
||||||
'master.users.assign.fail': 'Assign group failed',
|
'master.users.assign.fail': 'Assign group failed',
|
||||||
'master.users.deletion.title': 'Are you sure to delete this selected items?',
|
'master.users.delete.title': 'Are you sure to delete this selected items?',
|
||||||
'master.users.delete.success': 'User deleted successfully',
|
'master.users.delete.success': 'User deleted successfully',
|
||||||
'master.users.delete.fail': 'User deletion failed',
|
'master.users.delete.fail': 'User deletion failed',
|
||||||
|
'master.users.things.list': 'List of devices',
|
||||||
|
'master.users.things.relations.text': 'Relations',
|
||||||
|
'master.users.things.relation.write': 'Control',
|
||||||
|
'master.users.things.relation.read': 'View',
|
||||||
|
'master.users.things.relation.delete': 'Config',
|
||||||
|
'master.users.thing.unshare.confirm':
|
||||||
|
'Are you sure you want to stop sharing these devices?',
|
||||||
|
'master.users.thing.unshare.title': 'Stop Sharing',
|
||||||
|
'master.users.things.unsharing': 'Unsharing devices...',
|
||||||
|
'master.users.thing.unshare.success': 'Stop sharing successful',
|
||||||
|
'master.users.thing.unshare.fail': 'Stop sharing failed',
|
||||||
|
'master.users.thing.share.title': 'Share things',
|
||||||
|
'master.users.things.sharing': 'Sharing devices...',
|
||||||
|
'master.users.thing.share.success': 'Device sharing successful',
|
||||||
|
'master.users.thing.share.fail': 'Device sharing failed',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default {
|
|||||||
'Không thể tạo đơn vị con khi gốc đã có thiết bị',
|
'Không thể tạo đơn vị con khi gốc đã có thiết bị',
|
||||||
'master.groups.add': 'Tạo đơn vị cấp dưới',
|
'master.groups.add': 'Tạo đơn vị cấp dưới',
|
||||||
'master.groups.delete.confirm': 'Bạn có chắc muốn xóa nhóm này không?',
|
'master.groups.delete.confirm': 'Bạn có chắc muốn xóa nhóm này không?',
|
||||||
'master.groups.code': 'Mã đỡ vị',
|
'master.groups.code': 'Mã đơn vị',
|
||||||
'master.groups.code.exists': 'Mã đã tồn tại',
|
'master.groups.code.exists': 'Mã đã tồn tại',
|
||||||
'master.groups.short_name': 'Tên viết tắt',
|
'master.groups.short_name': 'Tên viết tắt',
|
||||||
'master.groups.short_name.exists': 'Tên viết tắt đã tồn tại',
|
'master.groups.short_name.exists': 'Tên viết tắt đã tồn tại',
|
||||||
|
|||||||
@@ -3,4 +3,32 @@ export default {
|
|||||||
'master.thing.external_id': 'External ID',
|
'master.thing.external_id': 'External ID',
|
||||||
'master.thing.group': 'Nhóm',
|
'master.thing.group': 'Nhóm',
|
||||||
'master.thing.address': 'Địa chỉ',
|
'master.thing.address': 'Địa chỉ',
|
||||||
|
// Device translations
|
||||||
|
'master.devices.title': 'Quản lý thiết bị',
|
||||||
|
'master.devices.name': 'Tên',
|
||||||
|
'master.devices.name.tip': 'Tên thiết bị',
|
||||||
|
'master.devices.external_id': 'External ID',
|
||||||
|
'master.devices.external_id.tip': 'Mã định danh bên ngoài',
|
||||||
|
'master.devices.type': 'Loại',
|
||||||
|
'master.devices.type.tip': 'Loại thiết bị',
|
||||||
|
'master.devices.online': 'Trực tuyến',
|
||||||
|
'master.devices.offline': 'Ngoại tuyến',
|
||||||
|
'master.devices.table.pagination': 'thiết bị',
|
||||||
|
'master.devices.register': 'Thêm thiết bị',
|
||||||
|
'master.devices.register.title': 'Thêm thiết bị mới',
|
||||||
|
'master.devices.create.success': 'Tạo thiết bị thành công',
|
||||||
|
'master.devices.create.error': 'Tạo thiết bị lỗi',
|
||||||
|
'master.devices.groups': 'Đơn vị',
|
||||||
|
'master.devices.groups.required': 'Vui lòng chọn đơn vị',
|
||||||
|
// Edit device modal
|
||||||
|
'master.devices.update.title': 'Cập nhật thiết bị',
|
||||||
|
'master.devices.ok': 'Đồng ý',
|
||||||
|
'master.devices.cancel': 'Hủy',
|
||||||
|
'master.devices.name.placeholder': 'Nhập tên thiết bị',
|
||||||
|
'master.devices.name.required': 'Vui lòng nhập tên thiết bị',
|
||||||
|
'master.devices.external_id.placeholder': 'Nhập mã định danh bên ngoài',
|
||||||
|
'master.devices.external_id.required': 'Vui lòng nhập mã định danh bên ngoài',
|
||||||
|
'master.devices.address': 'Địa chỉ',
|
||||||
|
'master.devices.address.placeholder': 'Nhập địa chỉ',
|
||||||
|
'master.devices.address.required': 'Vui lòng nhập địa chỉ',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,7 +47,22 @@ export default {
|
|||||||
'master.users.unassign.fail': 'Ngừng phân quyền thất bại',
|
'master.users.unassign.fail': 'Ngừng phân quyền thất bại',
|
||||||
'master.users.assign.success': 'Phân quyền đơn vị thành công',
|
'master.users.assign.success': 'Phân quyền đơn vị thành công',
|
||||||
'master.users.assign.fail': 'Phân quyền đơn vị thất bại',
|
'master.users.assign.fail': 'Phân quyền đơn vị thất bại',
|
||||||
'master.users.deletion.title': 'Chắc chắn xoá các tài khoản đã chọn?',
|
'master.users.delete.title': 'Chắc chắn xoá các tài khoản đã chọn?',
|
||||||
'master.users.delete.success': 'Xoá người dùng thành công',
|
'master.users.delete.success': 'Xoá người dùng thành công',
|
||||||
'master.users.delete.fail': 'Xoá người dùng thất bại',
|
'master.users.delete.fail': 'Xoá người dùng thất bại',
|
||||||
|
'master.users.things.list': 'Danh sách thiết bị',
|
||||||
|
'master.users.things.relations.text': 'Hành động',
|
||||||
|
'master.users.things.relation.write': 'Điều khiển',
|
||||||
|
'master.users.things.relation.read': 'Giám sát',
|
||||||
|
'master.users.things.relation.delete': 'Quản lí',
|
||||||
|
'master.users.thing.unshare.confirm':
|
||||||
|
'Chắc chắn muốn ngừng chia sẻ các thiết bị này?',
|
||||||
|
'master.users.thing.unshare.title': 'Ngừng chia sẻ',
|
||||||
|
'master.users.thing.unshare.success': 'Ngừng chia sẻ thành công',
|
||||||
|
'master.users.thing.unshare.fail': 'Ngừng chia sẻ thất bại',
|
||||||
|
'master.users.things.unsharing': 'Đang ngừng chia sẻ thiết bị...',
|
||||||
|
'master.users.thing.share.title': 'Chia sẻ thiết bị',
|
||||||
|
'master.users.things.sharing': 'Đang chia sẻ thiết bị...',
|
||||||
|
'master.users.thing.share.success': 'Chia sẻ thiết bị thành công',
|
||||||
|
'master.users.thing.share.fail': 'Chia sẻ thiết bị thất bại',
|
||||||
};
|
};
|
||||||
|
|||||||
210
src/pages/Manager/Device/components/CreateDevice.tsx
Normal file
210
src/pages/Manager/Device/components/CreateDevice.tsx
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
import TreeSelectedGroup from '@/components/shared/TreeSelectedGroup';
|
||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
ModalForm,
|
||||||
|
ProForm,
|
||||||
|
ProFormInstance,
|
||||||
|
ProFormSelect,
|
||||||
|
ProFormText,
|
||||||
|
} from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import { MessageInstance } from 'antd/es/message/interface';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
|
type CreateDeviceProps = {
|
||||||
|
message: MessageInstance;
|
||||||
|
onSuccess?: (isSuccess: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type CreateDeviceFormValues = {
|
||||||
|
name: string;
|
||||||
|
external_id: string;
|
||||||
|
type: string;
|
||||||
|
address?: string;
|
||||||
|
group_id?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CreateDevice = ({ message, onSuccess }: CreateDeviceProps) => {
|
||||||
|
const formRef = useRef<ProFormInstance<CreateDeviceFormValues>>();
|
||||||
|
const intl = useIntl();
|
||||||
|
const [group_id, setGroupId] = useState<string | string[] | null>(null);
|
||||||
|
|
||||||
|
const handleGroupSelect = (group: string | string[] | null) => {
|
||||||
|
setGroupId(group);
|
||||||
|
formRef.current?.setFieldsValue({
|
||||||
|
group_id: Array.isArray(group) ? group.join(',') : group || undefined,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalForm<CreateDeviceFormValues>
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'master.devices.register.title',
|
||||||
|
defaultMessage: 'Register New Device',
|
||||||
|
})}
|
||||||
|
formRef={formRef}
|
||||||
|
trigger={
|
||||||
|
<Button type="primary" key="primary" icon={<PlusOutlined />}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="master.devices.register"
|
||||||
|
defaultMessage="Register"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
autoFocusFirstInput
|
||||||
|
onFinish={async (values: CreateDeviceFormValues) => {
|
||||||
|
// TODO: Implement API call to create device
|
||||||
|
console.log('Create device with values:', values);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Placeholder for API call
|
||||||
|
// const body = {
|
||||||
|
// name: values.name,
|
||||||
|
// metadata: {
|
||||||
|
// external_id: values.external_id,
|
||||||
|
// type: values.type,
|
||||||
|
// address: values.address,
|
||||||
|
// group_id: values.group_id,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// const resp = await apiCreateDevice(body);
|
||||||
|
|
||||||
|
message.success(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'master.devices.create.success',
|
||||||
|
defaultMessage: 'Create device successfully',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
formRef.current?.resetFields();
|
||||||
|
onSuccess?.(true);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
message.error(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'master.devices.create.error',
|
||||||
|
defaultMessage: 'Failed to create device',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
onSuccess?.(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProFormText
|
||||||
|
name={'name'}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.name',
|
||||||
|
defaultMessage: 'Name',
|
||||||
|
})}
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'master.devices.name.placeholder',
|
||||||
|
defaultMessage: 'Enter device name',
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.name.required',
|
||||||
|
defaultMessage: 'The device name is required',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProFormText
|
||||||
|
name={'external_id'}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id',
|
||||||
|
defaultMessage: 'External ID',
|
||||||
|
})}
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id.placeholder',
|
||||||
|
defaultMessage: 'Enter external ID',
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id.required',
|
||||||
|
defaultMessage: 'The external ID is required',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProFormSelect
|
||||||
|
name="type"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.type',
|
||||||
|
defaultMessage: 'Type',
|
||||||
|
})}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'master.devices.type.gms',
|
||||||
|
defaultMessage: 'GMS',
|
||||||
|
}),
|
||||||
|
value: 'gms',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'master.devices.type.sgw',
|
||||||
|
defaultMessage: 'SGW',
|
||||||
|
}),
|
||||||
|
value: 'sgw',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'master.devices.type.spole',
|
||||||
|
defaultMessage: 'SPOLE',
|
||||||
|
}),
|
||||||
|
value: 'spole',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.type.required',
|
||||||
|
defaultMessage: 'Please select a device type',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProFormText
|
||||||
|
name={'address'}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.address',
|
||||||
|
defaultMessage: 'Address',
|
||||||
|
})}
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'master.devices.address.placeholder',
|
||||||
|
defaultMessage: 'Enter device address',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ProForm.Item
|
||||||
|
name="group_id"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.groups',
|
||||||
|
defaultMessage: 'Groups',
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.groups.required',
|
||||||
|
defaultMessage: 'Please select groups!',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<TreeSelectedGroup groupIds={group_id} onSelected={handleGroupSelect} />
|
||||||
|
</ProForm.Item>
|
||||||
|
</ModalForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateDevice;
|
||||||
133
src/pages/Manager/Device/components/EditDeviceModal.tsx
Normal file
133
src/pages/Manager/Device/components/EditDeviceModal.tsx
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Form, Input, Modal } from 'antd';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
device: MasterModel.Thing | null;
|
||||||
|
onCancel: () => void;
|
||||||
|
onSubmit: (values: {
|
||||||
|
name: string;
|
||||||
|
external_id: string;
|
||||||
|
address?: string;
|
||||||
|
}) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditDeviceModal: React.FC<Props> = ({
|
||||||
|
visible,
|
||||||
|
device,
|
||||||
|
onCancel,
|
||||||
|
onSubmit,
|
||||||
|
}) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (device) {
|
||||||
|
form.setFieldsValue({
|
||||||
|
name: device.name,
|
||||||
|
external_id: device?.metadata?.external_id,
|
||||||
|
address: device?.metadata?.address,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
form.resetFields();
|
||||||
|
}
|
||||||
|
}, [device, form]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'master.devices.update.title',
|
||||||
|
defaultMessage: 'Update device',
|
||||||
|
})}
|
||||||
|
open={visible}
|
||||||
|
onCancel={onCancel}
|
||||||
|
onOk={() => form.submit()}
|
||||||
|
okText={intl.formatMessage({
|
||||||
|
id: 'master.devices.ok',
|
||||||
|
defaultMessage: 'OK',
|
||||||
|
})}
|
||||||
|
cancelText={intl.formatMessage({
|
||||||
|
id: 'master.devices.cancel',
|
||||||
|
defaultMessage: 'Cancel',
|
||||||
|
})}
|
||||||
|
destroyOnClose
|
||||||
|
>
|
||||||
|
<Form form={form} layout="vertical" onFinish={onSubmit} preserve={false}>
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.name',
|
||||||
|
defaultMessage: 'Name',
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.name.required',
|
||||||
|
defaultMessage: 'Please enter device name',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'master.devices.name.placeholder',
|
||||||
|
defaultMessage: 'Enter device name',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="external_id"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id',
|
||||||
|
defaultMessage: 'External ID',
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id.required',
|
||||||
|
defaultMessage: 'Please enter external ID',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id.placeholder',
|
||||||
|
defaultMessage: 'Enter external ID',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="address"
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'master.devices.address',
|
||||||
|
defaultMessage: 'Address',
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage({
|
||||||
|
id: 'master.devices.address.required',
|
||||||
|
defaultMessage: 'Please enter address',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'master.devices.address.placeholder',
|
||||||
|
defaultMessage: 'Enter address',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditDeviceModal;
|
||||||
@@ -1,5 +1,319 @@
|
|||||||
|
import IconFont from '@/components/IconFont';
|
||||||
|
import TreeGroup from '@/components/shared/TreeGroup';
|
||||||
|
import { DEFAULT_PAGE_SIZE } from '@/constants';
|
||||||
|
import { apiSearchThings } from '@/services/master/ThingController';
|
||||||
|
import { EditOutlined, EnvironmentOutlined } from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
ActionType,
|
||||||
|
ProCard,
|
||||||
|
ProColumns,
|
||||||
|
ProTable,
|
||||||
|
} from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import { Button, Divider, Grid, Space, Tag, theme } from 'antd';
|
||||||
|
import message from 'antd/es/message';
|
||||||
|
import Paragraph from 'antd/lib/typography/Paragraph';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
import CreateDevice from './components/CreateDevice';
|
||||||
|
import EditDeviceModal from './components/EditDeviceModal';
|
||||||
|
|
||||||
const ManagerDevicePage = () => {
|
const ManagerDevicePage = () => {
|
||||||
return <div>ManagerDevicePage</div>;
|
const { useBreakpoint } = Grid;
|
||||||
|
const intl = useIntl();
|
||||||
|
const screens = useBreakpoint();
|
||||||
|
const { token } = theme.useToken();
|
||||||
|
const actionRef = useRef<ActionType | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
|
const [selectedRowsState, setSelectedRowsState] = useState<
|
||||||
|
MasterModel.Thing[]
|
||||||
|
>([]);
|
||||||
|
const [groupCheckedKeys, setGroupCheckedKeys] = useState<
|
||||||
|
string | string[] | null
|
||||||
|
>(null);
|
||||||
|
const [isEditModalVisible, setIsEditModalVisible] = useState<boolean>(false);
|
||||||
|
const [editingDevice, setEditingDevice] = useState<MasterModel.Thing | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleClickAssign = (device: MasterModel.Thing) => {
|
||||||
|
console.log('Device ', device);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (device: MasterModel.Thing) => {
|
||||||
|
setEditingDevice(device);
|
||||||
|
setIsEditModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditCancel = () => {
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
setEditingDevice(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditSubmit = async (values: any) => {
|
||||||
|
// TODO: call update API here if available. For now just simulate success.
|
||||||
|
console.log('Update values for', editingDevice?.id, values);
|
||||||
|
messageApi.success('Cập nhật thành công');
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
setEditingDevice(null);
|
||||||
|
actionRef.current?.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: ProColumns<MasterModel.Thing>[] = [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
title: (
|
||||||
|
<FormattedMessage id="master.devices.name" defaultMessage="Name" />
|
||||||
|
),
|
||||||
|
tip: intl.formatMessage({
|
||||||
|
id: 'master.devices.name.tip',
|
||||||
|
defaultMessage: 'The device name',
|
||||||
|
}),
|
||||||
|
dataIndex: 'name',
|
||||||
|
render: (_, record) => (
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
display: 'inline-block',
|
||||||
|
color: token.colorText,
|
||||||
|
}}
|
||||||
|
copyable
|
||||||
|
>
|
||||||
|
{record?.name}
|
||||||
|
</Paragraph>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'external_id',
|
||||||
|
title: (
|
||||||
|
<FormattedMessage
|
||||||
|
id="master.devices.external_id"
|
||||||
|
defaultMessage="External ID"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
tip: intl.formatMessage({
|
||||||
|
id: 'master.devices.external_id.tip',
|
||||||
|
defaultMessage: 'The external identifier',
|
||||||
|
}),
|
||||||
|
responsive: ['lg', 'md'],
|
||||||
|
dataIndex: ['metadata', 'external_id'],
|
||||||
|
render: (_, record) =>
|
||||||
|
record?.metadata?.external_id ? (
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
display: 'inline-block',
|
||||||
|
color: token.colorText,
|
||||||
|
}}
|
||||||
|
copyable
|
||||||
|
>
|
||||||
|
{record?.metadata?.external_id}
|
||||||
|
</Paragraph>
|
||||||
|
) : (
|
||||||
|
'-'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'type',
|
||||||
|
hideInSearch: true,
|
||||||
|
title: (
|
||||||
|
<FormattedMessage id="master.devices.type" defaultMessage="Type" />
|
||||||
|
),
|
||||||
|
tip: intl.formatMessage({
|
||||||
|
id: 'master.devices.type.tip',
|
||||||
|
defaultMessage: 'The device type',
|
||||||
|
}),
|
||||||
|
dataIndex: ['metadata', 'type'],
|
||||||
|
render: (_, record) => record?.metadata?.type || '...',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'connected',
|
||||||
|
hideInSearch: true,
|
||||||
|
title: <FormattedMessage id="common.status" defaultMessage="Status" />,
|
||||||
|
dataIndex: ['metadata', 'connected'],
|
||||||
|
render: (_, record) => (
|
||||||
|
<Tag color={record?.metadata?.connected ? 'green' : 'red'}>
|
||||||
|
{record?.metadata?.connected
|
||||||
|
? intl.formatMessage({
|
||||||
|
id: 'master.devices.online',
|
||||||
|
defaultMessage: 'Online',
|
||||||
|
})
|
||||||
|
: intl.formatMessage({
|
||||||
|
id: 'master.devices.offline',
|
||||||
|
defaultMessage: 'Offline',
|
||||||
|
})}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: (
|
||||||
|
<FormattedMessage id="common.actions" defaultMessage="Operating" />
|
||||||
|
),
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_, device) => {
|
||||||
|
return (
|
||||||
|
<Space
|
||||||
|
size={5}
|
||||||
|
split={<Divider type="vertical" style={{ margin: '0 4px' }} />}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
shape="default"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => handleEdit(device)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
shape="default"
|
||||||
|
size="small"
|
||||||
|
icon={<EnvironmentOutlined />}
|
||||||
|
// onClick={() => handleClickAssign(device)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
shape="default"
|
||||||
|
size="small"
|
||||||
|
icon={<IconFont type="icon-camera" />}
|
||||||
|
// onClick={() => handleClickAssign(device)}
|
||||||
|
/>
|
||||||
|
{device?.metadata?.type === 'gmsv6' && (
|
||||||
|
<Button
|
||||||
|
shape="default"
|
||||||
|
size="small"
|
||||||
|
icon={<IconFont type="icon-terminal" />}
|
||||||
|
// onClick={() => handleClickAssign(device)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EditDeviceModal
|
||||||
|
visible={isEditModalVisible}
|
||||||
|
device={editingDevice}
|
||||||
|
onCancel={handleEditCancel}
|
||||||
|
onSubmit={handleEditSubmit}
|
||||||
|
/>
|
||||||
|
{contextHolder}
|
||||||
|
<ProCard split={screens.md ? 'vertical' : 'horizontal'}>
|
||||||
|
<ProCard colSpan={{ xs: 24, sm: 24, md: 6, lg: 6, xl: 6 }}>
|
||||||
|
<TreeGroup
|
||||||
|
disable={isLoading}
|
||||||
|
multiple={true}
|
||||||
|
groupIds={groupCheckedKeys}
|
||||||
|
onSelected={(value: string | string[] | null) => {
|
||||||
|
setGroupCheckedKeys(value);
|
||||||
|
if (actionRef.current) {
|
||||||
|
actionRef.current.reload();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ProCard>
|
||||||
|
<ProCard colSpan={{ xs: 24, sm: 24, md: 18, lg: 18, xl: 18 }}>
|
||||||
|
<ProTable<MasterModel.Thing>
|
||||||
|
columns={columns}
|
||||||
|
tableLayout="auto"
|
||||||
|
actionRef={actionRef}
|
||||||
|
rowKey="id"
|
||||||
|
search={{
|
||||||
|
layout: 'vertical',
|
||||||
|
defaultCollapsed: false,
|
||||||
|
}}
|
||||||
|
dateFormatter="string"
|
||||||
|
rowSelection={{
|
||||||
|
selectedRowKeys: selectedRowsState.map((row) => row.id!),
|
||||||
|
onChange: (_: React.Key[], selectedRows: MasterModel.Thing[]) => {
|
||||||
|
setSelectedRowsState(selectedRows);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
pagination={{
|
||||||
|
defaultPageSize: DEFAULT_PAGE_SIZE * 2,
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '15', '20'],
|
||||||
|
showTotal: (total, range) =>
|
||||||
|
`${range[0]}-${range[1]}
|
||||||
|
${intl.formatMessage({
|
||||||
|
id: 'common.paginations.of',
|
||||||
|
defaultMessage: 'of',
|
||||||
|
})}
|
||||||
|
${total} ${intl.formatMessage({
|
||||||
|
id: 'master.devices.table.pagination',
|
||||||
|
defaultMessage: 'devices',
|
||||||
|
})}`,
|
||||||
|
}}
|
||||||
|
request={async (params = {}) => {
|
||||||
|
const { current = 1, pageSize, name, external_id } = params;
|
||||||
|
const size = pageSize || DEFAULT_PAGE_SIZE * 2;
|
||||||
|
const offset = current === 1 ? 0 : (current - 1) * size;
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const metadata: Partial<MasterModel.ThingMetadata> = {};
|
||||||
|
if (external_id) metadata.external_id = external_id;
|
||||||
|
|
||||||
|
// Add group filter if groups are selected
|
||||||
|
if (groupCheckedKeys && groupCheckedKeys.length > 0) {
|
||||||
|
const groupId = Array.isArray(groupCheckedKeys)
|
||||||
|
? groupCheckedKeys.join(',')
|
||||||
|
: groupCheckedKeys;
|
||||||
|
metadata.group_id = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query: MasterModel.SearchThingPaginationBody = {
|
||||||
|
offset: offset,
|
||||||
|
limit: size,
|
||||||
|
order: 'name',
|
||||||
|
dir: 'asc',
|
||||||
|
};
|
||||||
|
if (name) query.name = name;
|
||||||
|
if (Object.keys(metadata).length > 0) query.metadata = metadata;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await apiSearchThings(query);
|
||||||
|
setIsLoading(false);
|
||||||
|
return {
|
||||||
|
data: response.things || [],
|
||||||
|
success: true,
|
||||||
|
total: response.total || 0,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
setIsLoading(false);
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
success: false,
|
||||||
|
total: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
options={{
|
||||||
|
search: false,
|
||||||
|
setting: false,
|
||||||
|
density: false,
|
||||||
|
reload: true,
|
||||||
|
}}
|
||||||
|
toolBarRender={() => [
|
||||||
|
<CreateDevice
|
||||||
|
message={messageApi}
|
||||||
|
onSuccess={(isSuccess) => {
|
||||||
|
if (isSuccess) {
|
||||||
|
actionRef.current?.reload();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
key="create-device"
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</ProCard>
|
||||||
|
</ProCard>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ManagerDevicePage;
|
export default ManagerDevicePage;
|
||||||
|
|||||||
303
src/pages/Manager/Log/components/LogActions.tsx
Normal file
303
src/pages/Manager/Log/components/LogActions.tsx
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
const LogActions = (intl: any) => {
|
||||||
|
return [
|
||||||
|
//Alarm
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.alarm.confirm',
|
||||||
|
defaultMessage: 'Alarm confirm',
|
||||||
|
}),
|
||||||
|
value: '0-0',
|
||||||
|
selectable: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'things.alarm_confirm',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.confirm',
|
||||||
|
defaultMessage: 'Confirm',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'things.alarm_unconfirm',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.unconfirm',
|
||||||
|
defaultMessage: 'Unconfirm',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
//Things
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things',
|
||||||
|
defaultMessage: 'Things',
|
||||||
|
}),
|
||||||
|
value: '0-1',
|
||||||
|
selectable: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'things.create',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.create',
|
||||||
|
defaultMessage: 'Create new thing',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'things.update',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.update',
|
||||||
|
defaultMessage: 'Update thing',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'things.remove',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.remove',
|
||||||
|
defaultMessage: 'Remove thing',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'things.share',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.share',
|
||||||
|
defaultMessage: 'Share thing',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'things.unshare',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.unshare',
|
||||||
|
defaultMessage: 'Unshare thing',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'things.update_key',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.things.update_key',
|
||||||
|
defaultMessage: 'Update key thing',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Users
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.users',
|
||||||
|
defaultMessage: 'Users',
|
||||||
|
}),
|
||||||
|
value: '0-2',
|
||||||
|
selectable: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'users.create',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.users.create',
|
||||||
|
defaultMessage: 'Register user',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'users.update',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.users.update',
|
||||||
|
defaultMessage: 'Update user',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'users.remove',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.users.remove',
|
||||||
|
defaultMessage: 'Remove user',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'users.login',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.users.login',
|
||||||
|
defaultMessage: 'User login',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Groups
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups',
|
||||||
|
defaultMessage: 'Groups',
|
||||||
|
}),
|
||||||
|
value: '0-3',
|
||||||
|
selectable: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'group.create',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.create',
|
||||||
|
defaultMessage: 'Create new group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'group.update',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.update',
|
||||||
|
defaultMessage: 'Update group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'group.remove',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.remove',
|
||||||
|
defaultMessage: 'Remove group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'group.assign_thing',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.assign_thing',
|
||||||
|
defaultMessage: 'Assign thing to group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'group.assign_user',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.assign_user',
|
||||||
|
defaultMessage: 'Assign user to group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'group.unassign_thing',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.unassign_thing',
|
||||||
|
defaultMessage: 'Remove thing from group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'group.unassign_user',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.groups.unassign_user',
|
||||||
|
defaultMessage: 'Remove user from group',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Ships
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships',
|
||||||
|
defaultMessage: 'Ships',
|
||||||
|
}),
|
||||||
|
value: '0-4',
|
||||||
|
selectable: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'ships.create',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.create',
|
||||||
|
defaultMessage: 'Create new ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'ships.update',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.update',
|
||||||
|
defaultMessage: 'Update ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'ships.remove',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.remove',
|
||||||
|
defaultMessage: 'Remove ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'ships.assign_thing',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.assign_thing',
|
||||||
|
defaultMessage: 'Assign thing to ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'ships.assign_user',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.assign_user',
|
||||||
|
defaultMessage: 'Assign user to ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'ships.unassign_thing',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.unassign_thing',
|
||||||
|
defaultMessage: 'Remove thing from ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'ships.unassign_user',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.ships.unassign_user',
|
||||||
|
defaultMessage: 'Remove user from ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Trips
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips',
|
||||||
|
defaultMessage: 'Trips',
|
||||||
|
}),
|
||||||
|
value: '0-5',
|
||||||
|
selectable: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'trips.create',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.create',
|
||||||
|
defaultMessage: 'Create new ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'trips.update',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.update',
|
||||||
|
defaultMessage: 'Update ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'trips.remove',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.remove',
|
||||||
|
defaultMessage: 'Remove ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'trips.approve',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.approve',
|
||||||
|
defaultMessage: 'Approve trip',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'trips.request_approve',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.request_approve',
|
||||||
|
defaultMessage: 'Request approval for trip',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'trips.unassign_thing',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.unassign_thing',
|
||||||
|
defaultMessage: 'Remove thing from ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'trips.unassign_user',
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'master.logs.trips.unassign_user',
|
||||||
|
defaultMessage: 'Remove user from ship',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LogActions;
|
||||||
@@ -3,312 +3,16 @@ import { apiQueryLogs } from '@/services/master/LogController';
|
|||||||
import { apiQueryUsers } from '@/services/master/UserController';
|
import { apiQueryUsers } from '@/services/master/UserController';
|
||||||
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { theme } from 'antd';
|
||||||
import { DatePicker } from 'antd/lib';
|
import { DatePicker } from 'antd/lib';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
import LogActions from './components/LogActions';
|
||||||
|
|
||||||
const SystemLogs = () => {
|
const SystemLogs = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const tableRef = useRef<ActionType>();
|
const tableRef = useRef<ActionType>();
|
||||||
const actions = [
|
const { token } = theme.useToken();
|
||||||
//Alarm
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.alarm.confirm',
|
|
||||||
defaultMessage: 'Alarm confirm',
|
|
||||||
}),
|
|
||||||
value: '0-0',
|
|
||||||
selectable: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'things.alarm_confirm',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.confirm',
|
|
||||||
defaultMessage: 'Confirm',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'things.alarm_unconfirm',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.unconfirm',
|
|
||||||
defaultMessage: 'Unconfirm',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
//Things
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things',
|
|
||||||
defaultMessage: 'Things',
|
|
||||||
}),
|
|
||||||
value: '0-1',
|
|
||||||
selectable: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'things.create',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.create',
|
|
||||||
defaultMessage: 'Create new thing',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'things.update',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.update',
|
|
||||||
defaultMessage: 'Update thing',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'things.remove',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.remove',
|
|
||||||
defaultMessage: 'Remove thing',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'things.share',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.share',
|
|
||||||
defaultMessage: 'Share thing',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'things.unshare',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.unshare',
|
|
||||||
defaultMessage: 'Unshare thing',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'things.update_key',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.things.update_key',
|
|
||||||
defaultMessage: 'Update key thing',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Users
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.users',
|
|
||||||
defaultMessage: 'Users',
|
|
||||||
}),
|
|
||||||
value: '0-2',
|
|
||||||
selectable: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'users.create',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.users.create',
|
|
||||||
defaultMessage: 'Register user',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'users.update',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.users.update',
|
|
||||||
defaultMessage: 'Update user',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'users.remove',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.users.remove',
|
|
||||||
defaultMessage: 'Remove user',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'users.login',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.users.login',
|
|
||||||
defaultMessage: 'User login',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Groups
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups',
|
|
||||||
defaultMessage: 'Groups',
|
|
||||||
}),
|
|
||||||
value: '0-3',
|
|
||||||
selectable: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'group.create',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.create',
|
|
||||||
defaultMessage: 'Create new group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'group.update',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.update',
|
|
||||||
defaultMessage: 'Update group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'group.remove',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.remove',
|
|
||||||
defaultMessage: 'Remove group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'group.assign_thing',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.assign_thing',
|
|
||||||
defaultMessage: 'Assign thing to group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'group.assign_user',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.assign_user',
|
|
||||||
defaultMessage: 'Assign user to group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'group.unassign_thing',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.unassign_thing',
|
|
||||||
defaultMessage: 'Remove thing from group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'group.unassign_user',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.groups.unassign_user',
|
|
||||||
defaultMessage: 'Remove user from group',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Ships
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships',
|
|
||||||
defaultMessage: 'Ships',
|
|
||||||
}),
|
|
||||||
value: '0-4',
|
|
||||||
selectable: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'ships.create',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.create',
|
|
||||||
defaultMessage: 'Create new ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'ships.update',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.update',
|
|
||||||
defaultMessage: 'Update ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'ships.remove',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.remove',
|
|
||||||
defaultMessage: 'Remove ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'ships.assign_thing',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.assign_thing',
|
|
||||||
defaultMessage: 'Assign thing to ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'ships.assign_user',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.assign_user',
|
|
||||||
defaultMessage: 'Assign user to ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'ships.unassign_thing',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.unassign_thing',
|
|
||||||
defaultMessage: 'Remove thing from ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'ships.unassign_user',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.ships.unassign_user',
|
|
||||||
defaultMessage: 'Remove user from ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Trips
|
|
||||||
{
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips',
|
|
||||||
defaultMessage: 'Trips',
|
|
||||||
}),
|
|
||||||
value: '0-5',
|
|
||||||
selectable: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'trips.create',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.create',
|
|
||||||
defaultMessage: 'Create new ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'trips.update',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.update',
|
|
||||||
defaultMessage: 'Update ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'trips.remove',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.remove',
|
|
||||||
defaultMessage: 'Remove ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'trips.approve',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.approve',
|
|
||||||
defaultMessage: 'Approve trip',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'trips.request_approve',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.request_approve',
|
|
||||||
defaultMessage: 'Request approval for trip',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'trips.unassign_thing',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.unassign_thing',
|
|
||||||
defaultMessage: 'Remove thing from ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'trips.unassign_user',
|
|
||||||
title: intl.formatMessage({
|
|
||||||
id: 'master.logs.trips.unassign_user',
|
|
||||||
defaultMessage: 'Remove user from ship',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const queryUserSource = async (): Promise<MasterModel.ProfileResponse[]> => {
|
const queryUserSource = async (): Promise<MasterModel.ProfileResponse[]> => {
|
||||||
try {
|
try {
|
||||||
@@ -345,6 +49,10 @@ const SystemLogs = () => {
|
|||||||
return (
|
return (
|
||||||
<DatePicker.RangePicker
|
<DatePicker.RangePicker
|
||||||
width="50%"
|
width="50%"
|
||||||
|
style={{
|
||||||
|
backgroundColor: token.colorBgContainer,
|
||||||
|
color: token.colorText,
|
||||||
|
}}
|
||||||
presets={[
|
presets={[
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({
|
label: intl.formatMessage({
|
||||||
@@ -404,9 +112,9 @@ const SystemLogs = () => {
|
|||||||
treeCheckable: true,
|
treeCheckable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
},
|
},
|
||||||
request: async () => actions,
|
request: async () => LogActions(intl),
|
||||||
render: (_, item) => {
|
render: (_, item) => {
|
||||||
const childs = actions.flatMap((a) => a.children || []);
|
const childs = LogActions(intl).flatMap((a) => a.children || []);
|
||||||
const action = childs.find((a) => a?.value === item.subtopic);
|
const action = childs.find((a) => a?.value === item.subtopic);
|
||||||
return action?.title ?? '...';
|
return action?.title ?? '...';
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,35 @@
|
|||||||
import { ActionType, ProList } from '@ant-design/pro-components';
|
import ThingsFilter from '@/components/shared/ThingFilterModal';
|
||||||
import { useIntl } from '@umijs/max';
|
import { DEFAULT_PAGE_SIZE } from '@/constants';
|
||||||
import { message } from 'antd';
|
import {
|
||||||
import { useRef } from 'react';
|
apiDeleteUserThingPolicy,
|
||||||
|
apiGetThingPolicyByUser,
|
||||||
|
apiShareThingToUser,
|
||||||
|
} from '@/services/master/ThingController';
|
||||||
|
import { DeleteOutlined, ShareAltOutlined } from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
ActionType,
|
||||||
|
FooterToolbar,
|
||||||
|
ProList,
|
||||||
|
ProListMetas,
|
||||||
|
} from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
GetProp,
|
||||||
|
message,
|
||||||
|
Popconfirm,
|
||||||
|
Tag,
|
||||||
|
Typography,
|
||||||
|
} from 'antd';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
const { Paragraph } = Typography;
|
||||||
|
|
||||||
|
type PolicyShareDefault = {
|
||||||
|
read: boolean;
|
||||||
|
write: boolean;
|
||||||
|
delete: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
type ShareThingProps = {
|
type ShareThingProps = {
|
||||||
user: MasterModel.ProfileResponse | null;
|
user: MasterModel.ProfileResponse | null;
|
||||||
@@ -9,56 +37,287 @@ type ShareThingProps = {
|
|||||||
const ShareThing = ({ user }: ShareThingProps) => {
|
const ShareThing = ({ user }: ShareThingProps) => {
|
||||||
const listActionRef = useRef<ActionType>();
|
const listActionRef = useRef<ActionType>();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [messageAPI, contextHolder] = message.useMessage();
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
|
const [selectedRowsState, setSelectedRows] = useState<
|
||||||
|
MasterModel.ThingPolicy[]
|
||||||
|
>([]);
|
||||||
|
const [thingPolicy, setThingPolicy] = useState<MasterModel.ThingPolicy[]>([]);
|
||||||
|
const [shareThingModalVisible, setShareThingModalVisible] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
const [policyShare, setPolicyShare] = useState<PolicyShareDefault>({
|
||||||
|
read: true,
|
||||||
|
write: true,
|
||||||
|
delete: true,
|
||||||
|
});
|
||||||
|
const getPolicyInfo = (
|
||||||
|
policy: MasterModel.Policy,
|
||||||
|
): { color: string; text: string } => {
|
||||||
|
switch (policy) {
|
||||||
|
case 'read':
|
||||||
|
return {
|
||||||
|
color: 'blue',
|
||||||
|
text: intl.formatMessage({
|
||||||
|
id: 'master.users.things.relation.read',
|
||||||
|
defaultMessage: 'Read',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
case 'write':
|
||||||
|
return {
|
||||||
|
color: 'gold',
|
||||||
|
text: intl.formatMessage({
|
||||||
|
id: 'master.users.things.relation.write',
|
||||||
|
defaultMessage: 'Write',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
case 'delete':
|
||||||
|
return {
|
||||||
|
color: 'red',
|
||||||
|
text: intl.formatMessage({
|
||||||
|
id: 'master.users.things.relation.delete',
|
||||||
|
defaultMessage: 'Delete',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return { color: 'default', text: policy };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: ProListMetas<MasterModel.ThingPolicy> = {
|
||||||
|
title: {
|
||||||
|
dataIndex: 'name',
|
||||||
|
render: (_, record: MasterModel.ThingPolicy) => (
|
||||||
|
<Paragraph copyable>{record?.thing_name}</Paragraph>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
subTitle: {
|
||||||
|
dataIndex: 'metadata.external_id',
|
||||||
|
render: (_, record: MasterModel.ThingPolicy) => (
|
||||||
|
<Paragraph copyable>{record?.external_id}</Paragraph>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
dataIndex: 'policies',
|
||||||
|
render: (_, record: MasterModel.ThingPolicy) => {
|
||||||
|
return record?.policies?.map((policy) => {
|
||||||
|
const info = getPolicyInfo(policy);
|
||||||
|
return (
|
||||||
|
<Tag key={policy} color={info.color}>
|
||||||
|
{info.text}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleShareThings = async (thingIds: string[]) => {
|
||||||
|
const thingsFiltered = thingIds.filter((thingId) => {
|
||||||
|
return !thingPolicy.find((thing) => thing.thing_id === thingId);
|
||||||
|
});
|
||||||
|
if (thingsFiltered.length === 0) return;
|
||||||
|
const key = 'share';
|
||||||
|
try {
|
||||||
|
messageApi.open({
|
||||||
|
type: 'loading',
|
||||||
|
content: intl.formatMessage({
|
||||||
|
id: 'master.users.things.sharing',
|
||||||
|
defaultMessage: 'Sharing devices...',
|
||||||
|
}),
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
const allShare = thingsFiltered.map(async (thingId) => {
|
||||||
|
const resp = await apiShareThingToUser(
|
||||||
|
thingId,
|
||||||
|
user?.id || '',
|
||||||
|
Object.keys(policyShare).filter(
|
||||||
|
(key) => policyShare[key as keyof PolicyShareDefault],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(allShare);
|
||||||
|
|
||||||
|
messageApi.open({
|
||||||
|
type: 'success',
|
||||||
|
content: intl.formatMessage({
|
||||||
|
id: 'master.users.thing.share.success',
|
||||||
|
defaultMessage: 'Share successfully and will refresh soon',
|
||||||
|
}),
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (listActionRef.current) {
|
||||||
|
listActionRef.current.reload();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error when share thing: ', error);
|
||||||
|
messageApi.open({
|
||||||
|
type: 'error',
|
||||||
|
content: intl.formatMessage({
|
||||||
|
id: 'master.users.thing.share.fail',
|
||||||
|
defaultMessage: 'Share failed, please try again!',
|
||||||
|
}),
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange: GetProp<typeof Checkbox.Group, 'onChange'> = (
|
||||||
|
checkedValues,
|
||||||
|
) => {
|
||||||
|
setPolicyShare({
|
||||||
|
read: checkedValues.includes('read'),
|
||||||
|
write: checkedValues.includes('write'),
|
||||||
|
delete: checkedValues.includes('delete'),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleUnshare = async (selectedRows: MasterModel.ThingPolicy[]) => {
|
||||||
|
if (!selectedRows) return true;
|
||||||
|
const key = 'unshare';
|
||||||
|
try {
|
||||||
|
messageApi.open({
|
||||||
|
type: 'loading',
|
||||||
|
content: intl.formatMessage({
|
||||||
|
id: 'master.users.things.unsharing',
|
||||||
|
defaultMessage: 'Unsharing devices...',
|
||||||
|
}),
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
|
||||||
|
const allUnshare = selectedRows.map(async (row) => {
|
||||||
|
const resp = await apiDeleteUserThingPolicy(
|
||||||
|
row?.thing_id || '',
|
||||||
|
user?.id || '',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(allUnshare);
|
||||||
|
|
||||||
|
messageApi.open({
|
||||||
|
type: 'success',
|
||||||
|
content: intl.formatMessage({
|
||||||
|
id: 'master.users.thing.unshare.success',
|
||||||
|
defaultMessage: 'Unshare successfully and will refresh soon',
|
||||||
|
}),
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error when unshare thing: ', error);
|
||||||
|
messageApi.open({
|
||||||
|
type: 'error',
|
||||||
|
content: intl.formatMessage({
|
||||||
|
id: 'master.users.thing.unshare.fail',
|
||||||
|
defaultMessage: 'Unshare failed, please try again!',
|
||||||
|
}),
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
<ProList
|
<ThingsFilter
|
||||||
|
isOpen={shareThingModalVisible}
|
||||||
|
setIsOpen={setShareThingModalVisible}
|
||||||
|
thingIds={thingPolicy.map((thing) => thing.thing_id!)}
|
||||||
|
disabled
|
||||||
|
extra={
|
||||||
|
<Checkbox.Group
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'master.users.things.relation.read',
|
||||||
|
defaultMessage: 'Read',
|
||||||
|
}),
|
||||||
|
value: 'read',
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'master.users.things.relation.write',
|
||||||
|
defaultMessage: 'Write',
|
||||||
|
}),
|
||||||
|
value: 'write',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'master.users.things.relation.delete',
|
||||||
|
defaultMessage: 'Delete',
|
||||||
|
}),
|
||||||
|
value: 'delete',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
value={Object.keys(policyShare).filter(
|
||||||
|
(key) => policyShare[key as keyof PolicyShareDefault],
|
||||||
|
)}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onSubmit={handleShareThings}
|
||||||
|
/>
|
||||||
|
<ProList<MasterModel.ThingPolicy>
|
||||||
headerTitle={intl.formatMessage({
|
headerTitle={intl.formatMessage({
|
||||||
id: 'pages.users.things.list',
|
id: 'master.users.things.list',
|
||||||
defaultMessage: 'List things',
|
defaultMessage: 'List things',
|
||||||
})}
|
})}
|
||||||
actionRef={listActionRef}
|
actionRef={listActionRef}
|
||||||
toolBarRender={() => [
|
toolBarRender={() => [
|
||||||
// <Button
|
<Button
|
||||||
// type="primary"
|
type="primary"
|
||||||
// key="primary"
|
key="primary"
|
||||||
// onClick={() => {
|
icon={<ShareAltOutlined />}
|
||||||
// handleShareModalVisible(true);
|
onClick={() => {
|
||||||
// }}
|
setShareThingModalVisible(true);
|
||||||
// >
|
}}
|
||||||
// <PlusOutlined />{" "}
|
>
|
||||||
// <FormattedMessage
|
<FormattedMessage
|
||||||
// id="pages.things.share.text"
|
id="master.users.thing.share.title"
|
||||||
// defaultMessage="Share"
|
defaultMessage="Share"
|
||||||
// />
|
/>
|
||||||
// </Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
|
pagination={{
|
||||||
|
pageSize: DEFAULT_PAGE_SIZE,
|
||||||
|
}}
|
||||||
metas={columns}
|
metas={columns}
|
||||||
request={async () => {
|
request={async (params) => {
|
||||||
|
const { current, pageSize } = params;
|
||||||
const query = {
|
const query = {
|
||||||
type: 'sub',
|
type: 'sub',
|
||||||
id: user?.id || '',
|
id: user?.id || '',
|
||||||
};
|
};
|
||||||
if (user?.id) {
|
if (user?.id) {
|
||||||
const resp = (await apiQueryThingsByPolicy(
|
const offset = current === 1 ? 0 : (current! - 1) * pageSize!;
|
||||||
query,
|
const policyBody: Partial<MasterModel.SearchPaginationBody> = {
|
||||||
)) as PolicyResponse;
|
offset: offset,
|
||||||
const { relations } = resp;
|
limit: pageSize,
|
||||||
if (relations) {
|
|
||||||
const queries = relations.map(async (rel: PolicyRelation) => {
|
|
||||||
const thg = await apiQueryThing(rel.id);
|
|
||||||
return {
|
|
||||||
...thg,
|
|
||||||
relations: rel?.actions,
|
|
||||||
};
|
};
|
||||||
});
|
const resp = await apiGetThingPolicyByUser(policyBody, user.id);
|
||||||
const policies = await Promise.all(queries);
|
|
||||||
|
if (resp.things) {
|
||||||
|
setThingPolicy(resp.things);
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
success: true,
|
success: true,
|
||||||
data: policies,
|
data: resp.things,
|
||||||
total: policies.length,
|
total: resp.total,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
data: [],
|
||||||
|
total: 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
@@ -67,32 +326,67 @@ const ShareThing = ({ user }: ShareThingProps) => {
|
|||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
rowKey="id"
|
rowKey="external_id"
|
||||||
search={false}
|
search={false}
|
||||||
// rowSelection={{
|
rowSelection={{
|
||||||
// selectedRowKeys: selectedRowsState.map((row) => row.id).filter((id): id is string => id !== undefined),
|
selectedRowKeys: selectedRowsState
|
||||||
// onChange: (_: React.Key[], selectedRows: API.Thing[]) => {
|
.map((row) => row.external_id)
|
||||||
// setSelectedRows(selectedRows);
|
.filter((id): id is string => id !== undefined),
|
||||||
// },
|
onChange: (_, selectedRows: MasterModel.ThingPolicy[]) => {
|
||||||
// }}
|
setSelectedRows(selectedRows);
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{/* <FormShareVms
|
{selectedRowsState?.length > 0 && (
|
||||||
visible={shareModalVisibale}
|
<FooterToolbar
|
||||||
onVisibleChange={handleShareModalVisible}
|
extra={
|
||||||
user={user}
|
<div>
|
||||||
onSubmit={async (values: ShareFormValues) => {
|
<FormattedMessage
|
||||||
console.log(values);
|
id="master.footer.chosen"
|
||||||
const success = await handleShare(values);
|
defaultMessage="Chosen"
|
||||||
|
/>{' '}
|
||||||
|
<a
|
||||||
|
style={{
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedRowsState.length}
|
||||||
|
</a>{' '}
|
||||||
|
<FormattedMessage
|
||||||
|
id="common.paginations.things"
|
||||||
|
defaultMessage="item"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Popconfirm
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'master.users.thing.unshare.confirm',
|
||||||
|
defaultMessage: 'Are you sure to stop sharing these devices?',
|
||||||
|
})}
|
||||||
|
okText={intl.formatMessage({
|
||||||
|
id: 'common.sure',
|
||||||
|
defaultMessage: 'Sure',
|
||||||
|
})}
|
||||||
|
onConfirm={async () => {
|
||||||
|
const success = await handleUnshare(selectedRowsState);
|
||||||
if (success) {
|
if (success) {
|
||||||
handleShareModalVisible(false);
|
setSelectedRows([]);
|
||||||
onReload();
|
if (listActionRef.current) {
|
||||||
if (actionRef.current) {
|
listActionRef.current.reload();
|
||||||
//await delay(1000);
|
|
||||||
actionRef.current.reload();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/> */}
|
>
|
||||||
|
<Button type="primary" danger icon={<DeleteOutlined />}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="master.users.thing.unshare.title"
|
||||||
|
defaultMessage="Sure"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</FooterToolbar>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ const ManagerUserPage = () => {
|
|||||||
>
|
>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'master.users.deletion.title',
|
id: 'master.users.delete.title',
|
||||||
defaultMessage: 'Are you sure to delete this selected items',
|
defaultMessage: 'Are you sure to delete this selected items',
|
||||||
})}
|
})}
|
||||||
okText={intl.formatMessage({
|
okText={intl.formatMessage({
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { API_THINGS_SEARCH } from '@/constants/api';
|
import {
|
||||||
|
API_SHARE_THING,
|
||||||
|
API_THING_POLICY,
|
||||||
|
API_THINGS_SEARCH,
|
||||||
|
} from '@/constants/api';
|
||||||
import { request } from '@umijs/max';
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
export async function apiSearchThings(
|
export async function apiSearchThings(
|
||||||
@@ -28,3 +32,43 @@ export async function apiSearchThings(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function apiGetThingPolicyByUser(
|
||||||
|
params: Partial<MasterModel.SearchPaginationBody>,
|
||||||
|
userId: string,
|
||||||
|
) {
|
||||||
|
return request<MasterModel.ThingPolicyResponse>(
|
||||||
|
`${API_THING_POLICY}/${userId}`,
|
||||||
|
{
|
||||||
|
params: params,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiDeleteUserThingPolicy(
|
||||||
|
thing_id: string,
|
||||||
|
user_id: string,
|
||||||
|
) {
|
||||||
|
return request(`${API_SHARE_THING}/${thing_id}/share`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
data: {
|
||||||
|
policies: ['read', 'write', 'delete'],
|
||||||
|
user_ids: [user_id],
|
||||||
|
},
|
||||||
|
getResponse: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export async function apiShareThingToUser(
|
||||||
|
thing_id: string,
|
||||||
|
user_id: string,
|
||||||
|
policies: string[],
|
||||||
|
) {
|
||||||
|
return request(`${API_SHARE_THING}/${thing_id}/share`, {
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
policies: policies,
|
||||||
|
user_ids: [user_id],
|
||||||
|
},
|
||||||
|
getResponse: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
27
src/services/master/typings.d.ts
vendored
27
src/services/master/typings.d.ts
vendored
@@ -160,21 +160,24 @@ declare namespace MasterModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Thing Policy
|
// Thing Policy
|
||||||
|
interface ThingPolicyResponse {
|
||||||
|
total?: number;
|
||||||
|
offset?: number;
|
||||||
|
limit?: number;
|
||||||
|
order?: string;
|
||||||
|
direction?: string;
|
||||||
|
metadata?: null;
|
||||||
|
things?: ThingPolicy[];
|
||||||
|
}
|
||||||
|
|
||||||
interface ThingPolicy {
|
interface ThingPolicy {
|
||||||
next_page_token?: string;
|
policies?: Policy[];
|
||||||
relations?: Relation[];
|
thing_id?: string;
|
||||||
|
thing_name?: string;
|
||||||
|
external_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Relation {
|
type Policy = 'read' | 'delete' | 'write';
|
||||||
id?: string;
|
|
||||||
actions?: Action[];
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Action {
|
|
||||||
Delete = 'delete',
|
|
||||||
Read = 'read',
|
|
||||||
Write = 'write',
|
|
||||||
}
|
|
||||||
|
|
||||||
// Group
|
// Group
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user