Compare commits

...
9 Commits
Author SHA1 Message Date
Sarooj bukhari c1b2ededa7 remove duplicate group on select view to change the logic from name to id (#238) 2023-07-20 10:08:26 +02:00
Sarooj bukhari 31eaa4a241 add all filter state on persist on page refresh (#236)
* add all filter state on persist on page refresh

* clear state on logout

* fix issues while refresh
2023-07-20 09:22:01 +02:00
dependabot[bot] ba365336ff Bump word-wrap from 1.2.3 to 1.2.4 (#237)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-19 22:02:03 +05:00
Sarooj bukhari 06c238b013 Fix peer mobile view (#233) 2023-07-18 08:50:58 +02:00
dependabot[bot] ed56c240f3 Bump semver from 6.3.0 to 6.3.1 (#230)
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-15 01:01:59 +05:00
dependabot[bot] 1f3c7d87d7 Bump tough-cookie from 4.1.2 to 4.1.3 (#223)
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-15 01:01:37 +05:00
Zoltan Papp 9de2906fb2 Extend activity view with group delete (#232) 2023-07-14 10:11:32 +02:00
Sarooj bukhari 359b443326 Update remaining pages layout (#231) 2023-07-14 10:09:08 +02:00
braginini ecae39d94b Adjust DNS view 2023-07-13 12:55:04 +02:00
27 changed files with 2392 additions and 1889 deletions

No files matched your search

+84 -84
View File
@@ -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",
+33 -15
View File
@@ -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 {
@@ -618,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)}
</Option>
))}
</Select>
</Form.Item>
@@ -771,9 +782,16 @@ 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)}
</Option>
))}
</Select>
</Form.Item>
+31 -14
View File
@@ -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,
@@ -562,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)}
</Option>
))}
</Select>
</Form.Item>
@@ -715,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)}
</Option>
))}
</Select>
</Form.Item>
+5 -2
View File
@@ -747,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)}
</Option>
))}
</Select>
</Form.Item>
+47 -44
View File
@@ -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);
@@ -314,6 +313,46 @@ const NameServerGroupUpdate = () => {
{ errors }: any
) => (
<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
@@ -706,53 +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)}
</Option>
))}
</Select>
</Form.Item>
</Col>
<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 it to apply immediately"
: " Enable this server if you want it to apply immediately"}
</Paragraph>
</div>
</div>
</Form.Item>
</Col>
<Col
style={{
width: "100%",
+225 -167
View File
@@ -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;
+47 -26
View File
@@ -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)}
</Option>
))}
</Select>
</Form.Item>
+51 -50
View File
@@ -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 && (
@@ -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)}
</Option>
))}
</Select>
</Form.Item>
+51 -48
View File
@@ -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" }}>
@@ -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)}
</Option>
))}
</Select>
</Form.Item>
+6 -3
View File
@@ -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);
@@ -475,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)}
</Option>
))}
</Select>
</Form.Item>
+25 -28
View File
@@ -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,
@@ -402,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)}
</Option>
))}
</Select>
</Form.Item>
+17 -47
View File
@@ -11,9 +11,7 @@ import {
Modal,
Row,
Select,
Space,
Switch,
Tag,
Typography,
} from "antd";
import { RootState } from "typesafe-actions";
@@ -23,10 +21,7 @@ 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";
@@ -37,7 +32,13 @@ 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,19 @@ 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
return {
id: formSetupKey.id,
name: formSetupKey.name,
type: formSetupKey.type,
auto_groups: autoGroups,
auto_groups: existingGroups,
revoked: formSetupKey.revoked,
groupsToCreate: groupsToCreate,
expires_in: expiresIn,
@@ -539,9 +506,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)}
</Option>
))}
</Select>
</Form.Item>
File diff suppressed because it is too large. Load diff
+27 -27
View File
@@ -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,10 +331,13 @@ 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)}
</Option>
))}
</Select>
</Form.Item>
@@ -346,9 +346,9 @@ const InviteUserPopup = () => {
<Text type={"secondary"}>
Learn more about
<a
target="_blank"
rel="noreferrer"
href="https://docs.netbird.io/how-to/add-users-to-your-network"
target="_blank"
rel="noreferrer"
href="https://docs.netbird.io/how-to/add-users-to-your-network"
>
{" "}
user management
+21
View File
@@ -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
View File
@@ -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) => {
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 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
View File
@@ -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,
};
};
+50 -25
View File
@@ -23,6 +23,7 @@ import {
} from "antd";
import { Container } from "../components/Container";
import { useDispatch, useSelector } from "react-redux";
import { storeFilterState, getFilterState } from "../utils/filterState";
import { RootState } from "typesafe-actions";
import { Policy } from "../store/policy/types";
import { actions as policyActions } from "../store/policy";
@@ -122,6 +123,25 @@ export const AccessControl = () => {
};
}, []);
useEffect(() => {
if (!loading) {
const quickFilter = getFilterState("accessControlFilter", "quickFilter");
if (quickFilter) setOptionAllEnable(quickFilter);
const searchText = getFilterState("accessControlFilter", "search");
if (searchText) setTextToSearch(searchText);
const pageSize = getFilterState("accessControlFilter", "pageSize");
if (pageSize) onChangePageSize(pageSize, "accessControlFilter");
if (quickFilter || searchText || pageSize) {
setDataTable(transformDataTable(filterDataTable(searchText)));
} else {
setDataTable(sortBy(transformDataTable(filterDataTable("")), "name"));
}
}
}, [loading, policies]);
const transformDataTable = (d: Policy[]): PolicyDataTable[] => {
return d.map((policy) => {
const sourceLabel = getSourceDestinationLabel(
@@ -169,14 +189,32 @@ export const AccessControl = () => {
setShowTutorial(false);
} else {
setShowTutorial(isShowTutorial(policies));
setDataTable(sortBy(transformDataTable(filterDataTable()), "name"));
}
}, [policies]);
useEffect(() => {
setDataTable(transformDataTable(filterDataTable()));
setDataTable(transformDataTable(filterDataTable("")));
}, [textToSearch, optionAllEnable]);
const filterDataTable = (searchText: string): Policy[] => {
const t = searchText
? searchText.toLowerCase().trim()
: textToSearch.toLowerCase().trim();
let f: Policy[] = filter(
policies,
(f: Policy) =>
f.name.toLowerCase().includes(t) ||
f.description.toLowerCase().includes(t) ||
t === ""
) as Policy[];
if (optionAllEnable == "enabled") {
f = filter(f, (f: Policy) => f.enabled);
} else if (optionAllEnable == "disabled") {
f = filter(f, (f: Policy) => !f.enabled);
}
return f;
};
const styleNotification = { marginTop: 85 };
const saveKey = "saving";
@@ -243,15 +281,17 @@ export const AccessControl = () => {
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
setTextToSearch(e.target.value);
storeFilterState("accessControlFilter", "search", e.target.value);
};
const searchDataTable = () => {
const data = filterDataTable();
setDataTable(transformDataTable(data));
};
// const searchDataTable = () => {
// const data = filterDataTable();
// setDataTable(transformDataTable(data));
// };
const onChangeAllEnabled = ({ target: { value } }: RadioChangeEvent) => {
setOptionAllEnable(value);
storeFilterState("accessControlFilter", "quickFilter", value);
};
const showConfirmDelete = (record: PolicyDataTable) => {
@@ -310,23 +350,6 @@ export const AccessControl = () => {
});
};
const filterDataTable = (): Policy[] => {
const t = textToSearch.toLowerCase().trim();
let f: Policy[] = filter(
policies,
(f: Policy) =>
f.name.toLowerCase().includes(t) ||
f.description.toLowerCase().includes(t) ||
t === ""
) as Policy[];
if (optionAllEnable == "enabled") {
f = filter(f, (f: Policy) => f.enabled);
} else if (optionAllEnable == "disabled") {
f = filter(f, (f: Policy) => !f.enabled);
}
return f;
};
const onClickAddNewPolicy = () => {
dispatch(policyActions.setSetupNewPolicyVisible(true));
dispatch(
@@ -595,7 +618,7 @@ export const AccessControl = () => {
<Input
allowClear
value={textToSearch}
onPressEnter={searchDataTable}
// onPressEnter={searchDataTable}
placeholder="Search by name and description..."
onChange={onChangeTextToSearch}
/>
@@ -621,7 +644,9 @@ export const AccessControl = () => {
<Select
value={pageSize.toString()}
options={pageSizeOptions}
onChange={onChangePageSize}
onChange={(value) => {
onChangePageSize(value, "accessControlFilter");
}}
className="select-rows-per-page-en"
disabled={showTutorial}
/>
+43 -28
View File
@@ -24,6 +24,7 @@ import { capitalize, formatDateTime } from "../utils/common";
import { User } from "../store/user/types";
import { usePageSizeHelpers } from "../utils/pageSize";
import { QuestionCircleFilled } from "@ant-design/icons";
import { storeFilterState, getFilterState } from "../utils/filterState";
const { Title, Paragraph, Text } = Typography;
const { Column } = Table;
@@ -57,16 +58,18 @@ export const Activity = () => {
})
);
}, []);
useEffect(() => {
setDataTable(transformDataTable(events));
}, [events]);
// useEffect(() => {
// setDataTable(transformDataTable(events));
// }, [events]);
useEffect(() => {
setDataTable(transformDataTable(filterDataTable()));
setDataTable(transformDataTable(filterDataTable("")));
}, [textToSearch]);
const filterDataTable = (): Event[] => {
const t = textToSearch.toLowerCase().trim();
const filterDataTable = (searchText: string): Event[] => {
const t = searchText
? searchText.toLowerCase().trim()
: textToSearch.toLowerCase().trim();
let usrsMatch: User[] = filter(
users,
(u: User) =>
@@ -82,16 +85,33 @@ export const Activity = () => {
return f;
};
useEffect(() => {
if (!loading && events) {
const searchText = getFilterState("activityFilter", "search");
if (searchText) setTextToSearch(searchText);
const pageSize = getFilterState("activityFilter", "pageSize");
if (pageSize) onChangePageSize(pageSize, "activityFilter");
if (searchText || pageSize) {
setDataTable(transformDataTable(filterDataTable(searchText)));
} else {
setDataTable(transformDataTable(events));
}
}
}, [loading, events]);
const onChangeTextToSearch = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
setTextToSearch(e.target.value);
storeFilterState("activityFilter", "search", e.target.value);
};
const searchDataTable = () => {
const data = filterDataTable();
setDataTable(transformDataTable(data));
};
// const searchDataTable = () => {
// const data = filterDataTable();
// setDataTable(transformDataTable(data));
// };
const getActivityRow = (objectType: string, name: string, text: string) => {
return (
@@ -256,6 +276,7 @@ export const Activity = () => {
);
case "group.add":
case "group.update":
case "group.delete":
return renderMultiRowSpan(event.meta.name, "Group");
case "nameserver.group.add":
case "nameserver.group.update":
@@ -355,7 +376,14 @@ export const Activity = () => {
<Col span={24}>
<Title className="page-heading">Activity</Title>
<Paragraph type="secondary">
Here you can see all the account and network activity events
Here you can see all the account and network activity events.{" "}
<a
rel="noreferrer"
target="_blank"
href="https://docs.netbird.io/how-to/monitor-system-and-network-activity"
>
Learn more
</a>
</Paragraph>
<Space
direction="vertical"
@@ -367,7 +395,7 @@ export const Activity = () => {
<Input
allowClear
value={textToSearch}
onPressEnter={searchDataTable}
// onPressEnter={searchDataTable}
placeholder="Search..."
onChange={onChangeTextToSearch}
/>
@@ -377,25 +405,13 @@ export const Activity = () => {
<Select
value={pageSize.toString()}
options={pageSizeOptions}
onChange={onChangePageSize}
onChange={(value) => {
onChangePageSize(value, "activityFilter");
}}
className="select-rows-per-page-en"
/>
</Space>
</Col>
<Col xs={24} sm={24} md={5} lg={5} xl={5} xxl={5} span={5}>
<Row justify="end">
<Col>
<Button
icon={<QuestionCircleFilled />}
type="link"
target="_blank"
href="https://docs.netbird.io/how-to/monitor-system-and-network-activity"
>
Learn more about activity tracking
</Button>
</Col>
</Row>
</Col>
</Row>
{failed && (
<Alert
@@ -419,7 +435,6 @@ export const Activity = () => {
scroll={{ x: true }}
loading={tableSpin(loading)}
dataSource={dataTable}
size="small"
>
<Column
title="Timestamp"
+225 -160
View File
@@ -1,176 +1,241 @@
import React, {useEffect, useState} from 'react';
import {useDispatch, useSelector} from "react-redux";
import {RootState} from "typesafe-actions";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "typesafe-actions";
import {
Button,
Card,
Col,
Form,
message,
Select,
Space,
Typography,
Button,
Card,
Col,
Form,
message,
Row,
Select,
Space,
Typography,
} from "antd";
import {useGetTokenSilently} from "../utils/token";
import {useGetGroupTagHelpers} from "../utils/groups";
import {actions as dnsSettingsActions} from '../store/dns-settings';
import {DNSSettings, DNSSettingsToSave} from "../store/dns-settings/types";
import {actions as nsGroupActions} from "../store/nameservers";
import { useGetTokenSilently } from "../utils/token";
import { useGetGroupTagHelpers } from "../utils/groups";
import { actions as dnsSettingsActions } from "../store/dns-settings";
import { DNSSettings, DNSSettingsToSave } from "../store/dns-settings/types";
import { actions as nsGroupActions } from "../store/nameservers";
const {Paragraph} = Typography;
const styleNotification = {marginTop: 85}
const { Paragraph } = Typography;
const styleNotification = { marginTop: 85 };
export const DNSSettingsForm = () => {
const {getTokenSilently} = useGetTokenSilently()
const dispatch = useDispatch()
const { getTokenSilently } = useGetTokenSilently();
const dispatch = useDispatch();
const {
blueTagRender,
handleChangeTags,
dropDownRender,
optionRender,
tagGroups,
getExistingAndToCreateGroupsLists,
getGroupNamesFromIDs,
selectValidatorEmptyStrings
} = useGetGroupTagHelpers()
const {
blueTagRender,
handleChangeTags,
dropDownRender,
optionRender,
tagGroups,
getExistingAndToCreateGroupsLists,
getGroupNamesFromIDs,
selectValidatorEmptyStrings,
} = useGetGroupTagHelpers();
const dnsSettings = useSelector((state: RootState) => state.dnsSettings.dnsSettings)
const dnsSettingsData = useSelector((state: RootState) => state.dnsSettings.data)
const savedDNSSettings = useSelector((state: RootState) => state.dnsSettings.savedDNSSettings)
const loading = useSelector((state: RootState) => state.dnsSettings.loading);
const dnsSettings = useSelector(
(state: RootState) => state.dnsSettings.dnsSettings
);
const dnsSettingsData = useSelector(
(state: RootState) => state.dnsSettings.data
);
const savedDNSSettings = useSelector(
(state: RootState) => state.dnsSettings.savedDNSSettings
);
const loading = useSelector((state: RootState) => state.dnsSettings.loading);
const [form] = Form.useForm();
const [form] = Form.useForm()
useEffect(() => {
dispatch(
dnsSettingsActions.getDNSSettings.request({
getAccessTokenSilently: getTokenSilently,
payload: null,
})
);
}, []);
useEffect(() => {
dispatch(dnsSettingsActions.getDNSSettings.request({
useEffect(() => {
if (!dnsSettingsData) return;
dispatch(
dnsSettingsActions.setDNSSettings({
disabled_management_groups: getGroupNamesFromIDs(
dnsSettingsData.disabled_management_groups
),
})
);
}, [dnsSettingsData]);
useEffect(() => {
form.setFieldsValue(dnsSettings);
}, [dnsSettings]);
const createKey = "saving";
useEffect(() => {
if (savedDNSSettings.loading) {
message.loading({
content: "Saving...",
key: createKey,
duration: 0,
style: styleNotification,
});
} else if (savedDNSSettings.success) {
message.success({
content: "DNS settings has been successfully saved.",
key: createKey,
duration: 2,
style: styleNotification,
});
dispatch(
dnsSettingsActions.setSavedDNSSettings({
...savedDNSSettings,
success: false,
})
);
dispatch(dnsSettingsActions.resetSavedDNSSettings(null));
} else if (savedDNSSettings.error) {
let errorMsg = "Failed to update DNS settings";
switch (savedDNSSettings.error.statusCode) {
case 403:
errorMsg =
"Failed to update DNS settings. You might not have enough permissions.";
break;
default:
errorMsg = savedDNSSettings.error.data.message
? savedDNSSettings.error.data.message
: errorMsg;
break;
}
message.error({
content: errorMsg,
key: createKey,
duration: 5,
style: styleNotification,
});
dispatch(
dnsSettingsActions.setSavedDNSSettings({
...savedDNSSettings,
error: null,
})
);
dispatch(nsGroupActions.resetSavedNameServerGroup(null));
}
}, [savedDNSSettings]);
const handleFormSubmit = () => {
form
.validateFields()
.then((values) => {
let dnsSettingsToSave = createDNSSettingsToSave(values);
dispatch(
dnsSettingsActions.saveDNSSettings.request({
getAccessTokenSilently: getTokenSilently,
payload: null
}));
}, []);
useEffect(() => {
if (!dnsSettingsData) return
dispatch(dnsSettingsActions.setDNSSettings({
disabled_management_groups: getGroupNamesFromIDs(dnsSettingsData.disabled_management_groups),
}))
}, [dnsSettingsData])
useEffect(() => {
form.setFieldsValue(dnsSettings)
}, [dnsSettings])
const createKey = 'saving';
useEffect(() => {
if (savedDNSSettings.loading) {
message.loading({content: 'Saving...', key: createKey, duration: 0, style: styleNotification});
} else if (savedDNSSettings.success) {
message.success({
content: 'DNS settings has been successfully saved.',
key: createKey,
duration: 2,
style: styleNotification
});
dispatch(dnsSettingsActions.setSavedDNSSettings({...savedDNSSettings, success: false}));
dispatch(dnsSettingsActions.resetSavedDNSSettings(null))
} else if (savedDNSSettings.error) {
let errorMsg = "Failed to update DNS settings"
switch (savedDNSSettings.error.statusCode) {
case 403:
errorMsg = "Failed to update DNS settings. You might not have enough permissions."
break
default:
errorMsg = savedDNSSettings.error.data.message ? savedDNSSettings.error.data.message : errorMsg
break
}
message.error({
content: errorMsg,
key: createKey,
duration: 5,
style: styleNotification
});
dispatch(dnsSettingsActions.setSavedDNSSettings({...savedDNSSettings, error: null}));
dispatch(nsGroupActions.resetSavedNameServerGroup(null))
payload: dnsSettingsToSave,
})
);
})
.catch((errorInfo) => {
let msg = "please check the fields and try again";
if (errorInfo.errorFields) {
msg = errorInfo.errorFields[0].errors[0];
}
}, [savedDNSSettings])
message.error({
content: msg,
duration: 1,
});
});
};
const handleFormSubmit = () => {
form.validateFields()
.then((values) => {
let dnsSettingsToSave = createDNSSettingsToSave(values)
dispatch(dnsSettingsActions.saveDNSSettings.request({
getAccessTokenSilently:getTokenSilently,
payload: dnsSettingsToSave
}))
})
.catch((errorInfo) => {
let msg = "please check the fields and try again"
if (errorInfo.errorFields) {
msg = errorInfo.errorFields[0].errors[0]
}
message.error({
content: msg,
duration: 1,
});
});
}
const createDNSSettingsToSave = (values: DNSSettings): DNSSettingsToSave => {
let [existingGroups, newGroups] = getExistingAndToCreateGroupsLists(
values.disabled_management_groups
);
return {
disabled_management_groups: existingGroups,
groupsToCreate: newGroups,
} as DNSSettingsToSave;
};
const createDNSSettingsToSave = (values: DNSSettings): DNSSettingsToSave => {
let [existingGroups, newGroups] = getExistingAndToCreateGroupsLists(values.disabled_management_groups)
return {
disabled_management_groups: existingGroups,
groupsToCreate: newGroups
} as DNSSettingsToSave
}
return (
<>
<Paragraph>Manage your account's DNS settings</Paragraph>
<Col>
<Form
name="basic"
autoComplete="off"
form={form}
onFinish={handleFormSubmit}
>
<Space direction={"vertical"}
style={{ display: 'flex' }}>
<Card
title="DNS Management"
loading={loading}
>
<Form.Item
label="Disable DNS management for these groups"
name="disabled_management_groups"
tooltip="Peers in these groups will have their DNS management disabled and require manual configuration for domain name resolution"
rules={[{validator: selectValidatorEmptyStrings}]}
>
<Select mode="tags"
style={{width: '100%'}}
tagRender={blueTagRender}
onChange={handleChangeTags}
dropdownRender={dropDownRender}
>
{
tagGroups.map(m =>
<Select.Option key={m}>{optionRender(m)}</Select.Option>
)
}
</Select>
</Form.Item>
</Card>
<Form.Item style={{ textAlign:'center' }} >
<Button type="primary" htmlType="submit">
Save
</Button>
</Form.Item>
</Space>
</Form>
return (
<>
<Paragraph>Manage your account's DNS settings</Paragraph>
<Col>
<Form
name="basic"
autoComplete="off"
form={form}
onFinish={handleFormSubmit}
>
<Space direction={"vertical"} style={{ display: "flex" }}>
<Card loading={loading}>
<div
style={{
color: "rgba(0, 0, 0, 0.88)",
fontWeight: "500",
fontSize: "22px",
marginBottom: "20px",
}}
>
DNS Management
</div>
<Row>
<Col span={10}>
<label
style={{
color: "rgba(0, 0, 0, 0.88)",
fontSize: "14px",
fontWeight: "500",
}}
>
Disable DNS management for these groups
</label>
<Paragraph
type={"secondary"}
style={{
marginTop: "-2",
fontWeight: "400",
marginBottom: "5px",
}}
>
Peers in these groups will require manual domain name
resolution
</Paragraph>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
name="disabled_management_groups"
rules={[{ validator: selectValidatorEmptyStrings }]}
>
<Select
mode="tags"
style={{ width: "100%" }}
tagRender={blueTagRender}
onChange={handleChangeTags}
dropdownRender={dropDownRender}
>
{tagGroups.map((m) => (
<Select.Option key={m}>{optionRender(m)}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item style={{ marginBottom: "0" }}>
<Button type="primary" htmlType="submit">
Save
</Button>
</Form.Item>
</Col>
</Row>
</Card>
</Space>
</Form>
</Col>
</>
);
};
</>
)
}
export default DNSSettingsForm;
export default DNSSettingsForm;
Loaded 20 of 27 files, more files were not shown because too many files have changed in this diff. Show more