mirror of
https://github.com/netbirdio/dashboard.git
synced 2026-09-23 00:30:43 -07:00
Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c88bfa6476 | ||
|
|
c4138a8c45 | ||
|
|
3f5418bebc | ||
|
|
f60605e5e3 | ||
|
|
c1b2ededa7 | ||
|
|
31eaa4a241 | ||
|
|
ba365336ff | ||
|
|
06c238b013 | ||
|
|
ed56c240f3 | ||
|
|
1f3c7d87d7 | ||
|
|
9de2906fb2 | ||
|
|
359b443326 | ||
|
|
ecae39d94b | ||
|
|
30b858c1bc | ||
|
|
e82b269ff5 | ||
|
|
23a4b79f01 | ||
|
|
cc5a9b1033 |
No files matched your search
@@ -22,6 +22,10 @@ if [[ -z "${AUTH_AUDIENCE}" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${AUTH_AUDIENCE}" == "none" ]]; then
|
||||
unset AUTH_AUDIENCE
|
||||
fi
|
||||
|
||||
if [[ -z "${AUTH_SUPPORTED_SCOPES}" ]]; then
|
||||
if [[ -z "${AUTH0_DOMAIN}" ]]; then
|
||||
echo "AUTH_SUPPORTED_SCOPES environment variable must be set"
|
||||
|
||||
Generated
+84
-84
@@ -204,9 +204,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -237,9 +237,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/eslint-parser/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -311,9 +311,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -370,9 +370,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -1706,9 +1706,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -1918,9 +1918,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -5219,9 +5219,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -7467,9 +7467,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -7540,9 +7540,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -9512,9 +9512,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-lib-instrument/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -10800,9 +10800,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir/node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
@@ -14712,9 +14712,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
@@ -15831,9 +15831,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
|
||||
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
|
||||
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
|
||||
"dependencies": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
@@ -16710,9 +16710,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
|
||||
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -17249,9 +17249,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -17271,9 +17271,9 @@
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -17328,9 +17328,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -17371,9 +17371,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18237,9 +18237,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18394,9 +18394,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -20854,9 +20854,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -22543,9 +22543,9 @@
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -22589,9 +22589,9 @@
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -23955,9 +23955,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -24942,9 +24942,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -27566,9 +27566,9 @@
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
@@ -28430,9 +28430,9 @@
|
||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
|
||||
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
|
||||
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
|
||||
"requires": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
@@ -29069,9 +29069,9 @@
|
||||
}
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
|
||||
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA=="
|
||||
},
|
||||
"workbox-background-sync": {
|
||||
"version": "6.5.4",
|
||||
|
||||
@@ -50,7 +50,7 @@ interface FormPolicy {
|
||||
}
|
||||
|
||||
const AccessControlEdit = () => {
|
||||
const { optionRender, blueTagRender, grayTagRender } =
|
||||
const { optionRender, blueTagRender, tagGroups, grayTagRender } =
|
||||
useGetGroupTagHelpers();
|
||||
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
@@ -81,7 +81,7 @@ const AccessControlEdit = () => {
|
||||
biDirectional: false,
|
||||
reverseDirectional: false,
|
||||
});
|
||||
const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
// const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
const [formPolicy, setFormPolicy] = useState({} as FormPolicy);
|
||||
const [form] = Form.useForm();
|
||||
const inputNameRef = useRef<any>(null);
|
||||
@@ -99,9 +99,9 @@ const AccessControlEdit = () => {
|
||||
useEffect(() => {
|
||||
if (editDescription) inputDescriptionRef.current!.focus({ cursor: "end" });
|
||||
}, [editDescription]);
|
||||
useEffect(() => {
|
||||
setTagGroups(groups?.map((g) => g.name) || []);
|
||||
}, [groups]);
|
||||
// useEffect(() => {
|
||||
// setTagGroups(groups?.map((g) => g.name) || []);
|
||||
// }, [groups]);
|
||||
useEffect(() => {
|
||||
if (!policy) return;
|
||||
const fPolicy = {
|
||||
@@ -115,10 +115,10 @@ const AccessControlEdit = () => {
|
||||
ports: policy.rules[0].ports,
|
||||
action: policy.rules[0].action,
|
||||
tagSourceGroups: policy.rules[0].sources
|
||||
? policy.rules[0].sources?.map((t) => t.name)
|
||||
? policy.rules[0].sources?.map((t) => t.id || "")
|
||||
: [],
|
||||
tagDestinationGroups: policy.rules[0].destinations
|
||||
? policy.rules[0].destinations?.map((t) => t.name)
|
||||
? policy.rules[0].destinations?.map((t) => t.id || "")
|
||||
: [],
|
||||
} as FormPolicy;
|
||||
setFormPolicy(fPolicy);
|
||||
@@ -139,17 +139,21 @@ const AccessControlEdit = () => {
|
||||
const createPolicyToSave = (): PolicyToSave => {
|
||||
const sources =
|
||||
groups
|
||||
?.filter((g) => formPolicy.tagSourceGroups.includes(g.name))
|
||||
?.filter((g) => formPolicy.tagSourceGroups.includes(g.id || ""))
|
||||
.map((g) => g.id || "") || [];
|
||||
|
||||
const destinations =
|
||||
groups
|
||||
?.filter((g) => formPolicy.tagDestinationGroups.includes(g.name))
|
||||
?.filter((g) => formPolicy.tagDestinationGroups.includes(g.id || ""))
|
||||
.map((g) => g.id || "") || [];
|
||||
|
||||
const existingGroupsNames: any[] = groups?.map((g) => g.id);
|
||||
const sourcesNoId = formPolicy.tagSourceGroups.filter(
|
||||
(s) => !tagGroups.includes(s)
|
||||
(s) => !existingGroupsNames.includes(s)
|
||||
);
|
||||
|
||||
const destinationsNoId = formPolicy.tagDestinationGroups.filter(
|
||||
(s) => !tagGroups.includes(s)
|
||||
(s) => !existingGroupsNames.includes(s)
|
||||
);
|
||||
const groupsToSave = uniq([...sourcesNoId, ...destinationsNoId]);
|
||||
return {
|
||||
@@ -457,11 +461,7 @@ const AccessControlEdit = () => {
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card
|
||||
bordered={true}
|
||||
// title={setupKey.name}
|
||||
style={{ marginBottom: "7px" }}
|
||||
>
|
||||
<Card bordered={true} style={{ marginBottom: "7px" }}>
|
||||
<div style={{ maxWidth: "550px" }}>
|
||||
<Form
|
||||
layout="vertical"
|
||||
@@ -508,7 +508,6 @@ const AccessControlEdit = () => {
|
||||
<Form.Item
|
||||
name="name"
|
||||
label=""
|
||||
style={{ margin: "0" }}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
@@ -532,7 +531,7 @@ const AccessControlEdit = () => {
|
||||
{!editDescription ? (
|
||||
<div
|
||||
style={{
|
||||
margin: "12px 0 30px",
|
||||
margin: "0 0 39px",
|
||||
lineHeight: "22px",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
@@ -551,7 +550,7 @@ const AccessControlEdit = () => {
|
||||
<Form.Item
|
||||
name="description"
|
||||
label="Description"
|
||||
style={{ marginTop: 24, fontWeight: "500" }}
|
||||
style={{ marginTop: 10, fontWeight: "500" }}
|
||||
>
|
||||
<Input
|
||||
placeholder="Add description..."
|
||||
@@ -568,7 +567,7 @@ const AccessControlEdit = () => {
|
||||
</Row>
|
||||
</Header>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<Form.Item name="enabled" label="">
|
||||
<div
|
||||
style={{
|
||||
@@ -579,6 +578,7 @@ const AccessControlEdit = () => {
|
||||
<Switch
|
||||
onChange={handleChangeDisabled}
|
||||
defaultChecked={policy.enabled}
|
||||
size="small"
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
@@ -622,9 +622,16 @@ const AccessControlEdit = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeSource}
|
||||
dropdownRender={dropDownRenderGroups}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option
|
||||
key={index}
|
||||
value={m.id}
|
||||
serchValue={m.name}
|
||||
>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
@@ -775,16 +782,23 @@ const AccessControlEdit = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeDestination}
|
||||
dropdownRender={dropDownRenderGroups}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option
|
||||
key={index}
|
||||
value={m.id}
|
||||
serchValue={m.name}
|
||||
>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{ marginTop: "-15px", marginBottom: "30px" }}
|
||||
@@ -793,7 +807,7 @@ const AccessControlEdit = () => {
|
||||
protocol below
|
||||
</Paragraph>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<Row>
|
||||
<Col span={10}>
|
||||
<Form.Item
|
||||
@@ -830,7 +844,14 @@ const AccessControlEdit = () => {
|
||||
maxWidth: "260px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
placeholder={<div color={"rgba(0,0,0,0.25)"} className="arimo-font">Select ports</div>}
|
||||
placeholder={
|
||||
<div
|
||||
color={"rgba(0,0,0,0.25)"}
|
||||
className="arimo-font"
|
||||
>
|
||||
Select ports
|
||||
</div>
|
||||
}
|
||||
className="menlo-font"
|
||||
value={formPolicyCopy}
|
||||
disabled={true}
|
||||
@@ -862,7 +883,14 @@ const AccessControlEdit = () => {
|
||||
maxWidth: "260px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
placeholder={<div color={"rgba(0,0,0,0.25)"} className="arimo-font">Select ports</div>}
|
||||
placeholder={
|
||||
<div
|
||||
color={"rgba(0,0,0,0.25)"}
|
||||
className="arimo-font"
|
||||
>
|
||||
Select ports
|
||||
</div>
|
||||
}
|
||||
tagRender={grayTagRender}
|
||||
onChange={handleChangePorts}
|
||||
className="menlo-font"
|
||||
@@ -890,7 +918,7 @@ const AccessControlEdit = () => {
|
||||
justifyContent: "start",
|
||||
padding: 0,
|
||||
gap: "10px",
|
||||
marginTop: "30px",
|
||||
marginTop: "12px",
|
||||
}}
|
||||
key={0}
|
||||
>
|
||||
|
||||
@@ -50,8 +50,12 @@ interface FormPolicy {
|
||||
}
|
||||
|
||||
const AccessControlNew = () => {
|
||||
const { optionRender, grayTagRender, blueTagRender } =
|
||||
useGetGroupTagHelpers();
|
||||
const {
|
||||
optionRender,
|
||||
blueTagRender,
|
||||
tagGroups,
|
||||
grayTagRender,
|
||||
} = useGetGroupTagHelpers();
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const dispatch = useDispatch();
|
||||
const setupNewPolicyVisible = useSelector(
|
||||
@@ -81,7 +85,7 @@ const AccessControlNew = () => {
|
||||
biDirectional: true,
|
||||
reverseDirectional: true,
|
||||
});
|
||||
const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
// const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
const [formPolicy, setFormPolicy] = useState({} as FormPolicy);
|
||||
const [form] = Form.useForm();
|
||||
const inputNameRef = useRef<any>(null);
|
||||
@@ -93,9 +97,9 @@ const AccessControlNew = () => {
|
||||
useEffect(() => {
|
||||
if (editDescription) inputDescriptionRef.current!.focus({ cursor: "end" });
|
||||
}, [editDescription]);
|
||||
useEffect(() => {
|
||||
setTagGroups(groups?.map((g) => g.name) || []);
|
||||
}, [groups]);
|
||||
// useEffect(() => {
|
||||
// setTagGroups(groups?.map((g) => g.name) || []);
|
||||
// }, [groups]);
|
||||
useEffect(() => {
|
||||
if (!policy) return;
|
||||
const fPolicy = {
|
||||
@@ -122,19 +126,26 @@ const AccessControlNew = () => {
|
||||
const createPolicyToSave = (): PolicyToSave => {
|
||||
const sources =
|
||||
groups
|
||||
?.filter((g) => formPolicy.tagSourceGroups.includes(g.name))
|
||||
?.filter((g) => formPolicy.tagSourceGroups.includes(g.id || ""))
|
||||
.map((g) => g.id || "") || [];
|
||||
|
||||
const destinations =
|
||||
groups
|
||||
?.filter((g) => formPolicy.tagDestinationGroups.includes(g.name))
|
||||
?.filter((g) => formPolicy.tagDestinationGroups.includes(g.id || ""))
|
||||
.map((g) => g.id || "") || [];
|
||||
|
||||
|
||||
const existingGroupsNames: any[] = groups?.map((g) => g.id);
|
||||
const sourcesNoId = formPolicy.tagSourceGroups.filter(
|
||||
(s) => !tagGroups.includes(s)
|
||||
(s) => !existingGroupsNames.includes(s)
|
||||
);
|
||||
|
||||
const destinationsNoId = formPolicy.tagDestinationGroups.filter(
|
||||
(s) => !tagGroups.includes(s)
|
||||
(s) => !existingGroupsNames.includes(s)
|
||||
);
|
||||
|
||||
const groupsToSave = uniq([...sourcesNoId, ...destinationsNoId]);
|
||||
|
||||
return {
|
||||
id: formPolicy.id,
|
||||
name: formPolicy.name,
|
||||
@@ -456,18 +467,20 @@ const AccessControlNew = () => {
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
fontSize: "18px",
|
||||
margin: "0px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Create Rule
|
||||
Create rule
|
||||
</Paragraph>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
paddingBottom: "15px",
|
||||
marginTop: "-20px",
|
||||
fontSize: "14px",
|
||||
paddingBottom: "25px",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Use this rule to restrict access to groups of resources
|
||||
@@ -560,9 +573,12 @@ const AccessControlNew = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeSource}
|
||||
dropdownRender={dropDownRenderGroups}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
@@ -713,9 +729,12 @@ const AccessControlNew = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeDestination}
|
||||
dropdownRender={dropDownRenderGroups}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
@@ -767,6 +786,8 @@ const AccessControlNew = () => {
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
padding: "0 0 2px",
|
||||
display: "inline-block",
|
||||
}}
|
||||
>
|
||||
Ports
|
||||
@@ -828,9 +849,16 @@ const AccessControlNew = () => {
|
||||
className="menlo-font"
|
||||
placeholder={
|
||||
formPolicy.protocol === "all" ||
|
||||
formPolicy.protocol === "icmp"
|
||||
? "All"
|
||||
: (<div color={"rgba(0,0,0,0.25)"} className="arimo-font">Select ports</div>)
|
||||
formPolicy.protocol === "icmp" ? (
|
||||
"All"
|
||||
) : (
|
||||
<div
|
||||
color={"rgba(0,0,0,0.25)"}
|
||||
className="arimo-font"
|
||||
>
|
||||
Select ports
|
||||
</div>
|
||||
)
|
||||
}
|
||||
tagRender={grayTagRender}
|
||||
onChange={handleChangePorts}
|
||||
@@ -859,6 +887,7 @@ const AccessControlNew = () => {
|
||||
}}
|
||||
>
|
||||
<Switch
|
||||
size="small"
|
||||
onChange={handleChangeDisabled}
|
||||
defaultChecked={true}
|
||||
/>
|
||||
@@ -890,7 +919,7 @@ const AccessControlNew = () => {
|
||||
</Col>
|
||||
<Col
|
||||
span={24}
|
||||
style={{ marginTop: "20px", marginBottom: "25px" }}
|
||||
style={{ marginTop: "10px", marginBottom: "24px" }}
|
||||
>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
@@ -900,7 +929,7 @@ const AccessControlNew = () => {
|
||||
href="https://docs.netbird.io/how-to/manage-network-access"
|
||||
>
|
||||
{" "}
|
||||
Access Controls
|
||||
access controls
|
||||
</a>
|
||||
</Text>
|
||||
</Col>
|
||||
|
||||
@@ -331,121 +331,117 @@ const NameServerGroupAdd = () => {
|
||||
{ add, remove }: any,
|
||||
{ errors }: any
|
||||
) => (
|
||||
<Col>
|
||||
<div style={{ width: "100%", maxWidth: "360px" }}>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
marginBottom: "10px",
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
Nameservers
|
||||
</label>
|
||||
<div style={{ width: "100%", maxWidth: "360px" }}>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
marginBottom: "10px",
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
Nameservers
|
||||
</label>
|
||||
|
||||
{!!fields.length && (
|
||||
<Row align="middle">
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Typography.Text
|
||||
style={{ color: "#818183", paddingLeft: "5px" }}
|
||||
></Typography.Text>
|
||||
</Col>
|
||||
<Col span={10} style={{ textAlign: "left" }}>
|
||||
<Typography.Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Nameserver IP
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Typography.Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Port
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
<Col span={4} />
|
||||
</Row>
|
||||
)}
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
<Row key={index}>
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "3px" }}
|
||||
name={[field.name, "ns_type"]}
|
||||
rules={[
|
||||
{ required: true, message: "Missing first protocol" },
|
||||
]}
|
||||
initialValue={"udp"}
|
||||
>
|
||||
<Select
|
||||
disabled
|
||||
style={{ width: "100%" }}
|
||||
className="style-like-text"
|
||||
>
|
||||
<Option value="udp">UDP</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={10} style={{ margin: "1px" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "ip"]}
|
||||
rules={[{ validator: ipValidator }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="e.g. X.X.X.X"
|
||||
style={{ width: "100%" }}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "center" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "port"]}
|
||||
rules={[{ required: true, message: "Missing port" }]}
|
||||
initialValue={53}
|
||||
>
|
||||
<InputNumber placeholder="Port" style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col
|
||||
span={2}
|
||||
style={{
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MinusCircleOutlined onClick={() => remove(field.name)} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add()}
|
||||
block
|
||||
style={{
|
||||
maxWidth: "270px",
|
||||
marginTop: "5px",
|
||||
}}
|
||||
disabled={fields.length > 1}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
Add Nameserver
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</Form.Item>
|
||||
{!!fields.length && (
|
||||
<Row align="middle">
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Typography.Text
|
||||
style={{ color: "#818183", paddingLeft: "5px" }}
|
||||
></Typography.Text>
|
||||
</Col>
|
||||
<Col span={10} style={{ textAlign: "left" }}>
|
||||
<Typography.Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Nameserver IP
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Typography.Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Port
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
<Col span={4} />
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
)}
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
<Row key={index}>
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "3px" }}
|
||||
name={[field.name, "ns_type"]}
|
||||
rules={[{ required: true, message: "Missing first protocol" }]}
|
||||
initialValue={"udp"}
|
||||
>
|
||||
<Select
|
||||
disabled
|
||||
style={{ width: "100%" }}
|
||||
className="style-like-text"
|
||||
>
|
||||
<Option value="udp">UDP</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={10} style={{ margin: "1px" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "ip"]}
|
||||
rules={[{ validator: ipValidator }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="e.g. X.X.X.X"
|
||||
style={{ width: "100%" }}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "center" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "port"]}
|
||||
rules={[{ required: true, message: "Missing port" }]}
|
||||
initialValue={53}
|
||||
>
|
||||
<InputNumber placeholder="Port" style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col
|
||||
span={2}
|
||||
style={{
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MinusCircleOutlined onClick={() => remove(field.name)} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add()}
|
||||
block
|
||||
style={{
|
||||
maxWidth: "270px",
|
||||
marginTop: "5px",
|
||||
}}
|
||||
disabled={fields.length > 1}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
Add nameserver
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
@@ -470,9 +466,9 @@ const NameServerGroupAdd = () => {
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
marginTop: "-4px",
|
||||
fontWeight: "400",
|
||||
marginBottom: "0",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Add domain if you want to have a specific one
|
||||
@@ -556,18 +552,20 @@ const NameServerGroupAdd = () => {
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
fontSize: "18px",
|
||||
margin: "0px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Add Nameserver
|
||||
Add nameserver
|
||||
</Paragraph>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
paddingBottom: "0",
|
||||
marginTop: "-20px",
|
||||
fontSize: "14px",
|
||||
paddingBottom: "25px",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Use this nameserver to resolve domains in your network
|
||||
@@ -706,7 +704,7 @@ const NameServerGroupAdd = () => {
|
||||
</Row>
|
||||
</Header>
|
||||
</Col>
|
||||
<Col span={24} flex="auto">
|
||||
<Col span={24}>
|
||||
<Form.List
|
||||
name="nameservers"
|
||||
rules={[{ validator: formListValidator }]}
|
||||
@@ -714,7 +712,7 @@ const NameServerGroupAdd = () => {
|
||||
{renderNSList}
|
||||
</Form.List>
|
||||
</Col>
|
||||
<Col span={24} flex="auto">
|
||||
<Col span={24}>
|
||||
<Form.List name="domains">{renderDomains}</Form.List>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
@@ -730,9 +728,9 @@ const NameServerGroupAdd = () => {
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
marginTop: "-4px",
|
||||
fontWeight: "400",
|
||||
marginBottom: "0",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
Advertise this route to peers that belong to the following
|
||||
@@ -749,9 +747,12 @@ const NameServerGroupAdd = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeTags}
|
||||
dropdownRender={dropDownRender}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
@@ -787,8 +788,9 @@ const NameServerGroupAdd = () => {
|
||||
marginBottom: "0",
|
||||
}}
|
||||
>
|
||||
Disable this server if you don't want it to apply
|
||||
immediately
|
||||
{formNSGroup.enabled
|
||||
? "Disable this server if you don't want it to apply immediately"
|
||||
: " Enable this server if you want it to apply immediately"}
|
||||
</Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
@@ -796,7 +798,7 @@ const NameServerGroupAdd = () => {
|
||||
</Col>
|
||||
<Col
|
||||
span={24}
|
||||
style={{ marginTop: "10px", marginBottom: "20px" }}
|
||||
style={{ marginTop: "10px", marginBottom: "24px" }}
|
||||
>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
@@ -830,7 +832,7 @@ const NameServerGroupAdd = () => {
|
||||
onClick={handleFormSubmit}
|
||||
disabled={savedNSGroup.loading}
|
||||
>
|
||||
Create Nameserver
|
||||
Create nameserver
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
@@ -43,7 +43,6 @@ const NameServerGroupUpdate = () => {
|
||||
optionRender,
|
||||
tagGroups,
|
||||
getExistingAndToCreateGroupsLists,
|
||||
getGroupNamesFromIDs,
|
||||
selectValidator,
|
||||
} = useGetGroupTagHelpers();
|
||||
const dispatch = useDispatch();
|
||||
@@ -96,7 +95,7 @@ const NameServerGroupUpdate = () => {
|
||||
|
||||
let newFormGroup = {
|
||||
...nsGroup,
|
||||
groups: getGroupNamesFromIDs(nsGroup.groups),
|
||||
groups: nsGroup.groups,
|
||||
} as formNSGroup;
|
||||
setFormNSGroup(newFormGroup);
|
||||
form.setFieldsValue(newFormGroup);
|
||||
@@ -313,117 +312,161 @@ const NameServerGroupUpdate = () => {
|
||||
{ add, remove }: any,
|
||||
{ errors }: any
|
||||
) => (
|
||||
<Col>
|
||||
<div style={{ width: "100%", maxWidth: "360px" }}>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
marginBottom: "10px",
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
Nameservers
|
||||
</label>
|
||||
<Row>
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<Form.Item name="enabled" label="">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "15px",
|
||||
}}
|
||||
>
|
||||
<Switch
|
||||
onChange={handleChangeDisabled}
|
||||
defaultChecked={formNSGroup.enabled}
|
||||
size="small"
|
||||
checked={formNSGroup.enabled}
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Enabled
|
||||
</label>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
fontWeight: "400",
|
||||
marginBottom: "0",
|
||||
}}
|
||||
>
|
||||
{formNSGroup.enabled
|
||||
? "Disable this server if you don't want the configuration to apply immediately"
|
||||
: " Enable this server if you want the configuration to apply immediately"}
|
||||
</Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col>
|
||||
<div style={{ width: "100%", maxWidth: "360px" }}>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
marginBottom: "10px",
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
Nameservers
|
||||
</label>
|
||||
|
||||
{!!fields.length && (
|
||||
<Row align="middle">
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Text style={{ color: "#818183", paddingLeft: "5px" }}></Text>
|
||||
</Col>
|
||||
<Col span={10} style={{ textAlign: "left" }}>
|
||||
<Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Nameserver IP
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Text style={{ color: "#818183", paddingLeft: "5px" }}>Port</Text>
|
||||
</Col>
|
||||
<Col span={4} />
|
||||
</Row>
|
||||
)}
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
<Row key={index}>
|
||||
{!!fields.length && (
|
||||
<Row align="middle">
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "3px" }}
|
||||
name={[field.name, "ns_type"]}
|
||||
rules={[
|
||||
{ required: true, message: "Missing first protocol" },
|
||||
]}
|
||||
initialValue={"udp"}
|
||||
>
|
||||
<Select
|
||||
disabled
|
||||
style={{ width: "100%" }}
|
||||
className="style-like-text"
|
||||
>
|
||||
<Option value="udp">UDP</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Text style={{ color: "#818183", paddingLeft: "5px" }}></Text>
|
||||
</Col>
|
||||
<Col span={10} style={{ margin: "1px" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "ip"]}
|
||||
rules={[{ validator: ipValidator }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="e.g. X.X.X.X"
|
||||
style={{ width: "100%" }}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Col span={10} style={{ textAlign: "left" }}>
|
||||
<Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Nameserver IP
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "center" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "port"]}
|
||||
rules={[{ required: true, message: "Missing port" }]}
|
||||
initialValue={53}
|
||||
>
|
||||
<InputNumber placeholder="Port" style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col
|
||||
span={2}
|
||||
style={{
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MinusCircleOutlined onClick={() => remove(field.name)} />
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Text style={{ color: "#818183", paddingLeft: "5px" }}>
|
||||
Port
|
||||
</Text>
|
||||
</Col>
|
||||
<Col span={4} />
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
)}
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
<Row key={index}>
|
||||
<Col span={4} style={{ textAlign: "left" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "3px" }}
|
||||
name={[field.name, "ns_type"]}
|
||||
rules={[
|
||||
{ required: true, message: "Missing first protocol" },
|
||||
]}
|
||||
initialValue={"udp"}
|
||||
>
|
||||
<Select
|
||||
disabled
|
||||
style={{ width: "100%" }}
|
||||
className="style-like-text"
|
||||
>
|
||||
<Option value="udp">UDP</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={10} style={{ margin: "1px" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "ip"]}
|
||||
rules={[{ validator: ipValidator }]}
|
||||
>
|
||||
<Input
|
||||
placeholder="e.g. X.X.X.X"
|
||||
style={{ width: "100%" }}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4} style={{ textAlign: "center" }}>
|
||||
<Form.Item
|
||||
style={{ margin: "1px" }}
|
||||
name={[field.name, "port"]}
|
||||
rules={[{ required: true, message: "Missing port" }]}
|
||||
initialValue={53}
|
||||
>
|
||||
<InputNumber placeholder="Port" style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col
|
||||
span={2}
|
||||
style={{
|
||||
textAlign: "center",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MinusCircleOutlined onClick={() => remove(field.name)} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add()}
|
||||
block
|
||||
style={{
|
||||
maxWidth: "270px",
|
||||
marginTop: "5px",
|
||||
}}
|
||||
disabled={fields.length > 1}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
Add Nameserver
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add()}
|
||||
block
|
||||
style={{
|
||||
maxWidth: "270px",
|
||||
marginTop: "5px",
|
||||
}}
|
||||
disabled={fields.length > 1}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
Add Nameserver
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
@@ -448,24 +491,13 @@ const NameServerGroupUpdate = () => {
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
fontWeight: "400",
|
||||
marginBottom: "0",
|
||||
marginBottom: "10px",
|
||||
}}
|
||||
>
|
||||
Add domain if you want to have a specific one
|
||||
</Paragraph>
|
||||
</Col>
|
||||
{/* <Col>
|
||||
<Tooltip
|
||||
title="Only queries to domains specified here will be resolved by these nameservers."
|
||||
className={"ant-form-item-tooltip"}
|
||||
>
|
||||
<QuestionCircleOutlined
|
||||
style={{ color: "rgba(0, 0, 0, 0.45)", cursor: "help" }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Col> */}
|
||||
</Space>
|
||||
</Row>
|
||||
{fields.map((field, index) => {
|
||||
@@ -631,7 +663,7 @@ const NameServerGroupUpdate = () => {
|
||||
className={
|
||||
"access-control input-text ant-drawer-subtitle"
|
||||
}
|
||||
style={{ marginTop: "0" }}
|
||||
style={{ margin: "0 0 39px 0px" }}
|
||||
onClick={() => toggleEditDescription(true)}
|
||||
>
|
||||
{formNSGroup.description &&
|
||||
@@ -641,7 +673,7 @@ const NameServerGroupUpdate = () => {
|
||||
</div>
|
||||
) : (
|
||||
<Row>
|
||||
<Col span={8}>
|
||||
<Col span={8} style={{ marginBottom: "15px" }}>
|
||||
<div
|
||||
style={{ lineHeight: "15px", marginTop: "24px" }}
|
||||
>
|
||||
@@ -676,46 +708,8 @@ const NameServerGroupUpdate = () => {
|
||||
</Row>
|
||||
</Header>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item name="enabled" label="">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "15px",
|
||||
}}
|
||||
>
|
||||
<Switch
|
||||
onChange={handleChangeDisabled}
|
||||
defaultChecked={formNSGroup.enabled}
|
||||
size="small"
|
||||
checked={formNSGroup.enabled}
|
||||
/>
|
||||
<div>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Enabled
|
||||
</label>
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
fontWeight: "400",
|
||||
marginBottom: "0",
|
||||
}}
|
||||
>
|
||||
Disable this server if you don't want it to apply
|
||||
immediately
|
||||
</Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<Form.List
|
||||
name="nameservers"
|
||||
rules={[{ validator: formListValidator }]}
|
||||
@@ -724,15 +718,17 @@ const NameServerGroupUpdate = () => {
|
||||
</Form.List>
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<Form.List name="domains">{renderDomains}</Form.List>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Col span={24} style={{ marginBottom: "15px" }}>
|
||||
<label
|
||||
style={{
|
||||
color: "rgba(0, 0, 0, 0.88)",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
marginBottom: "5px",
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
Distribution groups
|
||||
@@ -749,13 +745,17 @@ const NameServerGroupUpdate = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeTags}
|
||||
dropdownRender={dropDownRender}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
<Col
|
||||
style={{
|
||||
width: "100%",
|
||||
|
||||
+225
-167
@@ -1,185 +1,243 @@
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import {Link, useLocation} from 'react-router-dom';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import logo from "../assets/logo.png";
|
||||
import {Avatar, Button, Col, Dropdown, Grid, Menu, Row} from 'antd'
|
||||
import {ItemType} from "antd/lib/menu/hooks/useItems";
|
||||
import {AvatarSize} from "antd/es/avatar/SizeContext";
|
||||
import {UserOutlined} from '@ant-design/icons';
|
||||
import {useOidc, useOidcIdToken, useOidcUser} from '@axa-fr/react-oidc';
|
||||
import {getConfig} from "../config";
|
||||
import {User} from "../store/user/types";
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
import {RootState} from "typesafe-actions";
|
||||
import {actions as userActions} from "../store/user";
|
||||
import {useGetTokenSilently} from "../utils/token";
|
||||
import {actions as personalAccessTokenActions} from "../store/personal-access-token";
|
||||
import { Avatar, Button, Col, Dropdown, Grid, Menu, Row } from "antd";
|
||||
import { ItemType } from "antd/lib/menu/hooks/useItems";
|
||||
import { AvatarSize } from "antd/es/avatar/SizeContext";
|
||||
import { UserOutlined } from "@ant-design/icons";
|
||||
import { useOidc, useOidcIdToken, useOidcUser } from "@axa-fr/react-oidc";
|
||||
import { getConfig } from "../config";
|
||||
import { User } from "../store/user/types";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { RootState } from "typesafe-actions";
|
||||
import { actions as userActions } from "../store/user";
|
||||
import { useGetTokenSilently } from "../utils/token";
|
||||
import { actions as personalAccessTokenActions } from "../store/personal-access-token";
|
||||
|
||||
const {useBreakpoint} = Grid;
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
const Navbar = () => {
|
||||
let location = useLocation();
|
||||
const config = getConfig();
|
||||
const { logout } = useOidc();
|
||||
const {getTokenSilently} = useGetTokenSilently()
|
||||
const dispatch = useDispatch()
|
||||
let location = useLocation();
|
||||
const config = getConfig();
|
||||
const { logout } = useOidc();
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const {oidcUser} = useOidcUser();
|
||||
const {idTokenPayload} = useOidcIdToken()
|
||||
const user = oidcUser;
|
||||
const [currentUser, setCurrentUser] = useState({} as User)
|
||||
const { oidcUser } = useOidcUser();
|
||||
const { idTokenPayload } = useOidcIdToken();
|
||||
const user = oidcUser;
|
||||
const [currentUser, setCurrentUser] = useState({} as User);
|
||||
|
||||
const screens = useBreakpoint();
|
||||
const screens = useBreakpoint();
|
||||
|
||||
const [hideMenuUser, setHideMenuUser] = useState(false)
|
||||
const users = useSelector((state: RootState) => state.user.data)
|
||||
const [isRefreshingUserState, setIsRefreshingUserState] = useState(false)
|
||||
const [hideMenuUser, setHideMenuUser] = useState(false);
|
||||
const users = useSelector((state: RootState) => state.user.data);
|
||||
const [isRefreshingUserState, setIsRefreshingUserState] = useState(false);
|
||||
|
||||
const items = [
|
||||
{label: (<Link to="/peers">Peers</Link>), key: '/peers'},
|
||||
{label: (<Link to="/setup-keys">Setup Keys</Link>), key: '/setup-keys'},
|
||||
{label: (<Link to="/acls">Access Control</Link>), key: '/acls'},
|
||||
{label: (<Link to="/routes">Network Routes</Link>), key: '/routes'},
|
||||
{ label: (<Link to="/dns">DNS</Link>), key: '/dns' },
|
||||
{label: (<Link to="/users">Users</Link>), key: '/users'},
|
||||
{label: (<Link to="/activity">Activity</Link>), key: '/activity'},
|
||||
{label: (<Link to="/settings">Settings</Link>), key: '/settings'}
|
||||
] as ItemType[]
|
||||
const items = [
|
||||
{ label: <Link to="/peers">Peers</Link>, key: "/peers" },
|
||||
{ label: <Link to="/setup-keys">Setup Keys</Link>, key: "/setup-keys" },
|
||||
{ label: <Link to="/acls">Access Control</Link>, key: "/acls" },
|
||||
{ label: <Link to="/routes">Network Routes</Link>, key: "/routes" },
|
||||
{ label: <Link to="/dns">DNS</Link>, key: "/dns" },
|
||||
{ label: <Link to="/users">Users</Link>, key: "/users" },
|
||||
{ label: <Link to="/activity">Activity</Link>, key: "/activity" },
|
||||
{ label: <Link to="/settings">Settings</Link>, key: "/settings" },
|
||||
] as ItemType[];
|
||||
|
||||
const userEmailKey = 'user-email'
|
||||
const userLogoutKey = 'user-logout'
|
||||
const userDividerKey = 'user-divider'
|
||||
const adminOnlyTabs = ["/setup-keys", "/acls", "/routes", "/dns", "/activity", "/settings"]
|
||||
const [menuItems, setMenuItems] = useState(items)
|
||||
const logoutWithRedirect = () =>
|
||||
logout("/", {client_id: config.clientId});
|
||||
const userEmailKey = "user-email";
|
||||
const userLogoutKey = "user-logout";
|
||||
const userDividerKey = "user-divider";
|
||||
const adminOnlyTabs = [
|
||||
"/setup-keys",
|
||||
"/acls",
|
||||
"/routes",
|
||||
"/dns",
|
||||
"/activity",
|
||||
"/settings",
|
||||
];
|
||||
const [menuItems, setMenuItems] = useState(items);
|
||||
const logoutWithRedirect = () => {
|
||||
let lRemove = [
|
||||
"peerFilter",
|
||||
"setupKeysFilter",
|
||||
"accessControlFilter",
|
||||
"routesFilter",
|
||||
"nameServerFilter",
|
||||
"userFilter",
|
||||
"serviceUserFilter",
|
||||
"activityFilter",
|
||||
];
|
||||
lRemove.forEach((element) => {
|
||||
localStorage.removeItem(element);
|
||||
});
|
||||
logout("/", { client_id: config.clientId });
|
||||
};
|
||||
|
||||
const openPersonalUserPage = () => {
|
||||
dispatch(userActions.setUser({
|
||||
id: currentUser.id,
|
||||
email: currentUser.email,
|
||||
role: currentUser.role,
|
||||
auto_groups: currentUser.auto_groups ? currentUser.auto_groups : [],
|
||||
name: currentUser.name,
|
||||
is_current: currentUser.is_current,
|
||||
is_service_user: currentUser.is_service_user,
|
||||
} as User));
|
||||
dispatch(userActions.setUserTabOpen("Users"));
|
||||
dispatch(userActions.setEditUserPopupVisible(true));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const fs = items.filter(m => showTab(m?.key?.toString(), currentUser) && m?.key !== userEmailKey && m?.key !== userLogoutKey && m?.key !== userDividerKey)
|
||||
if (screens.xs === true) {
|
||||
setHideMenuUser(false)
|
||||
fs.push({type: 'divider', key: userDividerKey})
|
||||
fs.push({
|
||||
label: (
|
||||
<Link to="#">{user?.name}</Link>
|
||||
),
|
||||
icon: createAvatar("small"),
|
||||
key: userEmailKey
|
||||
})
|
||||
fs.push({
|
||||
label: (<Button type="link" block onClick={logoutWithRedirect}>Logout</Button>),
|
||||
key: userLogoutKey
|
||||
})
|
||||
setMenuItems([...fs])
|
||||
return
|
||||
}
|
||||
setMenuItems([...fs])
|
||||
setHideMenuUser(true)
|
||||
}, [screens, currentUser])
|
||||
|
||||
useEffect(() => {
|
||||
if (users.length === 0 && !isRefreshingUserState &&
|
||||
window.location.pathname !== '/peers' &&
|
||||
window.location.pathname !== '/users') {
|
||||
setIsRefreshingUserState(true)
|
||||
dispatch(userActions.getUsers.request({getAccessTokenSilently: getTokenSilently, payload: null}))
|
||||
return
|
||||
}
|
||||
if (users.length === 0 && isRefreshingUserState) {
|
||||
return
|
||||
}
|
||||
let runUser = oidcUser
|
||||
if (!oidcUser) {
|
||||
runUser = idTokenPayload
|
||||
}
|
||||
setIsRefreshingUserState(false)
|
||||
if (runUser) {
|
||||
const found = users.find(u => u.is_current ? u.is_current : runUser.sub ? u.id == runUser.sub : false)
|
||||
if (found) {
|
||||
setCurrentUser(found)
|
||||
}
|
||||
}
|
||||
}, [users, oidcUser])
|
||||
|
||||
const showTab = (key: string | undefined, user: User | undefined) => {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (user.role?.toLowerCase() === "admin") {
|
||||
return true
|
||||
}
|
||||
return !adminOnlyTabs.find(t => t === key)
|
||||
}
|
||||
|
||||
const menuUser = (
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (<Link to="/users" onClick={openPersonalUserPage}>{user?.email}</Link>),
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: (<Link to="/logout" onClick={logoutWithRedirect}>Logout</Link>),
|
||||
key: '1',
|
||||
}
|
||||
]}
|
||||
/>
|
||||
const openPersonalUserPage = () => {
|
||||
dispatch(
|
||||
userActions.setUser({
|
||||
id: currentUser.id,
|
||||
email: currentUser.email,
|
||||
role: currentUser.role,
|
||||
auto_groups: currentUser.auto_groups ? currentUser.auto_groups : [],
|
||||
name: currentUser.name,
|
||||
is_current: currentUser.is_current,
|
||||
is_service_user: currentUser.is_service_user,
|
||||
} as User)
|
||||
);
|
||||
dispatch(userActions.setUserTabOpen("Users"));
|
||||
dispatch(userActions.setEditUserPopupVisible(true));
|
||||
};
|
||||
|
||||
const createAvatar = (size: AvatarSize) => {
|
||||
return user?.picture ? (
|
||||
<Avatar size={size} src={user?.picture} icon={<UserOutlined/>}/>
|
||||
) : (
|
||||
<Avatar size={size}>{(user?.name || '').slice(0, 1).toUpperCase()}</Avatar>
|
||||
)
|
||||
useEffect(() => {
|
||||
const fs = items.filter(
|
||||
(m) =>
|
||||
showTab(m?.key?.toString(), currentUser) &&
|
||||
m?.key !== userEmailKey &&
|
||||
m?.key !== userLogoutKey &&
|
||||
m?.key !== userDividerKey
|
||||
);
|
||||
if (screens.xs === true) {
|
||||
setHideMenuUser(false);
|
||||
fs.push({ type: "divider", key: userDividerKey });
|
||||
fs.push({
|
||||
label: <Link to="#">{user?.name}</Link>,
|
||||
icon: createAvatar("small"),
|
||||
key: userEmailKey,
|
||||
});
|
||||
fs.push({
|
||||
label: (
|
||||
<Button type="link" block onClick={logoutWithRedirect}>
|
||||
Logout
|
||||
</Button>
|
||||
),
|
||||
key: userLogoutKey,
|
||||
});
|
||||
setMenuItems([...fs]);
|
||||
return;
|
||||
}
|
||||
setMenuItems([...fs]);
|
||||
setHideMenuUser(true);
|
||||
}, [screens, currentUser]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
users.length === 0 &&
|
||||
!isRefreshingUserState &&
|
||||
window.location.pathname !== "/peers" &&
|
||||
window.location.pathname !== "/users"
|
||||
) {
|
||||
setIsRefreshingUserState(true);
|
||||
dispatch(
|
||||
userActions.getUsers.request({
|
||||
getAccessTokenSilently: getTokenSilently,
|
||||
payload: null,
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (users.length === 0 && isRefreshingUserState) {
|
||||
return;
|
||||
}
|
||||
let runUser = oidcUser;
|
||||
if (!oidcUser) {
|
||||
runUser = idTokenPayload;
|
||||
}
|
||||
setIsRefreshingUserState(false);
|
||||
if (runUser) {
|
||||
const found = users.find((u) =>
|
||||
u.is_current ? u.is_current : runUser.sub ? u.id == runUser.sub : false
|
||||
);
|
||||
if (found) {
|
||||
setCurrentUser(found);
|
||||
}
|
||||
}
|
||||
}, [users, oidcUser]);
|
||||
|
||||
const showTab = (key: string | undefined, user: User | undefined) => {
|
||||
if (!user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row justify="space-evenly" align="middle">
|
||||
<Col flex="0 1 60px">
|
||||
<Link id="logo" to="/">
|
||||
<img
|
||||
alt="logo"
|
||||
style={{width: "55px"}}
|
||||
src={logo}
|
||||
/>
|
||||
</Link>
|
||||
</Col>
|
||||
<Col flex="1 1 auto">
|
||||
<div>
|
||||
<Menu mode="horizontal" selectable={true} selectedKeys={[location.pathname]}
|
||||
onSelect={(e) => {
|
||||
dispatch(userActions.setUser(null as unknown as User));
|
||||
dispatch(personalAccessTokenActions.resetPersonalAccessTokens(null))
|
||||
}}
|
||||
defaultSelectedKeys={[location.pathname]} items={menuItems}/>
|
||||
</div>
|
||||
</Col>
|
||||
{hideMenuUser &&
|
||||
<Col>
|
||||
<Dropdown overlay={menuUser} placement="bottomRight" trigger={['click']}>
|
||||
{createAvatar("large")}
|
||||
</Dropdown>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
</>
|
||||
if (user.role?.toLowerCase() === "admin") {
|
||||
return true;
|
||||
}
|
||||
return !adminOnlyTabs.find((t) => t === key);
|
||||
};
|
||||
|
||||
const menuUser = (
|
||||
<Menu
|
||||
items={[
|
||||
{
|
||||
label: (
|
||||
<Link to="/users" onClick={openPersonalUserPage}>
|
||||
{user?.email}
|
||||
</Link>
|
||||
),
|
||||
key: "0",
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Link to="/logout" onClick={logoutWithRedirect}>
|
||||
Logout
|
||||
</Link>
|
||||
),
|
||||
key: "1",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
const createAvatar = (size: AvatarSize) => {
|
||||
return user?.picture ? (
|
||||
<Avatar size={size} src={user?.picture} icon={<UserOutlined />} />
|
||||
) : (
|
||||
<Avatar size={size}>
|
||||
{(user?.name || "").slice(0, 1).toUpperCase()}
|
||||
</Avatar>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row justify="space-evenly" align="middle">
|
||||
<Col flex="0 1 60px">
|
||||
<Link id="logo" to="/">
|
||||
<img alt="logo" style={{ width: "55px" }} src={logo} />
|
||||
</Link>
|
||||
</Col>
|
||||
<Col flex="1 1 auto">
|
||||
<div>
|
||||
<Menu
|
||||
mode="horizontal"
|
||||
selectable={true}
|
||||
selectedKeys={[location.pathname]}
|
||||
onSelect={(e) => {
|
||||
dispatch(userActions.setUser(null as unknown as User));
|
||||
dispatch(
|
||||
personalAccessTokenActions.resetPersonalAccessTokens(null)
|
||||
);
|
||||
}}
|
||||
defaultSelectedKeys={[location.pathname]}
|
||||
items={menuItems}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
{hideMenuUser && (
|
||||
<Col>
|
||||
<Dropdown
|
||||
overlay={menuUser}
|
||||
placement="bottomRight"
|
||||
trigger={["click"]}
|
||||
>
|
||||
{createAvatar("large")}
|
||||
</Dropdown>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navbar;
|
||||
@@ -54,7 +54,7 @@ const PeerUpdate = () => {
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const { Column } = Table;
|
||||
const { confirm } = Modal;
|
||||
const { optionRender } = useGetGroupTagHelpers();
|
||||
const { optionRender, tagGroups, blueTagRender } = useGetGroupTagHelpers();
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const groups = useSelector((state: RootState) => state.group.data);
|
||||
@@ -76,7 +76,6 @@ const PeerUpdate = () => {
|
||||
const setupNewRouteVisible = useSelector(
|
||||
(state: RootState) => state.route.setupNewRouteVisible
|
||||
);
|
||||
const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
const [selectedTagGroups, setSelectedTagGroups] = useState([] as string[]);
|
||||
const [peerGroups, setPeerGroups] = useState([] as GroupPeer[]);
|
||||
const inputNameRef = useRef<any>(null);
|
||||
@@ -160,10 +159,10 @@ const PeerUpdate = () => {
|
||||
const gs = peer?.groups?.map(
|
||||
(g) => ({ id: g?.id || "", name: g.name } as GroupPeer)
|
||||
) as GroupPeer[];
|
||||
const gs_name = gs?.map((g) => g.name) as string[];
|
||||
const gs_name = gs?.map((g) => g.id) as string[];
|
||||
setPeerGroups(gs);
|
||||
setSelectedTagGroups(gs_name);
|
||||
const fPeer = {
|
||||
const fPeer = {
|
||||
...peer,
|
||||
name: formPeer.name ? formPeer.name : peer.name,
|
||||
groupsNames: gs_name,
|
||||
@@ -177,9 +176,6 @@ const PeerUpdate = () => {
|
||||
form.setFieldsValue(fPeer);
|
||||
}, [peer]);
|
||||
|
||||
useEffect(() => {
|
||||
setTagGroups(groups?.map((g) => g.name) || []);
|
||||
}, [groups]);
|
||||
|
||||
useEffect(() => {}, [users]);
|
||||
|
||||
@@ -202,18 +198,19 @@ const PeerUpdate = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const groupsToRemove = peerGroups
|
||||
.filter((pg) => !selectedTagGroups.includes(pg.name))
|
||||
.filter((pg) => !selectedTagGroups.includes(pg.id))
|
||||
.map((g) => g.id);
|
||||
const groupsToAdd = (groups as Group[])
|
||||
.filter(
|
||||
(g) =>
|
||||
selectedTagGroups.includes(g.name) &&
|
||||
selectedTagGroups.includes(g.id || "") &&
|
||||
!groupsToRemove.includes(g.id || "") &&
|
||||
!peerGroups.find((pg) => pg.id === g.id)
|
||||
)
|
||||
.map((g) => g.id) as string[];
|
||||
|
||||
const groupsNoId = selectedTagGroups.filter(
|
||||
(stg) => !groups.find((g) => g.name === stg)
|
||||
(stg) => !groups.find((g) => g.id === stg)
|
||||
);
|
||||
setPeerGroupsToSave({
|
||||
...peerGroupsToSave,
|
||||
@@ -230,9 +227,9 @@ const PeerUpdate = () => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
const groupName = getGroupNameFromID(value);
|
||||
let tagClosable = true;
|
||||
if (value === "All") {
|
||||
if (groupName[0] === "All") {
|
||||
tagClosable = false;
|
||||
}
|
||||
|
||||
@@ -244,11 +241,20 @@ const PeerUpdate = () => {
|
||||
onClose={onClose}
|
||||
style={{ marginRight: 3 }}
|
||||
>
|
||||
{value}
|
||||
{groupName && groupName.length ? groupName[0] : value}
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
|
||||
const getGroupNameFromID = (groupID: string) => {
|
||||
if (!groupID) {
|
||||
return "";
|
||||
}
|
||||
return (
|
||||
groups?.filter((g) => groupID === g.id).map((g) => g.name || "") || []
|
||||
);
|
||||
};
|
||||
|
||||
const dropDownRender = (menu: React.ReactElement) => (
|
||||
<>
|
||||
{menu}
|
||||
@@ -328,7 +334,7 @@ const PeerUpdate = () => {
|
||||
|
||||
const handleChangeTags = (value: string[]) => {
|
||||
let validatedValues: string[] = [];
|
||||
value.forEach(function (v) {
|
||||
value.forEach(function (v: any) {
|
||||
if (v.trim().length) {
|
||||
validatedValues.push(v);
|
||||
}
|
||||
@@ -336,6 +342,17 @@ const PeerUpdate = () => {
|
||||
setSelectedTagGroups(validatedValues);
|
||||
};
|
||||
|
||||
const getGroupNamesFromIDs = (groupIDList: string[]): string[] => {
|
||||
if (!groupIDList) {
|
||||
return [];
|
||||
}
|
||||
return (
|
||||
groups
|
||||
?.filter((g) => groupIDList.includes(g.id!))
|
||||
.map((g) => g.name || "") || []
|
||||
);
|
||||
};
|
||||
|
||||
const nameValidator = (_: RuleObject, value: string) => {
|
||||
let punyName = punycode.toASCII(value.toLowerCase());
|
||||
let domain = "";
|
||||
@@ -478,7 +495,8 @@ const PeerUpdate = () => {
|
||||
return Promise.reject(new Error("Please enter ate least one group"));
|
||||
}
|
||||
|
||||
value.forEach(function (v: string) {
|
||||
const val = getGroupNamesFromIDs(value);
|
||||
val.forEach(function (v: string) {
|
||||
if (!v.trim().length) {
|
||||
hasSpaceNamed.push(v);
|
||||
}
|
||||
@@ -746,7 +764,7 @@ const PeerUpdate = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={30} style={{ marginTop: "25px" }}>
|
||||
<Col span={4}>
|
||||
<Col lg={4} md={24}>
|
||||
<Form.Item
|
||||
name="ip"
|
||||
label={
|
||||
@@ -791,7 +809,7 @@ const PeerUpdate = () => {
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={5}>
|
||||
<Col lg={5} md={24}>
|
||||
<Form.Item
|
||||
name="dns_label"
|
||||
label="Domain name"
|
||||
@@ -806,7 +824,7 @@ const PeerUpdate = () => {
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Col lg={4} md={24}>
|
||||
<Form.Item
|
||||
name="last_seen"
|
||||
label="Last seen"
|
||||
@@ -861,13 +879,13 @@ const PeerUpdate = () => {
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Col md={24} lg={8}>
|
||||
<Paragraph
|
||||
style={{
|
||||
whiteSpace: "pre-line",
|
||||
margin: 0,
|
||||
fontWeight: "500",
|
||||
}}
|
||||
style={{
|
||||
whiteSpace: "pre-line",
|
||||
margin: 0,
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
Groups
|
||||
</Paragraph>
|
||||
@@ -886,9 +904,12 @@ const PeerUpdate = () => {
|
||||
tagRender={tagRender}
|
||||
dropdownRender={dropDownRender}
|
||||
onChange={handleChangeTags}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
@@ -123,8 +123,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
} else {
|
||||
setNewRoute(false);
|
||||
}
|
||||
|
||||
}, [route]);
|
||||
}, [route]);
|
||||
|
||||
selectedPeer &&
|
||||
selectedPeer.notPeerRoutes &&
|
||||
@@ -362,54 +361,53 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
const styleNotification = { marginTop: 85 };
|
||||
|
||||
const styleNotification = { marginTop: 85 };
|
||||
|
||||
const saveKey = "saving";
|
||||
useEffect(() => {
|
||||
if (savedRoute.loading) {
|
||||
message.loading({
|
||||
content: "Saving...",
|
||||
key: saveKey,
|
||||
duration: 0,
|
||||
style: styleNotification,
|
||||
});
|
||||
} else if (savedRoute.success) {
|
||||
message.success({
|
||||
content: "Route has been successfully added.",
|
||||
key: saveKey,
|
||||
duration: 2,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSetupNewRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRoutePeerVisible(false));
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, success: false }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
} else if (savedRoute.error) {
|
||||
let errorMsg = "Failed to update network route";
|
||||
switch (savedRoute.error.statusCode) {
|
||||
case 403:
|
||||
errorMsg =
|
||||
"Failed to update network route. You might not have enough permissions.";
|
||||
break;
|
||||
default:
|
||||
errorMsg = savedRoute.error.data.message
|
||||
? savedRoute.error.data.message
|
||||
: errorMsg;
|
||||
break;
|
||||
}
|
||||
message.error({
|
||||
content: errorMsg,
|
||||
key: saveKey,
|
||||
duration: 5,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, error: null }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
const saveKey = "saving";
|
||||
useEffect(() => {
|
||||
if (savedRoute.loading) {
|
||||
message.loading({
|
||||
content: "Saving...",
|
||||
key: saveKey,
|
||||
duration: 0,
|
||||
style: styleNotification,
|
||||
});
|
||||
} else if (savedRoute.success) {
|
||||
message.success({
|
||||
content: "Route has been successfully added.",
|
||||
key: saveKey,
|
||||
duration: 2,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSetupNewRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRoutePeerVisible(false));
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, success: false }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
} else if (savedRoute.error) {
|
||||
let errorMsg = "Failed to update network route";
|
||||
switch (savedRoute.error.statusCode) {
|
||||
case 403:
|
||||
errorMsg =
|
||||
"Failed to update network route. You might not have enough permissions.";
|
||||
break;
|
||||
default:
|
||||
errorMsg = savedRoute.error.data.message
|
||||
? savedRoute.error.data.message
|
||||
: errorMsg;
|
||||
break;
|
||||
}
|
||||
}, [savedRoute]);
|
||||
|
||||
message.error({
|
||||
content: errorMsg,
|
||||
key: saveKey,
|
||||
duration: 5,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, error: null }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
}
|
||||
}, [savedRoute]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{route && (
|
||||
@@ -426,7 +424,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
disabled={savedRoute.loading}
|
||||
onClick={handleFormSubmit}
|
||||
>
|
||||
Add Route
|
||||
Add route
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
@@ -455,7 +453,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
marginBottom: "25px",
|
||||
}}
|
||||
>
|
||||
Add Route
|
||||
Add route
|
||||
</Paragraph>
|
||||
|
||||
{!!selectedPeer.selectedPeer && (
|
||||
@@ -734,9 +732,12 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeTags}
|
||||
dropdownRender={dropDownRender}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
@@ -887,7 +888,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
</Col>
|
||||
<Col
|
||||
span={24}
|
||||
style={{ marginTop: "20px", marginBottom: "25px" }}
|
||||
style={{ marginTop: "24px", marginBottom: "12px" }}
|
||||
>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
@@ -897,7 +898,7 @@ const RouteAddNew = (selectedPeer: any) => {
|
||||
href="https://docs.netbird.io/how-to/routing-traffic-to-private-networks"
|
||||
>
|
||||
{" "}
|
||||
Network Routes
|
||||
network routes
|
||||
</a>
|
||||
</Text>
|
||||
</Col>
|
||||
|
||||
@@ -73,7 +73,7 @@ const RoutePeerUpdate = () => {
|
||||
if (!route) return;
|
||||
const fRoute = {
|
||||
...route,
|
||||
groups: getGroupNamesFromIDs(route.groups),
|
||||
groups: route.groups,
|
||||
} as FormRoute;
|
||||
setFormRoute(fRoute);
|
||||
form.setFieldsValue(fRoute);
|
||||
@@ -222,53 +222,53 @@ const RoutePeerUpdate = () => {
|
||||
onCancel();
|
||||
};
|
||||
|
||||
const styleNotification = { marginTop: 85 };
|
||||
const styleNotification = { marginTop: 85 };
|
||||
|
||||
const saveKey = "saving";
|
||||
useEffect(() => {
|
||||
if (savedRoute.loading) {
|
||||
message.loading({
|
||||
content: "Saving...",
|
||||
key: saveKey,
|
||||
duration: 0,
|
||||
style: styleNotification,
|
||||
});
|
||||
} else if (savedRoute.success) {
|
||||
message.success({
|
||||
content: "Route has been successfully updated.",
|
||||
key: saveKey,
|
||||
duration: 2,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSetupNewRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRoutePeerVisible(false));
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, success: false }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
} else if (savedRoute.error) {
|
||||
let errorMsg = "Failed to update network route";
|
||||
switch (savedRoute.error.statusCode) {
|
||||
case 403:
|
||||
errorMsg =
|
||||
"Failed to update network route. You might not have enough permissions.";
|
||||
break;
|
||||
default:
|
||||
errorMsg = savedRoute.error.data.message
|
||||
? savedRoute.error.data.message
|
||||
: errorMsg;
|
||||
break;
|
||||
}
|
||||
message.error({
|
||||
content: errorMsg,
|
||||
key: saveKey,
|
||||
duration: 5,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, error: null }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
const saveKey = "saving";
|
||||
useEffect(() => {
|
||||
if (savedRoute.loading) {
|
||||
message.loading({
|
||||
content: "Saving...",
|
||||
key: saveKey,
|
||||
duration: 0,
|
||||
style: styleNotification,
|
||||
});
|
||||
} else if (savedRoute.success) {
|
||||
message.success({
|
||||
content: "Route has been successfully updated.",
|
||||
key: saveKey,
|
||||
duration: 2,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSetupNewRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRouteVisible(false));
|
||||
dispatch(routeActions.setSetupEditRoutePeerVisible(false));
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, success: false }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
} else if (savedRoute.error) {
|
||||
let errorMsg = "Failed to update network route";
|
||||
switch (savedRoute.error.statusCode) {
|
||||
case 403:
|
||||
errorMsg =
|
||||
"Failed to update network route. You might not have enough permissions.";
|
||||
break;
|
||||
default:
|
||||
errorMsg = savedRoute.error.data.message
|
||||
? savedRoute.error.data.message
|
||||
: errorMsg;
|
||||
break;
|
||||
}
|
||||
}, [savedRoute]);
|
||||
|
||||
message.error({
|
||||
content: errorMsg,
|
||||
key: saveKey,
|
||||
duration: 5,
|
||||
style: styleNotification,
|
||||
});
|
||||
dispatch(routeActions.setSavedRoute({ ...savedRoute, error: null }));
|
||||
dispatch(routeActions.resetSavedRoute(null));
|
||||
}
|
||||
}, [savedRoute]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container style={{ paddingTop: "40px", paddingBottom: "50px" }}>
|
||||
@@ -291,7 +291,7 @@ const RoutePeerUpdate = () => {
|
||||
requiredMark={false}
|
||||
onValuesChange={onChange}
|
||||
style={{ width: "100%", maxWidth: "600px" }}
|
||||
className="route-form"
|
||||
className="route-form edit-form-wrapper"
|
||||
>
|
||||
<Row gutter={16}>
|
||||
<Col span={24}>
|
||||
@@ -477,9 +477,12 @@ const RoutePeerUpdate = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeTags}
|
||||
dropdownRender={dropDownRender}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
@@ -76,7 +76,7 @@ const RouteAddNew = () => {
|
||||
if (!route) return;
|
||||
const fRoute = {
|
||||
...route,
|
||||
groups: getGroupNamesFromIDs(route.groups),
|
||||
groups: route.groups,
|
||||
} as FormRoute;
|
||||
setFormRoute(fRoute);
|
||||
setPreviousRouteKey(fRoute.network_id + fRoute.network);
|
||||
@@ -310,7 +310,7 @@ const RouteAddNew = () => {
|
||||
disabled={savedRoute.loading}
|
||||
onClick={handleFormSubmit}
|
||||
>
|
||||
Add Route
|
||||
Add route
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
@@ -334,9 +334,7 @@ const RouteAddNew = () => {
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
fontSize: "18px",
|
||||
margin: "0px",
|
||||
fontWeight: 500,
|
||||
marginBottom: "0",
|
||||
}}
|
||||
>
|
||||
Add new routing peer
|
||||
@@ -344,9 +342,12 @@ const RouteAddNew = () => {
|
||||
<Paragraph
|
||||
type={"secondary"}
|
||||
style={{
|
||||
marginTop: "-2",
|
||||
fontWeight: "400",
|
||||
marginBottom: "25px",
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
marginTop: "-23px",
|
||||
fontSize: "14px",
|
||||
paddingBottom: "25px",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
When you add multiple routing peers, NetBird enables high
|
||||
@@ -474,9 +475,12 @@ const RouteAddNew = () => {
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeTags}
|
||||
dropdownRender={dropDownRender}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
@@ -7,11 +7,9 @@ import {
|
||||
Divider,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Row,
|
||||
Select,
|
||||
Breadcrumb,
|
||||
Switch,
|
||||
Tag,
|
||||
Typography,
|
||||
Card,
|
||||
@@ -22,15 +20,14 @@ import {
|
||||
SetupKey,
|
||||
SetupKeyToSave,
|
||||
} from "../store/setup-key/types";
|
||||
import { formatDate, timeAgo } from "../utils/common";
|
||||
import { formatDate } from "../utils/common";
|
||||
import { RuleObject } from "antd/lib/form";
|
||||
import { CustomTagProps } from "rc-select/lib/BaseSelect";
|
||||
import { Group } from "../store/group/types";
|
||||
import { useGetTokenSilently } from "../utils/token";
|
||||
import moment from "moment";
|
||||
import { Container } from "./Container";
|
||||
import Paragraph from "antd/es/typography/Paragraph";
|
||||
import { EditOutlined, LockOutlined } from "@ant-design/icons";
|
||||
import { LockOutlined } from "@ant-design/icons";
|
||||
import { actions as personalAccessTokenActions } from "../store/personal-access-token";
|
||||
import { useGetGroupTagHelpers } from "../utils/groups";
|
||||
|
||||
@@ -42,7 +39,13 @@ const customExpiresFormat = (value: Date): string | null => {
|
||||
};
|
||||
|
||||
const SetupKeyNew = () => {
|
||||
const { optionRender, blueTagRender } = useGetGroupTagHelpers();
|
||||
const {
|
||||
optionRender,
|
||||
blueTagRender,
|
||||
tagGroups,
|
||||
getExistingAndToCreateGroupsLists,
|
||||
setGroupTagFilterAll,
|
||||
} = useGetGroupTagHelpers();
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -50,14 +53,18 @@ const SetupKeyNew = () => {
|
||||
const savedSetupKey = useSelector(
|
||||
(state: RootState) => state.setupKey.savedSetupKey
|
||||
);
|
||||
|
||||
const groups = useSelector((state: RootState) => state.group.data);
|
||||
|
||||
const [form] = Form.useForm();
|
||||
const [editName, setEditName] = useState(false);
|
||||
const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
const [formSetupKey, setFormSetupKey] = useState({} as FormSetupKey);
|
||||
const [formSetupKey, setFormSetupKey] = useState({} as FormSetupKey);
|
||||
const inputNameRef = useRef<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setGroupTagFilterAll(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
//Unmounting component clean
|
||||
return () => {
|
||||
@@ -71,12 +78,6 @@ const SetupKeyNew = () => {
|
||||
inputNameRef.current!.focus({ cursor: "end" });
|
||||
}, [editName]);
|
||||
|
||||
useEffect(() => {
|
||||
setTagGroups(
|
||||
groups?.filter((g) => g.name !== "All").map((g) => g.name) || []
|
||||
);
|
||||
}, [groups]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!setupKey) return;
|
||||
|
||||
@@ -92,32 +93,25 @@ const SetupKeyNew = () => {
|
||||
|
||||
const fSetupKey = {
|
||||
...setupKey,
|
||||
autoGroupNames: setupKey.auto_groups ? formKeyGroups : [],
|
||||
autoGroupNames: setupKey.auto_groups || [],
|
||||
exp: moment(setupKey.expires),
|
||||
last: moment(setupKey.last_used),
|
||||
} as FormSetupKey;
|
||||
|
||||
form.setFieldsValue(fSetupKey);
|
||||
setFormSetupKey(fSetupKey);
|
||||
}, [setupKey]);
|
||||
|
||||
const createSetupKeyToSave = (): SetupKeyToSave => {
|
||||
const autoGroups =
|
||||
groups
|
||||
?.filter((g) => formSetupKey.autoGroupNames.includes(g.name))
|
||||
.map((g) => g.id || "") || [];
|
||||
// find groups that do not yet exist (newly added by the user)
|
||||
const allGroupsNames: string[] = groups?.map((g) => g.name);
|
||||
const groupsToCreate = formSetupKey.autoGroupNames.filter(
|
||||
(s) => !allGroupsNames.includes(s)
|
||||
let [existingGroups, groupsToCreate] = getExistingAndToCreateGroupsLists(
|
||||
formSetupKey.autoGroupNames
|
||||
);
|
||||
|
||||
const expiresIn = formSetupKey.expires_in * 24 * 3600 // the api expects seconds while the form returns days
|
||||
const expiresIn = formSetupKey.expires_in * 24 * 3600; // the api expects seconds while the form returns days
|
||||
return {
|
||||
id: formSetupKey.id,
|
||||
name: formSetupKey.name,
|
||||
type: formSetupKey.type,
|
||||
auto_groups: autoGroups,
|
||||
auto_groups: existingGroups,
|
||||
revoked: formSetupKey.revoked,
|
||||
groupsToCreate: groupsToCreate,
|
||||
expires_in: expiresIn,
|
||||
@@ -275,7 +269,13 @@ const SetupKeyNew = () => {
|
||||
/>
|
||||
<Card bordered={true} style={{ marginBottom: "7px", border: "none" }}>
|
||||
<div style={{ maxWidth: "800px" }}>
|
||||
<h3 style={{ fontSize: "22px", fontWeight: "500",marginBottom:"30px" }}>
|
||||
<h3
|
||||
style={{
|
||||
fontSize: "22px",
|
||||
fontWeight: "500",
|
||||
marginBottom: "30px",
|
||||
}}
|
||||
>
|
||||
{setupKey.name}
|
||||
</h3>
|
||||
<Form
|
||||
@@ -361,7 +361,7 @@ const SetupKeyNew = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ marginTop: "30px" }}>
|
||||
<Row style={{ marginTop: "39px" }}>
|
||||
<Col
|
||||
xs={24}
|
||||
sm={24}
|
||||
@@ -396,9 +396,12 @@ const SetupKeyNew = () => {
|
||||
dropdownRender={dropDownRender}
|
||||
// enabled only when we have a new key !setupkey.id or when the key is valid
|
||||
disabled={!(!setupKey.id || setupKey.valid)}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
@@ -419,20 +422,6 @@ const SetupKeyNew = () => {
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ marginTop: "40px", marginBottom: "28px" }}>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://docs.netbird.io/how-to/register-machines-using-setup-keys"
|
||||
>
|
||||
{" "}
|
||||
Setup Keys
|
||||
</a>
|
||||
</Text>
|
||||
</Row>
|
||||
</Form>
|
||||
</div>
|
||||
<Container
|
||||
@@ -442,6 +431,7 @@ const SetupKeyNew = () => {
|
||||
justifyContent: "start",
|
||||
padding: 0,
|
||||
gap: "10px",
|
||||
marginTop: "24px",
|
||||
}}
|
||||
key={0}
|
||||
>
|
||||
|
||||
@@ -11,9 +11,7 @@ import {
|
||||
Modal,
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Tag,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import { RootState } from "typesafe-actions";
|
||||
@@ -23,21 +21,24 @@ import {
|
||||
SetupKeyToSave,
|
||||
} from "../store/setup-key/types";
|
||||
import { RuleObject } from "antd/lib/form";
|
||||
import { CustomTagProps } from "rc-select/lib/BaseSelect";
|
||||
import { Group } from "../store/group/types";
|
||||
import { useGetTokenSilently } from "../utils/token";
|
||||
import moment from "moment";
|
||||
import { Container } from "./Container";
|
||||
import Paragraph from "antd/es/typography/Paragraph";
|
||||
import { CheckOutlined, CopyOutlined } from "@ant-design/icons";
|
||||
import { copyToClipboard } from "../utils/common";
|
||||
import {useGetGroupTagHelpers} from "../utils/groups";
|
||||
import { useGetGroupTagHelpers } from "../utils/groups";
|
||||
|
||||
const { Option } = Select;
|
||||
const { Text } = Typography;
|
||||
|
||||
const SetupKeyNew = () => {
|
||||
const { optionRender, blueTagRender } = useGetGroupTagHelpers();
|
||||
const {
|
||||
optionRender,
|
||||
blueTagRender,
|
||||
tagGroups,
|
||||
getExistingAndToCreateGroupsLists,
|
||||
setGroupTagFilterAll,
|
||||
} = useGetGroupTagHelpers();
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const dispatch = useDispatch();
|
||||
const setupNewKeyVisible = useSelector(
|
||||
@@ -54,7 +55,6 @@ const SetupKeyNew = () => {
|
||||
const [showPlainToken, setShowPlainToken] = useState(false);
|
||||
const [plainToken, setPlainToken] = useState("");
|
||||
const [tokenCopied, setTokenCopied] = useState(false);
|
||||
const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
const [formSetupKey, setFormSetupKey] = useState({} as FormSetupKey);
|
||||
const inputNameRef = useRef<any>(null);
|
||||
|
||||
@@ -65,52 +65,21 @@ const SetupKeyNew = () => {
|
||||
}, [editName]);
|
||||
|
||||
useEffect(() => {
|
||||
setTagGroups(
|
||||
groups?.filter((g) => g.name !== "All").map((g) => g.name) || []
|
||||
);
|
||||
}, [groups]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!setupKey) return;
|
||||
|
||||
const allGroups = new Map<string, Group>();
|
||||
let formKeyGroups: string[] = [];
|
||||
groups.forEach((g) => allGroups.set(g.id!, g));
|
||||
|
||||
if (setupKey.auto_groups) {
|
||||
formKeyGroups = setupKey.auto_groups
|
||||
.filter((g) => allGroups.get(g))
|
||||
.map((g) => allGroups.get(g)!.name);
|
||||
}
|
||||
|
||||
const fSetupKey = {
|
||||
...setupKey,
|
||||
autoGroupNames: setupKey.auto_groups ? formKeyGroups : [],
|
||||
exp: moment(setupKey.expires),
|
||||
last: moment(setupKey.last_used),
|
||||
} as FormSetupKey;
|
||||
|
||||
form.setFieldsValue(fSetupKey);
|
||||
setFormSetupKey(fSetupKey);
|
||||
}, [setupKey]);
|
||||
setGroupTagFilterAll(true);
|
||||
}, []);
|
||||
|
||||
const createSetupKeyToSave = (): SetupKeyToSave => {
|
||||
const autoGroups =
|
||||
groups
|
||||
?.filter((g) => formSetupKey.autoGroupNames.includes(g.name))
|
||||
.map((g) => g.id || "") || [];
|
||||
// find groups that do not yet exist (newly added by the user)
|
||||
const allGroupsNames: string[] = groups?.map((g) => g.name);
|
||||
const groupsToCreate = formSetupKey.autoGroupNames.filter(
|
||||
(s) => !allGroupsNames.includes(s)
|
||||
let [existingGroups, groupsToCreate] = getExistingAndToCreateGroupsLists(
|
||||
formSetupKey.autoGroupNames || []
|
||||
);
|
||||
|
||||
const expiresIn = formSetupKey.expires_in * 24 * 3600 // the api expects seconds we have days
|
||||
const expiresIn = formSetupKey.expires_in
|
||||
? formSetupKey.expires_in * 24 * 3600
|
||||
: 7 * 24 * 3600; // the api expects seconds we have days
|
||||
return {
|
||||
id: formSetupKey.id,
|
||||
name: formSetupKey.name,
|
||||
type: formSetupKey.type,
|
||||
auto_groups: autoGroups,
|
||||
type: formSetupKey.type ? formSetupKey.type : "one-off",
|
||||
auto_groups: existingGroups,
|
||||
revoked: formSetupKey.revoked,
|
||||
groupsToCreate: groupsToCreate,
|
||||
expires_in: expiresIn,
|
||||
@@ -180,7 +149,7 @@ const SetupKeyNew = () => {
|
||||
type: "one-off",
|
||||
key: "",
|
||||
last_used: "",
|
||||
expires: "",
|
||||
expires: "7",
|
||||
state: "valid",
|
||||
auto_groups: [] as string[],
|
||||
usage_limit: 0,
|
||||
@@ -251,25 +220,27 @@ const SetupKeyNew = () => {
|
||||
);
|
||||
|
||||
const changesDetected = (): boolean => {
|
||||
console.log("formSetupKey", formSetupKey);
|
||||
return (
|
||||
formSetupKey.name == null ||
|
||||
formSetupKey.name !== setupKey.name ||
|
||||
groupsChanged() ||
|
||||
formSetupKey.usage_limit !== setupKey.usage_limit
|
||||
formSetupKey?.usage_limit !== setupKey.usage_limit
|
||||
);
|
||||
};
|
||||
|
||||
const groupsChanged = (): boolean => {
|
||||
console.log("groupsChanged", formSetupKey);
|
||||
if (
|
||||
setupKey &&
|
||||
setupKey.auto_groups &&
|
||||
formSetupKey.autoGroupNames.length !== setupKey.auto_groups.length
|
||||
setupKey?.auto_groups &&
|
||||
formSetupKey?.autoGroupNames &&
|
||||
formSetupKey?.autoGroupNames.length !== setupKey?.auto_groups.length
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
const formGroupIds =
|
||||
groups
|
||||
?.filter((g) => formSetupKey.autoGroupNames.includes(g.name))
|
||||
?.filter((g) => formSetupKey?.autoGroupNames.includes(g.name))
|
||||
.map((g) => g.id || "") || [];
|
||||
|
||||
return (
|
||||
@@ -314,7 +285,7 @@ const SetupKeyNew = () => {
|
||||
fontSize: "14px",
|
||||
borderRadius: "2px",
|
||||
}}
|
||||
disabled={savedSetupKey.loading || !changesDetected()}
|
||||
disabled={savedSetupKey.loading || !!!formSetupKey.name}
|
||||
onClick={handleFormSubmit}
|
||||
>
|
||||
Create key
|
||||
@@ -345,8 +316,7 @@ const SetupKeyNew = () => {
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
fontSize: "18px",
|
||||
margin: "0px",
|
||||
fontWeight:"500"
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
{showPlainToken
|
||||
@@ -358,6 +328,10 @@ const SetupKeyNew = () => {
|
||||
style={{
|
||||
textAlign: "start",
|
||||
whiteSpace: "pre-line",
|
||||
marginTop: "-20px",
|
||||
fontSize: "14px",
|
||||
paddingBottom: "25px",
|
||||
marginBottom: "4px",
|
||||
}}
|
||||
>
|
||||
{showPlainToken
|
||||
@@ -372,6 +346,7 @@ const SetupKeyNew = () => {
|
||||
onValuesChange={onChange}
|
||||
initialValues={{
|
||||
usage_limit: 1,
|
||||
expires_in: "7",
|
||||
}}
|
||||
>
|
||||
<Row>
|
||||
@@ -398,7 +373,7 @@ const SetupKeyNew = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ marginTop: "20px" }} justify={"space-between"}>
|
||||
<Row style={{ marginTop: "24px" }} justify={"space-between"}>
|
||||
<Col span={18}>
|
||||
<Paragraph
|
||||
style={{
|
||||
@@ -420,6 +395,7 @@ const SetupKeyNew = () => {
|
||||
<Row justify={"end"}>
|
||||
<Form.Item name="reusable" valuePropName="checked">
|
||||
<Switch
|
||||
size="small"
|
||||
onChange={(checked) => {
|
||||
setFormSetupKey({
|
||||
...formSetupKey,
|
||||
@@ -432,7 +408,7 @@ const SetupKeyNew = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ marginTop: "10px" }}>
|
||||
<Row style={{ marginTop: "16px" }}>
|
||||
<Col span={24}>
|
||||
<Paragraph
|
||||
style={{
|
||||
@@ -470,7 +446,7 @@ const SetupKeyNew = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ marginTop: "20px" }}>
|
||||
<Row style={{ marginTop: "24px" }}>
|
||||
<Col span={24}>
|
||||
<Paragraph
|
||||
style={{
|
||||
@@ -505,7 +481,7 @@ const SetupKeyNew = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ marginTop: "20px" }}>
|
||||
<Row style={{ marginTop: "24px" }}>
|
||||
<Col span={24}>
|
||||
<Paragraph
|
||||
style={{
|
||||
@@ -525,25 +501,27 @@ const SetupKeyNew = () => {
|
||||
<Form.Item
|
||||
style={{ marginTop: "5px", marginBottom: 0 }}
|
||||
name="autoGroupNames"
|
||||
rules={[{ validator: selectValidator }]}
|
||||
>
|
||||
<Select
|
||||
mode="tags"
|
||||
style={{ width: "100%"}}
|
||||
style={{ width: "100%" }}
|
||||
placeholder="Associate groups with the key"
|
||||
tagRender={blueTagRender}
|
||||
dropdownRender={dropDownRender}
|
||||
// enabled only when we have a new key !setupkey.id or when the key is valid
|
||||
disabled={!(!setupKey.id || setupKey.valid)}
|
||||
optionFilterProp="serchValue"
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ marginTop: "40px", marginBottom: "28px" }}>
|
||||
<Row style={{ marginTop: "24px", marginBottom: "24px" }}>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
<a
|
||||
|
||||
+652
-625
File diff suppressed because it is too large.
Load diff
@@ -177,9 +177,18 @@ const AddPATPopup = () => {
|
||||
</Form.Item>
|
||||
<Paragraph type={"secondary"} style={{fontSize: "14px", marginTop: "-18px"}}>Should be between 1 and 365 days</Paragraph>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Button icon={<QuestionCircleFilled/>} type="link" target="_blank" disabled={true} style={{marginTop: "20px", marginBottom: "20px"}}
|
||||
href="https://docs.netbird.io/how-to/access-netbird-public-api">Learn more about personal access tokens</Button>
|
||||
<Col span={24} style={{marginTop: "15px"}}>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://docs.netbird.io/how-to/access-netbird-public-api"
|
||||
>
|
||||
{" "}
|
||||
access tokens
|
||||
</a>
|
||||
</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>}
|
||||
|
||||
@@ -8,11 +8,10 @@ import {
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
Tag,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import { Container } from "../Container";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { RootState } from "typesafe-actions";
|
||||
import { useGetTokenSilently } from "../../utils/token";
|
||||
@@ -28,7 +27,8 @@ const { Title, Text, Paragraph } = Typography;
|
||||
const { Option } = Select;
|
||||
|
||||
const InviteUserPopup = () => {
|
||||
const { optionRender, blueTagRender } = useGetGroupTagHelpers();
|
||||
const { optionRender, blueTagRender, tagGroups, handleChangeTags } =
|
||||
useGetGroupTagHelpers();
|
||||
const { getTokenSilently } = useGetTokenSilently();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -48,19 +48,16 @@ const InviteUserPopup = () => {
|
||||
const [form] = Form.useForm();
|
||||
const inputNameRef = useRef<any>(null);
|
||||
|
||||
const [tagGroups, setTagGroups] = useState([] as string[]);
|
||||
const [selectedTagGroups, setSelectedTagGroups] = useState([] as string[]);
|
||||
|
||||
const createUserToSave = (values: any): UserToSave => {
|
||||
const autoGroups =
|
||||
groups
|
||||
?.filter(
|
||||
(g) =>
|
||||
values.autoGroupsNames && values.autoGroupsNames.includes(g.name)
|
||||
values.autoGroupsNames && values.autoGroupsNames.includes(g.id)
|
||||
)
|
||||
.map((g) => g.id || "") || [];
|
||||
// find groups that do not yet exist (newly added by the user)
|
||||
const allGroupsNames: string[] = groups?.map((g) => g.name);
|
||||
const allGroupsNames: string[] = groups?.map((g) => g.id || "");
|
||||
const groupsToCreate =
|
||||
values.autoGroupsNames?.filter(
|
||||
(s: string) => !allGroupsNames.includes(s)
|
||||
@@ -130,15 +127,15 @@ const InviteUserPopup = () => {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const handleChangeTags = (value: string[]) => {
|
||||
let validatedValues: string[] = [];
|
||||
value.forEach(function (v) {
|
||||
if (v.trim().length) {
|
||||
validatedValues.push(v);
|
||||
}
|
||||
});
|
||||
setSelectedTagGroups(validatedValues);
|
||||
};
|
||||
// const handleChangeTags = (value: string[]) => {
|
||||
// let validatedValues: string[] = [];
|
||||
// value.forEach(function (v) {
|
||||
// if (v.trim().length) {
|
||||
// validatedValues.push(v);
|
||||
// }
|
||||
// });
|
||||
// setSelectedTagGroups(validatedValues);
|
||||
// };
|
||||
|
||||
const dropDownRender = (menu: React.ReactElement) => (
|
||||
<>
|
||||
@@ -168,11 +165,11 @@ const InviteUserPopup = () => {
|
||||
</>
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setTagGroups(
|
||||
groups?.filter((g) => g.name != "All").map((g) => g.name) || []
|
||||
);
|
||||
}, [groups]);
|
||||
// useEffect(() => {
|
||||
// setTagGroups(
|
||||
// groups?.filter((g) => g.name != "All").map((g) => g.name) || []
|
||||
// );
|
||||
// }, [groups]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
@@ -334,25 +331,29 @@ const InviteUserPopup = () => {
|
||||
placeholder="Associate groups with the user"
|
||||
tagRender={blueTagRender}
|
||||
onChange={handleChangeTags}
|
||||
optionFilterProp="serchValue"
|
||||
dropdownRender={dropDownRender}
|
||||
>
|
||||
{tagGroups.map((m) => (
|
||||
<Option key={m}>{optionRender(m)}</Option>
|
||||
{tagGroups.map((m, index) => (
|
||||
<Option key={index} value={m.id} serchValue={m.name}>
|
||||
{optionRender(m.name, m.id)}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Button
|
||||
icon={<QuestionCircleFilled />}
|
||||
type="link"
|
||||
target="_blank"
|
||||
disabled={true}
|
||||
style={{ marginTop: "20px", marginBottom: "20px" }}
|
||||
href="https://docs.netbird.io/how-to/access-netbird-public-api"
|
||||
>
|
||||
Learn more about user
|
||||
</Button>
|
||||
<Text type={"secondary"}>
|
||||
Learn more about
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://docs.netbird.io/how-to/add-users-to-your-network"
|
||||
>
|
||||
{" "}
|
||||
user management
|
||||
</a>
|
||||
</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
|
||||
+22
-1
@@ -433,7 +433,7 @@ ul.ant-list-items {
|
||||
}
|
||||
|
||||
.route-form .ant-form-item {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.nb-code {
|
||||
@@ -467,4 +467,25 @@ ul.ant-list-items {
|
||||
|
||||
.style-like-text .ant-select-arrow {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
.ant-spin-nested-loading .ant-spin-spinning {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.route-form.edit-form-wrapper .ant-form-item {
|
||||
margin-bottom: 39px;
|
||||
}
|
||||
|
||||
.groupsSelect {
|
||||
max-width: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 1220px) {
|
||||
.groupsSelect{
|
||||
margin-left: 0;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export const storeFilterState = (page, filterName, filterValue) => {
|
||||
let filterStateObj = {}
|
||||
|
||||
const getValue = localStorage.getItem(page)
|
||||
if (getValue) {
|
||||
filterStateObj = JSON.parse(getValue)
|
||||
}
|
||||
|
||||
filterStateObj[filterName] = filterValue
|
||||
localStorage.setItem(page, JSON.stringify(filterStateObj))
|
||||
}
|
||||
|
||||
|
||||
export const getFilterState = (page, filterName) => {
|
||||
const getFilterObject = JSON.parse(localStorage.getItem(page))
|
||||
if (getFilterObject) {
|
||||
return getFilterObject[filterName]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
+166
-134
@@ -1,150 +1,182 @@
|
||||
import {CustomTagProps} from "rc-select/lib/BaseSelect";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Col, Divider, Row, Tag} from "antd";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState} from "typesafe-actions";
|
||||
import {RuleObject} from "antd/lib/form";
|
||||
import { CustomTagProps } from "rc-select/lib/BaseSelect";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Col, Divider, Row, Tag } from "antd";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "typesafe-actions";
|
||||
import { RuleObject } from "antd/lib/form";
|
||||
|
||||
export const useGetGroupTagHelpers = () => {
|
||||
const groups = useSelector((state: RootState) => state.group.data)
|
||||
const groups = useSelector((state: RootState) => state.group.data);
|
||||
const [tagGroups, setTagGroups] = useState([] as any[]);
|
||||
const [groupTagFilterAll, setGroupTagFilterAll] = useState(false);
|
||||
const [selectedTagGroups, setSelectedTagGroups] = useState([] as string[]);
|
||||
|
||||
const [tagGroups, setTagGroups] = useState([] as string[])
|
||||
const [groupTagFilterAll, setGroupTagFilterAll] = useState(false)
|
||||
const [selectedTagGroups, setSelectedTagGroups] = useState([] as string[])
|
||||
const blueTagRender = (props: CustomTagProps) => {
|
||||
return tagRender(props, "blue");
|
||||
};
|
||||
const grayTagRender = (props: CustomTagProps) => {
|
||||
return tagRender(props, "");
|
||||
};
|
||||
|
||||
const blueTagRender = (props: CustomTagProps) => {
|
||||
return tagRender(props, "blue")
|
||||
}
|
||||
const grayTagRender = (props: CustomTagProps) => {
|
||||
return tagRender(props, "")
|
||||
}
|
||||
|
||||
const tagRender = (props: CustomTagProps, color: string) => {
|
||||
const {value, closable, onClose} = props;
|
||||
const onPreventMouseDown = (event: React.MouseEvent<HTMLSpanElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
return (
|
||||
<Tag
|
||||
color={color}
|
||||
onMouseDown={onPreventMouseDown}
|
||||
closable={closable}
|
||||
onClose={onClose}
|
||||
style={{marginRight: 3}}
|
||||
>
|
||||
{value}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
|
||||
const handleChangeTags = (value: string[]) => {
|
||||
let validatedValues: string[] = []
|
||||
value.forEach(function (v) {
|
||||
if (v.trim().length) {
|
||||
validatedValues.push(v)
|
||||
}
|
||||
})
|
||||
setSelectedTagGroups(validatedValues)
|
||||
const tagRender = (props: CustomTagProps, color: string) => {
|
||||
const { value, closable, onClose } = props;
|
||||
const onPreventMouseDown = (event: React.MouseEvent<HTMLSpanElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
const groupName = getGroupNameFromID(value);
|
||||
return (
|
||||
<Tag
|
||||
color={color}
|
||||
onMouseDown={onPreventMouseDown}
|
||||
closable={closable}
|
||||
onClose={onClose}
|
||||
style={{ marginRight: 3 }}
|
||||
>
|
||||
{groupName && groupName.length ? groupName[0] : value}
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
|
||||
const dropDownRender = (menu: React.ReactElement) => (
|
||||
<>
|
||||
{menu}
|
||||
<Divider style={{margin: '8px 0'}}/>
|
||||
<Row style={{padding: '0 8px 4px'}}>
|
||||
<Col flex="auto">
|
||||
<span style={{color: "#9CA3AF"}}>Add new group by pressing "Enter"</span>
|
||||
</Col>
|
||||
<Col flex="none">
|
||||
<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M1.70455 7.19176V5.89915H10.3949C10.7727 5.89915 11.1174 5.80634 11.429 5.62074C11.7405 5.43513 11.9875 5.18655 12.1697 4.875C12.3554 4.56345 12.4482 4.21875 12.4482 3.84091C12.4482 3.46307 12.3554 3.12003 12.1697 2.81179C11.9841 2.50024 11.7356 2.25166 11.424 2.06605C11.1158 1.88044 10.7727 1.78764 10.3949 1.78764H9.83807V0.5H10.3949C11.0114 0.5 11.5715 0.650805 12.0753 0.952414C12.5791 1.25402 12.9818 1.65672 13.2834 2.16051C13.585 2.6643 13.7358 3.22443 13.7358 3.84091C13.7358 4.30161 13.648 4.73414 13.4723 5.13849C13.3 5.54285 13.0613 5.89915 12.7564 6.20739C12.4515 6.51562 12.0968 6.75758 11.6925 6.93324C11.2881 7.10559 10.8556 7.19176 10.3949 7.19176H1.70455ZM4.90128 11.0646L0.382102 6.54545L4.90128 2.02628L5.79119 2.91619L2.15696 6.54545L5.79119 10.1747L4.90128 11.0646Z"
|
||||
fill="#9CA3AF"/>
|
||||
</svg>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
const handleChangeTags = (value: string[]) => {
|
||||
const groupsName = getGroupNamesFromIDs(value);
|
||||
let validatedValues: string[] = [];
|
||||
groupsName.forEach(function (v) {
|
||||
if (v.trim().length) {
|
||||
validatedValues.push(v);
|
||||
}
|
||||
});
|
||||
setSelectedTagGroups(validatedValues);
|
||||
};
|
||||
|
||||
const optionRender = (label: string) => {
|
||||
let peersCount = "";
|
||||
const g = groups.find((_g) => _g.name === label);
|
||||
if (g)
|
||||
peersCount = ` - ${g.peers_count || 0} ${
|
||||
!g.peers_count || parseInt(g.peers_count) !== 1 ? "peers" : "peer"
|
||||
} `;
|
||||
return (
|
||||
<div>
|
||||
<Tag color="blue" style={{ marginRight: 3}}>
|
||||
{label}
|
||||
</Tag>
|
||||
<span style={{ fontSize: ".85em" }}>{peersCount}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const dropDownRender = (menu: React.ReactElement) => (
|
||||
<>
|
||||
{menu}
|
||||
<Divider style={{ margin: "8px 0" }} />
|
||||
<Row style={{ padding: "0 8px 4px" }}>
|
||||
<Col flex="auto">
|
||||
<span style={{ color: "#9CA3AF" }}>
|
||||
Add new group by pressing "Enter"
|
||||
</span>
|
||||
</Col>
|
||||
<Col flex="none">
|
||||
<svg
|
||||
width="14"
|
||||
height="12"
|
||||
viewBox="0 0 14 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1.70455 7.19176V5.89915H10.3949C10.7727 5.89915 11.1174 5.80634 11.429 5.62074C11.7405 5.43513 11.9875 5.18655 12.1697 4.875C12.3554 4.56345 12.4482 4.21875 12.4482 3.84091C12.4482 3.46307 12.3554 3.12003 12.1697 2.81179C11.9841 2.50024 11.7356 2.25166 11.424 2.06605C11.1158 1.88044 10.7727 1.78764 10.3949 1.78764H9.83807V0.5H10.3949C11.0114 0.5 11.5715 0.650805 12.0753 0.952414C12.5791 1.25402 12.9818 1.65672 13.2834 2.16051C13.585 2.6643 13.7358 3.22443 13.7358 3.84091C13.7358 4.30161 13.648 4.73414 13.4723 5.13849C13.3 5.54285 13.0613 5.89915 12.7564 6.20739C12.4515 6.51562 12.0968 6.75758 11.6925 6.93324C11.2881 7.10559 10.8556 7.19176 10.3949 7.19176H1.70455ZM4.90128 11.0646L0.382102 6.54545L4.90128 2.02628L5.79119 2.91619L2.15696 6.54545L5.79119 10.1747L4.90128 11.0646Z"
|
||||
fill="#9CA3AF"
|
||||
/>
|
||||
</svg>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
|
||||
const getExistingAndToCreateGroupsLists = (groupNameList: string[]): [string[], string[]] => {
|
||||
const groupIDList = groups?.filter(g => groupNameList.includes(g.name)).map(g => g.id || '') || []
|
||||
// find groups that do not yet exist (newly added by the user)
|
||||
const existingGroupsNames: string[] = groups?.map(g => g.name);
|
||||
const groupNameListToCreate = groupNameList.filter(s => !existingGroupsNames.includes(s))
|
||||
return [groupIDList, groupNameListToCreate]
|
||||
const optionRender = (label: string, id: any) => {
|
||||
let peersCount = "";
|
||||
const g = groups.find((_g) => _g.id === id);
|
||||
if (g)
|
||||
peersCount = ` - ${g.peers_count || 0} ${
|
||||
!g.peers_count || parseInt(g.peers_count) !== 1 ? "peers" : "peer"
|
||||
} `;
|
||||
return (
|
||||
<div>
|
||||
<Tag color="blue" style={{ marginRight: 3 }}>
|
||||
{label}
|
||||
</Tag>
|
||||
<span style={{ fontSize: ".85em" }}>{peersCount}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const getExistingAndToCreateGroupsLists = (
|
||||
groupIDsList: string[]
|
||||
): [string[], string[]] => {
|
||||
const groupIDList =
|
||||
groups
|
||||
?.filter((g) => groupIDsList.includes(g.id || ""))
|
||||
.map((g) => g.id || "") || [];
|
||||
|
||||
// find groups that do not yet exist (newly added by the user)
|
||||
const existingGroupsNames: any[] = groups?.map((g) => g.id);
|
||||
const groupNameListToCreate = groupIDsList.filter(
|
||||
(s) => !existingGroupsNames.includes(s)
|
||||
);
|
||||
return [groupIDList, groupNameListToCreate];
|
||||
};
|
||||
|
||||
const getGroupNamesFromIDs = (groupIDList: string[]): string[] => {
|
||||
if (!groupIDList) {
|
||||
return [];
|
||||
}
|
||||
return (
|
||||
groups
|
||||
?.filter((g) => groupIDList.includes(g.id!))
|
||||
.map((g) => g.name || "") || []
|
||||
);
|
||||
};
|
||||
|
||||
const getGroupNameFromID = (groupID: string) => {
|
||||
if (!groupID) {
|
||||
return "";
|
||||
}
|
||||
return (
|
||||
groups?.filter((g) => groupID === g.id).map((g) => g.name || "") || []
|
||||
);
|
||||
};
|
||||
|
||||
const selectValidator = (obj: RuleObject, value: string[]) => {
|
||||
if (!value.length) {
|
||||
return Promise.reject(new Error("Please enter at least one group"));
|
||||
}
|
||||
|
||||
const getGroupNamesFromIDs = (groupIDList: string[]): string[] => {
|
||||
if (!groupIDList) {
|
||||
return []
|
||||
}
|
||||
return selectValidatorEmptyStrings(obj, value);
|
||||
};
|
||||
|
||||
return groups?.filter(g => groupIDList.includes(g.id!)).map(g => g.name || '') || []
|
||||
const selectValidatorEmptyStrings = (_: RuleObject, value: string[]) => {
|
||||
let hasSpaceNamed = [];
|
||||
value.forEach(function (v: string) {
|
||||
if (!v.trim().length) {
|
||||
hasSpaceNamed.push(v);
|
||||
}
|
||||
});
|
||||
|
||||
if (hasSpaceNamed.length) {
|
||||
return Promise.reject(
|
||||
new Error("Group names with just spaces are not allowed")
|
||||
);
|
||||
}
|
||||
|
||||
const selectValidator = (obj: RuleObject, value: string[]) => {
|
||||
if (!value.length) {
|
||||
return Promise.reject(new Error("Please enter at least one group"))
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
return selectValidatorEmptyStrings(obj,value)
|
||||
useEffect(() => {
|
||||
if (groupTagFilterAll) {
|
||||
setTagGroups(groups?.filter((g) => g.name !== "All").map((g) => g) || []);
|
||||
} else {
|
||||
setTagGroups(groups);
|
||||
}
|
||||
}, [groups, groupTagFilterAll]);
|
||||
|
||||
const selectValidatorEmptyStrings = (_: RuleObject, value: string[]) => {
|
||||
let hasSpaceNamed = []
|
||||
value.forEach(function (v: string) {
|
||||
if (!v.trim().length) {
|
||||
hasSpaceNamed.push(v)
|
||||
}
|
||||
})
|
||||
|
||||
if (hasSpaceNamed.length) {
|
||||
return Promise.reject(new Error("Group names with just spaces are not allowed"))
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (groupTagFilterAll) {
|
||||
setTagGroups(groups?.filter(g => g.name != "All").map(g => g.name) || [])
|
||||
} else {
|
||||
setTagGroups(groups?.map(g => g.name) || [])
|
||||
}
|
||||
}, [groups])
|
||||
|
||||
return {
|
||||
tagRender,
|
||||
blueTagRender,
|
||||
grayTagRender,
|
||||
handleChangeTags,
|
||||
dropDownRender,
|
||||
optionRender,
|
||||
tagGroups,
|
||||
selectedTagGroups,
|
||||
setGroupTagFilterAll,
|
||||
getExistingAndToCreateGroupsLists,
|
||||
getGroupNamesFromIDs,
|
||||
selectValidator,
|
||||
selectValidatorEmptyStrings
|
||||
}
|
||||
}
|
||||
return {
|
||||
tagRender,
|
||||
blueTagRender,
|
||||
grayTagRender,
|
||||
handleChangeTags,
|
||||
dropDownRender,
|
||||
optionRender,
|
||||
tagGroups,
|
||||
selectedTagGroups,
|
||||
groupTagFilterAll,
|
||||
setGroupTagFilterAll,
|
||||
getExistingAndToCreateGroupsLists,
|
||||
getGroupNamesFromIDs,
|
||||
selectValidator,
|
||||
selectValidatorEmptyStrings,
|
||||
};
|
||||
};
|
||||
+20
-19
@@ -1,24 +1,25 @@
|
||||
import {useState} from "react";
|
||||
import { useState } from "react";
|
||||
import { storeFilterState } from "./filterState";
|
||||
|
||||
export const usePageSizeHelpers = () => {
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const onChangePageSize = (value: string, pageName: string) => {
|
||||
setPageSize(parseInt(value.toString()));
|
||||
storeFilterState(pageName, "pageSize", parseInt(value.toString()));
|
||||
};
|
||||
|
||||
const onChangePageSize = (value: string) => {
|
||||
setPageSize(parseInt(value.toString()))
|
||||
}
|
||||
const pageSizeOptions = [
|
||||
{ label: "10", value: "10" },
|
||||
{ label: "25", value: "25" },
|
||||
{ label: "50", value: "50" },
|
||||
{ label: "100", value: "100" },
|
||||
{ label: "1000", value: "1000" },
|
||||
];
|
||||
|
||||
const pageSizeOptions = [
|
||||
{label: "10", value: "10"},
|
||||
{label: "25", value: "25"},
|
||||
{label: "50", value: "50"},
|
||||
{label: "100", value: "100"},
|
||||
{label: "1000", value: "1000"}
|
||||
]
|
||||
|
||||
return {
|
||||
onChangePageSize,
|
||||
pageSize,
|
||||
pageSizeOptions
|
||||
}
|
||||
}
|
||||
return {
|
||||
onChangePageSize,
|
||||
pageSize,
|
||||
pageSizeOptions,
|
||||
};
|
||||
};
|
||||
Loaded 20 of 30 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user