Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a924227805 | ||
|
|
e4e75632c5 | ||
|
|
ddb7c24832 | ||
|
|
2144d3f8c0 | ||
|
|
4a824dec81 | ||
|
|
b35fee1be8 | ||
|
|
1b167af12b | ||
|
|
f2962e34ae | ||
|
|
386db5029a | ||
|
|
0e6e54a124 | ||
|
|
c666cb3879 | ||
|
|
4039517683 | ||
|
|
00fc7b8038 | ||
|
|
81d283ec8d | ||
|
|
105100e349 | ||
|
|
4598690dbf | ||
|
|
f68341c315 | ||
|
|
e8a8cea909 | ||
|
|
bf53f107e3 | ||
|
|
00de974528 | ||
|
|
0445398e94 | ||
|
|
272e2ba955 | ||
|
|
0a2adc2d92 | ||
|
|
7008fc1770 | ||
|
|
041a261540 | ||
|
|
1008d819f7 | ||
|
|
fb84a79a04 | ||
|
|
fcd6786149 | ||
|
|
45bfdbdce0 | ||
|
|
1537c2141f | ||
|
|
ea968ebf3c | ||
|
|
3ba1a52644 | ||
|
|
a015cc6706 | ||
|
|
5bad362793 | ||
|
|
5520756edd | ||
|
|
ba954a1d6e | ||
|
|
2944ff298c | ||
|
|
80d121e87a | ||
|
|
8a7b852974 | ||
|
|
ed8352d857 | ||
|
|
41f64ca9fe | ||
|
|
738e49dc92 | ||
|
|
68a16257c6 | ||
|
|
5dcbae55f4 | ||
|
|
e0d963256c | ||
|
|
2bff4bbd15 | ||
|
|
a0eba89f34 | ||
|
|
4e78de9da2 | ||
|
|
85f00eb7e8 | ||
|
|
8e13855b66 | ||
|
|
06f49e24c2 | ||
|
|
e598ae45f7 | ||
|
|
ad7f469e06 | ||
|
|
c8d3e3b70c | ||
|
|
cb57ff5cc2 | ||
|
|
72f070fbcb | ||
|
|
fb0a86d37c | ||
|
|
36402dfefa | ||
|
|
c61874dbdd | ||
|
|
20848f28d5 | ||
|
|
5d23966f00 | ||
|
|
294cc66e4a | ||
|
|
0fd2e7032a | ||
|
|
340b85043e | ||
|
|
1821ae3c2b | ||
|
|
c536cb2afa | ||
|
|
3f79b4c2f6 | ||
|
|
137ba9185e | ||
|
|
2f6a0913dc | ||
|
|
2c7336d440 | ||
|
|
5a022ff3f6 | ||
|
|
fe4855500e | ||
|
|
ce8f5cbe0c | ||
|
|
7a90a6f9f4 | ||
|
|
b6bebe33fe | ||
|
|
9cf8072c1e | ||
|
|
0ca00ca6a1 | ||
|
|
619c5242db | ||
|
|
ff07854590 | ||
|
|
ba99989c66 | ||
|
|
3c75933cf2 | ||
|
|
ea9ef7afd3 | ||
|
|
f5e633a781 | ||
|
|
90b94816dd | ||
|
|
11dcaef3ff | ||
|
|
3f3e7f71ec | ||
|
|
b6070572cf | ||
|
|
e818a02a2a | ||
|
|
d8c8e222c8 | ||
|
|
f12b9715bc | ||
|
|
31c65d3e0b | ||
|
|
fcd6741cf9 | ||
|
|
d663b9230f | ||
|
|
5f2d61ad7a | ||
|
|
ec80a2dc0b | ||
|
|
2cece3de59 | ||
|
|
79eb580802 | ||
|
|
b93e3327a7 | ||
|
|
f01030a47a | ||
|
|
3cbd907c09 | ||
|
|
8fae69b7a4 | ||
|
|
e45dd4240e | ||
|
|
16a8552e6c | ||
|
|
c953ec6152 | ||
|
|
a433f10240 | ||
|
|
b73b97b5e9 | ||
|
|
0607e0b228 | ||
|
|
3bd4f67ec7 | ||
|
|
845d5a5d51 | ||
|
|
0101da731f | ||
|
|
68592acd39 | ||
|
|
b86fc5edb3 | ||
|
|
32b54ddf11 | ||
|
|
f8a0741e6c | ||
|
|
652d231771 | ||
|
|
1c3c5f4fec | ||
|
|
e7006a4a44 | ||
|
|
0f81d54f25 | ||
|
|
f3121c24c6 | ||
|
|
7abd0f2cd4 | ||
|
|
46b342005a | ||
|
|
4e0349bd58 | ||
|
|
30a569233b | ||
|
|
44ba6b4d0f | ||
|
|
9065070eb2 | ||
|
|
fd951bfdd5 | ||
|
|
27d613b594 | ||
|
|
ba757b9aa4 | ||
|
|
c445463c0c | ||
|
|
4693177e4b | ||
|
|
30b135eba3 | ||
|
|
bda48e07f1 | ||
|
|
7c8ab64e34 | ||
|
|
ec7855bd02 | ||
|
|
d401eefd6b | ||
|
|
0ad759a384 | ||
|
|
d3d20b29c3 | ||
|
|
fbb570c0d5 | ||
|
|
2318082bb8 | ||
|
|
05dd5f7de2 | ||
|
|
841251d09e | ||
|
|
a4dd8f70f0 | ||
|
|
9d0d1329b6 | ||
|
|
7a929777b4 | ||
|
|
ce3ec99c9f | ||
|
|
4f7847275e | ||
|
|
9a5ddb22b3 | ||
|
|
b1322cbec3 | ||
|
|
637bc84136 | ||
|
|
3147f02b6a | ||
|
|
dabff74946 | ||
|
|
de99577b9d | ||
|
|
1846432601 | ||
|
|
6f307dc822 | ||
|
|
f43210e29e | ||
|
|
50b9be4eca | ||
|
|
1a38222974 | ||
|
|
cb9cd0a43c | ||
|
|
c2e2ae8dbd | ||
|
|
df790a92be | ||
|
|
e1f9242b34 | ||
|
|
9d2a52e639 | ||
|
|
5cbca9457e | ||
|
|
25c66cff43 | ||
|
|
75a2e0deee | ||
|
|
b857137f1a | ||
|
|
40141cdcb0 | ||
|
|
c5c1d6903e | ||
|
|
f15c8188b9 | ||
|
|
8f971cfb02 | ||
|
|
32c811ec5a | ||
|
|
4febc56c30 | ||
|
|
f22ee4a68b | ||
|
|
87bec0399f | ||
|
|
1f29255dd1 | ||
|
|
4a11638182 | ||
|
|
10743372f8 | ||
|
|
d4b11bbb76 | ||
|
|
ced2417c98 | ||
|
|
27415aeca6 | ||
|
|
9bd2e336a6 | ||
|
|
d5778ec173 | ||
|
|
74e80f086a | ||
|
|
b1c6191fa1 | ||
|
|
8e0245c844 | ||
|
|
613fbf8c39 | ||
|
|
1788cda5c2 | ||
|
|
155adf549e | ||
|
|
5463542532 | ||
|
|
f5a25bc0e5 | ||
|
|
993339d0d1 | ||
|
|
bc4fe897cf | ||
|
|
c773bdaabd | ||
|
|
9f9a2be1d8 | ||
|
|
1e4b0c2f20 | ||
|
|
56025f6d56 | ||
|
|
5188b90f32 | ||
|
|
7178f537a8 | ||
|
|
45ac589975 | ||
|
|
9925e10ffc | ||
|
|
e3fde8d564 | ||
|
|
8aee01e008 | ||
|
|
cd203ff067 | ||
|
|
254cb6d80f | ||
|
|
9b3ad54d0a | ||
|
|
4ae3bb5780 | ||
|
|
b8aa1ef765 | ||
|
|
5e5daef49a | ||
|
|
88c478c533 | ||
|
|
1ecec115e4 | ||
|
|
8ff597eedb | ||
|
|
69f74488e5 | ||
|
|
ded9a27f42 | ||
|
|
43284ae625 | ||
|
|
f7b1ef9741 | ||
|
|
a6d445818f | ||
|
|
122a84b9e2 | ||
|
|
9716e64c93 | ||
|
|
eb8cf1b6da | ||
|
|
c633a9ad8d | ||
|
|
923eda1307 | ||
|
|
997342a31c |
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
release_notes: false
|
||||||
@@ -7,7 +7,7 @@ import { URLSearchParams } from "url";
|
|||||||
const API_TOKEN = process.env.POEDITOR_API;
|
const API_TOKEN = process.env.POEDITOR_API;
|
||||||
const PROJECT_ID = process.env.POEDITOR_PROJECT_ID;
|
const PROJECT_ID = process.env.POEDITOR_PROJECT_ID;
|
||||||
const LANGUAGES = (
|
const LANGUAGES = (
|
||||||
process.env.LANGUAGES || "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr,ja"
|
process.env.LANGUAGES || "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr,ja,zh-cn,th"
|
||||||
).split(",");
|
).split(",");
|
||||||
const EXPORT_FORMAT = process.env.EXPORT_FORMAT || "key_value_json";
|
const EXPORT_FORMAT = process.env.EXPORT_FORMAT || "key_value_json";
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install client dependencies
|
- name: Install client dependencies
|
||||||
working-directory: client
|
working-directory: client
|
||||||
run: npm ci
|
run: npm install
|
||||||
|
|
||||||
- name: Check client formatting
|
- name: Check client formatting
|
||||||
working-directory: client
|
working-directory: client
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
working-directory: server
|
working-directory: server
|
||||||
run: npm ci
|
run: npm install
|
||||||
|
|
||||||
- name: Check server formatting
|
- name: Check server formatting
|
||||||
working-directory: server
|
working-directory: server
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ on:
|
|||||||
languages:
|
languages:
|
||||||
description: "Languages to synchronize (comma separated, e.g.: tr,en,es)"
|
description: "Languages to synchronize (comma separated, e.g.: tr,en,es)"
|
||||||
required: false
|
required: false
|
||||||
default: "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr,ja"
|
default: "ar,zh-tw,cs,en,fi,fr,de,pt-br,ru,es,tr,ja,zh-cn,th"
|
||||||
format:
|
format:
|
||||||
description: "Export format (key_value_json or json)"
|
description: "Export format (key_value_json or json)"
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
.vscode
|
||||||
@@ -52,7 +52,7 @@ Usage instructions can be found [here](https://docs.checkmate.so/checkmate-2.1).
|
|||||||
|
|
||||||
See installation instructions in [Checkmate documentation portal](https://docs.checkmate.so/checkmate-2.1/users-guide/quickstart).
|
See installation instructions in [Checkmate documentation portal](https://docs.checkmate.so/checkmate-2.1/users-guide/quickstart).
|
||||||
|
|
||||||
Alternatively, you can also use [Coolify](https://coolify.io/), [Elestio](https://elest.io/open-source/checkmate), [K8s](./charts/helm/checkmate/INSTALLATION.md) or [Pikapods](https://www.pikapods.com/) to quickly spin off a Checkmate instance. If you would like to monitor your server infrastructure, you'll need [Capture agent](https://github.com/bluewave-labs/capture). Capture repository also contains the installation instructions.
|
Alternatively, you can also use [Coolify](https://coolify.io/), [Elestio](https://elest.io/open-source/checkmate), [K8s](./charts/helm/checkmate/INSTALLATION.md), [Sive Host](https://sive.host) (South Africa) or [Pikapods](https://www.pikapods.com/) to quickly spin off a Checkmate instance. If you would like to monitor your server infrastructure, you'll need [Capture agent](https://github.com/bluewave-labs/capture). Capture repository also contains the installation instructions.
|
||||||
|
|
||||||
### Using a Custom CA
|
### Using a Custom CA
|
||||||
|
|
||||||
|
|||||||
Generated
+20
-627
@@ -21,7 +21,7 @@
|
|||||||
"dayjs": "1.11.13",
|
"dayjs": "1.11.13",
|
||||||
"flag-icons": "7.3.2",
|
"flag-icons": "7.3.2",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"i18next": "^24.2.2",
|
"i18next": "25.4.2",
|
||||||
"joi": "17.13.3",
|
"joi": "17.13.3",
|
||||||
"mui-color-input": "^6.0.0",
|
"mui-color-input": "^6.0.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
@@ -45,10 +45,7 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.6",
|
"eslint-plugin-react-refresh": "^0.4.6",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"vite": "6.3.5"
|
"vite": "6.3.6"
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.41.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
@@ -283,9 +280,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.27.1",
|
"version": "7.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz",
|
||||||
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
|
"integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -491,262 +488,6 @@
|
|||||||
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
|
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
|
|
||||||
"cpu": [
|
|
||||||
"ppc64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"aix"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/android-arm": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/android-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/android-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/darwin-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/darwin-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/freebsd-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/freebsd-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-arm": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-ia32": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-loong64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
|
|
||||||
"cpu": [
|
|
||||||
"loong64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-mips64el": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
|
|
||||||
"cpu": [
|
|
||||||
"mips64el"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-ppc64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
|
|
||||||
"cpu": [
|
|
||||||
"ppc64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-riscv64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
|
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-s390x": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
|
|
||||||
"cpu": [
|
|
||||||
"s390x"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/linux-x64": {
|
"node_modules/@esbuild/linux-x64": {
|
||||||
"version": "0.25.5",
|
"version": "0.25.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
|
||||||
@@ -763,134 +504,6 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"netbsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/netbsd-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"netbsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/openbsd-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"openbsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/openbsd-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"openbsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/sunos-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"sunos"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/win32-arm64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/win32-ia32": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/win32-x64": {
|
|
||||||
"version": "0.25.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
|
|
||||||
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
|
||||||
@@ -2063,123 +1676,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.41.0",
|
"version": "4.41.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz",
|
||||||
@@ -2193,71 +1689,6 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==",
|
|
||||||
"cpu": [
|
|
||||||
"loong64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==",
|
|
||||||
"cpu": [
|
|
||||||
"ppc64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==",
|
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==",
|
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==",
|
|
||||||
"cpu": [
|
|
||||||
"s390x"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.41.0",
|
"version": "4.41.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz",
|
||||||
@@ -2284,45 +1715,6 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@sideway/address": {
|
"node_modules/@sideway/address": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
|
||||||
@@ -3030,13 +2422,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.9.0",
|
"version": "1.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||||
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
|
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.4",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4342,14 +3734,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.12"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4690,9 +4083,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/i18next": {
|
"node_modules/i18next": {
|
||||||
"version": "24.2.3",
|
"version": "25.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.4.2.tgz",
|
||||||
"integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==",
|
"integrity": "sha512-gD4T25a6ovNXsfXY1TwHXXXLnD/K2t99jyYMCSimSCBnBRJVQr5j+VAaU83RJCPzrTGhVQ6dqIga66xO2rtd5g==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -4709,7 +4102,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.26.10"
|
"@babel/runtime": "^7.27.6"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
@@ -6996,9 +6389,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.3.5",
|
"version": "6.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz",
|
||||||
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
|
"integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
|
|||||||
+2
-5
@@ -26,7 +26,7 @@
|
|||||||
"dayjs": "1.11.13",
|
"dayjs": "1.11.13",
|
||||||
"flag-icons": "7.3.2",
|
"flag-icons": "7.3.2",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"i18next": "^24.2.2",
|
"i18next": "25.4.2",
|
||||||
"joi": "17.13.3",
|
"joi": "17.13.3",
|
||||||
"mui-color-input": "^6.0.0",
|
"mui-color-input": "^6.0.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
@@ -58,9 +58,6 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.6",
|
"eslint-plugin-react-refresh": "^0.4.6",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"vite": "6.3.5"
|
"vite": "6.3.6"
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.41.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import { Box, Stack, Tooltip, Typography } from "@mui/material";
|
import { Box, Stack, Tooltip, Typography } from "@mui/material";
|
||||||
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
import { formatDateWithTz } from "../../../Utils/timeUtils";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState, forwardRef } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
@@ -17,26 +17,32 @@ import PropTypes from "prop-types";
|
|||||||
* @returns {JSX.Element} The Bar component.
|
* @returns {JSX.Element} The Bar component.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Bar = ({ width, height, backgroundColor, borderRadius, children }) => {
|
const Bar = forwardRef(
|
||||||
const theme = useTheme();
|
({ width, height, backgroundColor, borderRadius, children, ...otherProps }, ref) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
position="relative"
|
ref={ref}
|
||||||
width={width}
|
position="relative"
|
||||||
height={height}
|
width={width}
|
||||||
backgroundColor={backgroundColor}
|
height={height}
|
||||||
sx={{
|
backgroundColor={backgroundColor}
|
||||||
borderRadius: borderRadius || theme.spacing(1.5),
|
sx={{
|
||||||
}}
|
borderRadius: borderRadius || theme.spacing(1.5),
|
||||||
>
|
}}
|
||||||
{children}
|
{...otherProps}
|
||||||
</Box>
|
>
|
||||||
);
|
{children}
|
||||||
};
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Bar.displayName = "Bar";
|
||||||
|
|
||||||
Bar.propTypes = {
|
Bar.propTypes = {
|
||||||
width: PropTypes.string.isRequired,
|
width: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||||
height: PropTypes.string.isRequired,
|
height: PropTypes.string.isRequired,
|
||||||
backgroundColor: PropTypes.string.isRequired,
|
backgroundColor: PropTypes.string.isRequired,
|
||||||
borderRadius: PropTypes.string,
|
borderRadius: PropTypes.string,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export const tooltipDateFormatLookup = (dateRange) => {
|
export const tooltipDateFormatLookup = (dateRange) => {
|
||||||
const dateFormatLookup = {
|
const dateFormatLookup = {
|
||||||
|
recent: "ddd. MMMM D, YYYY, hh:mm A",
|
||||||
day: "ddd. MMMM D, YYYY, hh:mm A",
|
day: "ddd. MMMM D, YYYY, hh:mm A",
|
||||||
week: "ddd. MMMM D, YYYY, hh:mm A",
|
week: "ddd. MMMM D, YYYY, hh:mm A",
|
||||||
month: "ddd. MMMM D, YYYY",
|
month: "ddd. MMMM D, YYYY",
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const Check = ({ text, noHighlightText, variant = "info", outlined = false }) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
Check.propTypes = {
|
Check.propTypes = {
|
||||||
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
|
text: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
||||||
noHighlightText: PropTypes.string,
|
noHighlightText: PropTypes.string,
|
||||||
variant: PropTypes.oneOf(["info", "error", "success"]),
|
variant: PropTypes.oneOf(["info", "error", "success"]),
|
||||||
outlined: PropTypes.bool,
|
outlined: PropTypes.bool,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useId } from "react";
|
|||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { Modal, Stack, Typography } from "@mui/material";
|
import { Modal, Stack, Typography } from "@mui/material";
|
||||||
|
|
||||||
const GenericDialog = ({ title, description, open, onClose, theme, children }) => {
|
const GenericDialog = ({ title, description, open, onClose, theme, children, width }) => {
|
||||||
const titleId = useId();
|
const titleId = useId();
|
||||||
const descriptionId = useId();
|
const descriptionId = useId();
|
||||||
const ariaDescribedBy = description?.length > 0 ? descriptionId : "";
|
const ariaDescribedBy = description?.length > 0 ? descriptionId : "";
|
||||||
@@ -16,6 +16,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
|||||||
>
|
>
|
||||||
<Stack
|
<Stack
|
||||||
gap={theme.spacing(2)}
|
gap={theme.spacing(2)}
|
||||||
|
width={width}
|
||||||
sx={{
|
sx={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: "50%",
|
top: "50%",
|
||||||
@@ -39,6 +40,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
|||||||
fontSize={16}
|
fontSize={16}
|
||||||
color={theme.palette.primary.contrastText}
|
color={theme.palette.primary.contrastText}
|
||||||
fontWeight={600}
|
fontWeight={600}
|
||||||
|
marginBottom={theme.spacing(4)}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -46,6 +48,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
|||||||
<Typography
|
<Typography
|
||||||
id={descriptionId}
|
id={descriptionId}
|
||||||
color={theme.palette.primary.contrastTextTertiary}
|
color={theme.palette.primary.contrastTextTertiary}
|
||||||
|
marginBottom={theme.spacing(4)}
|
||||||
>
|
>
|
||||||
{description}
|
{description}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -64,6 +67,7 @@ GenericDialog.propTypes = {
|
|||||||
theme: PropTypes.object.isRequired,
|
theme: PropTypes.object.isRequired,
|
||||||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
|
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
|
||||||
.isRequired,
|
.isRequired,
|
||||||
|
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
|
||||||
};
|
};
|
||||||
|
|
||||||
export { GenericDialog };
|
export { GenericDialog };
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Background from "../../assets/Images/background-grid.svg?react";
|
import Background from "../../assets/Images/background-grid.svg?react";
|
||||||
import SkeletonDark from "../../assets/Images/create-placeholder-dark.svg?react";
|
|
||||||
import OutputAnimation from "../../assets/Animations/output.gif";
|
import OutputAnimation from "../../assets/Animations/output.gif";
|
||||||
import DarkmodeOutput from "../../assets/Animations/darkmodeOutput.gif";
|
import DarkmodeOutput from "../../assets/Animations/darkmodeOutput.gif";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
@@ -13,7 +12,7 @@ const FallbackBackground = () => {
|
|||||||
<Box
|
<Box
|
||||||
component="img"
|
component="img"
|
||||||
src={mode === "light" ? OutputAnimation : DarkmodeOutput}
|
src={mode === "light" ? OutputAnimation : DarkmodeOutput}
|
||||||
Background="transparent"
|
background="transparent"
|
||||||
alt="Loading animation"
|
alt="Loading animation"
|
||||||
sx={{
|
sx={{
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import GenericFallback from "../GenericFallback";
|
||||||
|
import Fallback from "../Fallback";
|
||||||
|
import { Typography } from "@mui/material";
|
||||||
|
import { useTheme } from "@emotion/react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useIsAdmin } from "../../Hooks/useIsAdmin";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
const PageStateWrapper = ({
|
||||||
|
networkError,
|
||||||
|
isLoading,
|
||||||
|
items,
|
||||||
|
type,
|
||||||
|
fallbackLink,
|
||||||
|
fallbackChildren,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const isAdmin = useIsAdmin();
|
||||||
|
const isEmpty = items === null || (Array.isArray(items) && items.length === 0);
|
||||||
|
const hasInitialized = items !== undefined && !(isLoading && isEmpty);
|
||||||
|
const showEmpty = !isLoading && isEmpty;
|
||||||
|
if (networkError) {
|
||||||
|
return (
|
||||||
|
<GenericFallback>
|
||||||
|
<Typography
|
||||||
|
variant="h1"
|
||||||
|
marginY={theme.spacing(4)}
|
||||||
|
color={theme.palette.primary.contrastTextTertiary}
|
||||||
|
>
|
||||||
|
{t("common.toasts.networkError")}
|
||||||
|
</Typography>
|
||||||
|
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
||||||
|
</GenericFallback>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!hasInitialized) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (showEmpty) {
|
||||||
|
return (
|
||||||
|
<Fallback
|
||||||
|
type={type}
|
||||||
|
title={t(`${type}.fallback.title`)}
|
||||||
|
checks={t(`${type}.fallback.checks`, { returnObjects: true })}
|
||||||
|
link={fallbackLink}
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
>
|
||||||
|
{fallbackChildren}
|
||||||
|
</Fallback>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
PageStateWrapper.propTypes = {
|
||||||
|
networkError: PropTypes.any,
|
||||||
|
isLoading: PropTypes.bool,
|
||||||
|
items: PropTypes.oneOfType([PropTypes.array, PropTypes.oneOf([null])]),
|
||||||
|
type: PropTypes.string,
|
||||||
|
fallbackLink: PropTypes.string,
|
||||||
|
fallbackChildren: PropTypes.node,
|
||||||
|
children: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PageStateWrapper;
|
||||||
@@ -74,7 +74,7 @@ const StarPrompt = ({ repoUrl = "https://github.com/bluewave-labs/checkmate" })
|
|||||||
<Typography
|
<Typography
|
||||||
variant="body1"
|
variant="body1"
|
||||||
sx={{
|
sx={{
|
||||||
color: theme.palette.text.secondary,
|
color: theme.palette.primary.contrastTextTertiary,
|
||||||
fontSize: "0.938rem",
|
fontSize: "0.938rem",
|
||||||
lineHeight: 1.5,
|
lineHeight: 1.5,
|
||||||
mb: 1,
|
mb: 1,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
TableHead,
|
TableHead,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import SkeletonLayout from "./skeleton";
|
import SkeletonLayout from "./skeleton";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
@@ -41,6 +42,7 @@ const DataTable = ({
|
|||||||
data = [],
|
data = [],
|
||||||
config = {
|
config = {
|
||||||
emptyView: "No data",
|
emptyView: "No data",
|
||||||
|
tooltipContent: null,
|
||||||
onRowClick: () => {},
|
onRowClick: () => {},
|
||||||
},
|
},
|
||||||
}) => {
|
}) => {
|
||||||
@@ -101,24 +103,54 @@ const DataTable = ({
|
|||||||
data.map((row) => {
|
data.map((row) => {
|
||||||
const key = row.id || row._id || Math.random();
|
const key = row.id || row._id || Math.random();
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<Tooltip
|
||||||
key={key}
|
key={key}
|
||||||
sx={config?.rowSX ?? {}}
|
followCursor
|
||||||
onClick={config?.onRowClick ? () => config.onRowClick(row) : null}
|
enterDelay={500}
|
||||||
|
enterNextDelay={500}
|
||||||
|
title={
|
||||||
|
typeof config.tooltipContent === "function"
|
||||||
|
? config.tooltipContent(row)
|
||||||
|
: config.tooltipContent
|
||||||
|
}
|
||||||
|
slotProps={{
|
||||||
|
tooltip: {
|
||||||
|
sx: {
|
||||||
|
background: "unset",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
popper: {
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: "offset",
|
||||||
|
options: {
|
||||||
|
offset: ({ popper }) => {
|
||||||
|
return [popper.width / 2 + 20, -popper.height / 8];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{headers.map((header, index) => {
|
<TableRow
|
||||||
return (
|
sx={config?.rowSX ?? {}}
|
||||||
<TableCell
|
onClick={config?.onRowClick ? () => config.onRowClick(row) : null}
|
||||||
align={index === 0 ? "left" : "center"}
|
>
|
||||||
key={header.id}
|
{headers.map((header, index) => {
|
||||||
onClick={header.onClick ? (e) => header.onClick(e, row) : null}
|
return (
|
||||||
sx={header.getCellSx ? header.getCellSx(row) : {}}
|
<TableCell
|
||||||
>
|
align={index === 0 ? "left" : "center"}
|
||||||
{header.render(row)}
|
key={header.id}
|
||||||
</TableCell>
|
onClick={header.onClick ? (e) => header.onClick(e, row) : null}
|
||||||
);
|
sx={header.getCellSx ? header.getCellSx(row) : {}}
|
||||||
})}
|
>
|
||||||
</TableRow>
|
{header.render(row)}
|
||||||
|
</TableCell>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -14,25 +14,25 @@ const useGetInviteToken = () => {
|
|||||||
const clearToken = () => {
|
const clearToken = () => {
|
||||||
setToken(undefined);
|
setToken(undefined);
|
||||||
};
|
};
|
||||||
|
const fetchToken = async (email, role) => {
|
||||||
|
const response = await networkService.requestInvitationToken({ email, role });
|
||||||
|
const token = response?.data?.data?.token;
|
||||||
|
if (typeof token === "undefined") {
|
||||||
|
throw new Error(t("inviteNoTokenFound"));
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
};
|
||||||
const getInviteToken = async ({ email, role }) => {
|
const getInviteToken = async ({ email, role }) => {
|
||||||
try {
|
try {
|
||||||
const response = await networkService.requestInvitationToken({
|
setIsLoading(true);
|
||||||
email,
|
const token = await fetchToken(email, role);
|
||||||
role,
|
|
||||||
});
|
|
||||||
const token = response?.data?.data?.token;
|
|
||||||
if (typeof token === "undefined") {
|
|
||||||
throw new Error(t("inviteNoTokenFound"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let inviteLink = token;
|
let inviteLink = token;
|
||||||
|
|
||||||
if (typeof CLIENT_HOST !== "undefined") {
|
if (typeof CLIENT_HOST !== "undefined") {
|
||||||
inviteLink = `${CLIENT_HOST}/register/${token}`;
|
inviteLink = `${CLIENT_HOST}/register/${token}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setToken(inviteLink);
|
setToken(inviteLink);
|
||||||
|
return token;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setError(error);
|
setError(error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -40,7 +40,26 @@ const useGetInviteToken = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return [getInviteToken, clearToken, isLoading, error, token];
|
const addTeamMember = async (formData, role) => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const token = await fetchToken(formData.email, role);
|
||||||
|
const toSubmit = {
|
||||||
|
...formData,
|
||||||
|
inviteToken: token,
|
||||||
|
};
|
||||||
|
delete toSubmit.confirm;
|
||||||
|
const responseRegister = await networkService.registerUser(toSubmit);
|
||||||
|
return responseRegister;
|
||||||
|
} catch (error) {
|
||||||
|
setError(error);
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return [getInviteToken, clearToken, isLoading, error, token, addTeamMember];
|
||||||
};
|
};
|
||||||
|
|
||||||
export { useGetInviteToken };
|
export { useGetInviteToken };
|
||||||
@@ -15,9 +15,6 @@ const useFetchLogs = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await networkService.getLogs();
|
const response = await networkService.getLogs();
|
||||||
setLogs(response.data.data);
|
setLogs(response.data.data);
|
||||||
createToast({
|
|
||||||
body: t("logsPage.toast.fetchLogsSuccess"),
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setError(error);
|
setError(error);
|
||||||
createToast({
|
createToast({
|
||||||
|
|||||||
@@ -369,6 +369,8 @@ const useUpdateMonitor = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const updatedFields = {
|
const updatedFields = {
|
||||||
name: monitor.name,
|
name: monitor.name,
|
||||||
|
statusWindowSize: monitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: monitor.statusWindowThreshold,
|
||||||
description: monitor.description,
|
description: monitor.description,
|
||||||
interval: monitor.interval,
|
interval: monitor.interval,
|
||||||
notifications: monitor.notifications,
|
notifications: monitor.notifications,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const useCreateNotification = () => {
|
|||||||
|
|
||||||
const useGetNotificationsByTeamId = (updateTrigger) => {
|
const useGetNotificationsByTeamId = (updateTrigger) => {
|
||||||
const [notifications, setNotifications] = useState([]);
|
const [notifications, setNotifications] = useState([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import Menu from "@mui/material/Menu";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import { useTheme } from "@emotion/react";
|
||||||
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import Proptypes from "prop-types";
|
||||||
|
|
||||||
|
const AddMemberMenu = ({ handleInviteOpen, handleIsRegisterOpen }) => {
|
||||||
|
const [anchorEl, setAnchorEl] = useState(null);
|
||||||
|
const open = Boolean(anchorEl);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const theme = useTheme();
|
||||||
|
const handleClick = (event) => {
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
};
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="accent"
|
||||||
|
endIcon={<ArrowDropDownIcon sx={{ color: theme.palette.secondary.light }} />}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
{t("teamPanel.addTeamMember.addMemberMenu")}
|
||||||
|
</Button>
|
||||||
|
<Menu
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
sx={{
|
||||||
|
"& .MuiPaper-root": {
|
||||||
|
minWidth: anchorEl?.offsetWidth || "auto",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
handleClose();
|
||||||
|
handleInviteOpen();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("teamPanel.inviteTeamMember")}
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
handleClose();
|
||||||
|
handleIsRegisterOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("teamPanel.register")}
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AddMemberMenu.propTypes = {
|
||||||
|
handleInviteOpen: Proptypes.func.isRequired,
|
||||||
|
handleIsRegisterOpen: Proptypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddMemberMenu;
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { newOrChangedCredentials } from "../../../../../Validation/validation";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
const useAddTeamMember = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [errors, setErrors] = useState({});
|
||||||
|
|
||||||
|
const clearErrors = () => setErrors({});
|
||||||
|
|
||||||
|
const validateFields = (name, value, formData) => {
|
||||||
|
const { error } = newOrChangedCredentials.validate(
|
||||||
|
{ [name]: value },
|
||||||
|
{ abortEarly: false, context: { password: formData.password } }
|
||||||
|
);
|
||||||
|
|
||||||
|
setErrors((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[name]: error?.details?.[0]?.message || "",
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateForm = (formData, role) => {
|
||||||
|
const { error } = newOrChangedCredentials.validate(formData, {
|
||||||
|
abortEarly: false,
|
||||||
|
context: { password: formData.password },
|
||||||
|
});
|
||||||
|
const formErrors = {};
|
||||||
|
if (error) {
|
||||||
|
for (const err of error.details) {
|
||||||
|
formErrors[err.path[0]] = err.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!role[0] || role.length === 0) {
|
||||||
|
formErrors.role = t(
|
||||||
|
"teamPanel.registerTeamMember.auth.common.inputs.role.errors.empty"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (Object.keys(formErrors).length > 0) {
|
||||||
|
setErrors(formErrors);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setErrors({});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { errors, setErrors, clearErrors, validateFields, validateForm };
|
||||||
|
};
|
||||||
|
export default useAddTeamMember;
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import { Button, Stack } from "@mui/material";
|
||||||
|
import { GenericDialog } from "../../../../Components/Dialog/genericDialog";
|
||||||
|
import TextInput from "../../../../Components/Inputs/TextInput";
|
||||||
|
import Select from "../../../../Components/Inputs/Select";
|
||||||
|
import { useGetInviteToken } from "../../../../Hooks/inviteHooks";
|
||||||
|
import { useTheme } from "@emotion/react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { createToast } from "../../../../Utils/toastUtils";
|
||||||
|
import { useState } from "react";
|
||||||
|
import PasswordTooltip from "../../../Auth/components/PasswordTooltip";
|
||||||
|
import useAddTeamMember from "./hooks/useAddTeamMember";
|
||||||
|
import usePasswordFeedback from "../../../Auth/hooks/usePasswordFeedback";
|
||||||
|
import { PasswordEndAdornment } from "../../../../Components/Inputs/TextInput/Adornments";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
const INITIAL_FORM_STATE = {
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
confirm: "",
|
||||||
|
teamId: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const INITIAL_ROLE_STATE = ["user"];
|
||||||
|
const AddTeamMember = ({ handleIsRegisterOpen, isRegisterOpen, onMemberAdded }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { errors, setErrors, clearErrors, validateFields, validateForm } =
|
||||||
|
useAddTeamMember();
|
||||||
|
const { feedback, handlePasswordFeedback } = usePasswordFeedback();
|
||||||
|
const [getInviteToken, clearToken, isLoading, error, token, addTeamMember] =
|
||||||
|
useGetInviteToken();
|
||||||
|
const [form, setForm] = useState(INITIAL_FORM_STATE);
|
||||||
|
const [role, setRole] = useState(INITIAL_ROLE_STATE);
|
||||||
|
const [isLoadingSubmit, setIsLoadingSubmit] = useState(false);
|
||||||
|
const closeAddMemberModal = () => {
|
||||||
|
handleIsRegisterOpen(false);
|
||||||
|
setForm(INITIAL_FORM_STATE);
|
||||||
|
setRole(INITIAL_ROLE_STATE);
|
||||||
|
clearErrors();
|
||||||
|
clearToken();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (e) => {
|
||||||
|
let { name, value } = e.target;
|
||||||
|
if (name === "email") value = value.toLowerCase();
|
||||||
|
const updatedForm = { ...form, [name]: value };
|
||||||
|
validateFields(name, value, updatedForm);
|
||||||
|
setForm(updatedForm);
|
||||||
|
|
||||||
|
if (name === "password" || name === "confirm") {
|
||||||
|
handlePasswordFeedback(updatedForm, name, value, form, errors, setErrors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onsubmitAddMember = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!validateForm(form, role)) return;
|
||||||
|
try {
|
||||||
|
setIsLoadingSubmit(true);
|
||||||
|
await addTeamMember(form, role);
|
||||||
|
createToast({
|
||||||
|
body: t("teamPanel.registerToast.success"),
|
||||||
|
});
|
||||||
|
onMemberAdded();
|
||||||
|
closeAddMemberModal();
|
||||||
|
} catch (error) {
|
||||||
|
const errorMsg = error.response?.data?.msg || error.message || "unknownError";
|
||||||
|
createToast({
|
||||||
|
type: "error",
|
||||||
|
body: t(errorMsg),
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setIsLoadingSubmit(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const tErr = (key) => (key ? t([`teamPanel.registerTeamMember.${key}`, key]) : "");
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<GenericDialog
|
||||||
|
title={t("teamPanel.addTeamMember.title")}
|
||||||
|
description={t("teamPanel.addTeamMember.description")}
|
||||||
|
open={isRegisterOpen}
|
||||||
|
onClose={closeAddMemberModal}
|
||||||
|
theme={theme}
|
||||||
|
width={{ sm: "55%", md: "50%", lg: "40%", xl: "30%" }}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
name="firstName"
|
||||||
|
label={t("auth.common.inputs.firstName.label")}
|
||||||
|
isRequired={true}
|
||||||
|
gap={theme.spacing(4)}
|
||||||
|
placeholder={t("auth.common.inputs.firstName.placeholder")}
|
||||||
|
value={form.firstName}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.firstName ? true : false}
|
||||||
|
helperText={errors.firstName ? tErr(errors.firstName) : null}
|
||||||
|
sx={{ mb: errors.firstName ? theme.spacing(15) : theme.spacing(5) }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
name="lastName"
|
||||||
|
label={t("auth.common.inputs.lastName.label")}
|
||||||
|
isRequired={true}
|
||||||
|
gap={theme.spacing(4)}
|
||||||
|
placeholder={t("auth.common.inputs.lastName.placeholder")}
|
||||||
|
value={form.lastName}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.lastName ? true : false}
|
||||||
|
helperText={errors.lastName ? tErr(errors.lastName) : null}
|
||||||
|
sx={{ mb: errors.lastName ? theme.spacing(15) : theme.spacing(5) }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
type="email"
|
||||||
|
label={t("auth.common.inputs.email.label")}
|
||||||
|
name="email"
|
||||||
|
gap={theme.spacing(4)}
|
||||||
|
isRequired={true}
|
||||||
|
id="input-team-member"
|
||||||
|
placeholder={t("teamPanel.email")}
|
||||||
|
value={form.email}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.email ? true : false}
|
||||||
|
helperText={errors.email ? tErr(errors.email) : null}
|
||||||
|
sx={{ mb: errors.email ? theme.spacing(15) : theme.spacing(5) }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
label={t("teamPanel.role")}
|
||||||
|
id="team-member-role"
|
||||||
|
name="role"
|
||||||
|
required={true}
|
||||||
|
placeholder={t("teamPanel.selectRole")}
|
||||||
|
isHidden={true}
|
||||||
|
value={role[0] || ""}
|
||||||
|
sx={{ mb: theme.spacing(5) }}
|
||||||
|
onChange={(event) => setRole([event.target.value])}
|
||||||
|
items={[
|
||||||
|
{ _id: "admin", name: t("roles.admin") },
|
||||||
|
{ _id: "user", name: t("roles.teamMember") },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PasswordTooltip
|
||||||
|
feedback={feedback}
|
||||||
|
form={form}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
type="password"
|
||||||
|
id="register-password-input"
|
||||||
|
name="password"
|
||||||
|
label={t("auth.common.inputs.password.label")}
|
||||||
|
isRequired={true}
|
||||||
|
placeholder="••••••••••"
|
||||||
|
value={form.password}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.password && errors.password[0] ? true : false}
|
||||||
|
endAdornment={<PasswordEndAdornment />}
|
||||||
|
sx={{ mb: theme.spacing(5) }}
|
||||||
|
/>
|
||||||
|
</PasswordTooltip>
|
||||||
|
<TextInput
|
||||||
|
type="password"
|
||||||
|
id="register-confirm-input"
|
||||||
|
name="confirm"
|
||||||
|
label={t("auth.common.inputs.passwordConfirm.label")}
|
||||||
|
gap={theme.spacing(4)}
|
||||||
|
isRequired={true}
|
||||||
|
placeholder={t("auth.common.inputs.passwordConfirm.placeholder")}
|
||||||
|
autoComplete="current-password"
|
||||||
|
value={form.confirm}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.confirm && errors.confirm[0] ? true : false}
|
||||||
|
endAdornment={<PasswordEndAdornment />}
|
||||||
|
sx={{ mb: theme.spacing(5) }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
spacing={theme.spacing(10)}
|
||||||
|
mt={theme.spacing(8)}
|
||||||
|
justifyContent="flex-end"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
onClick={closeAddMemberModal}
|
||||||
|
disabled={isLoadingSubmit}
|
||||||
|
>
|
||||||
|
{t("teamPanel.cancel")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="accent"
|
||||||
|
onClick={onsubmitAddMember}
|
||||||
|
disabled={isLoadingSubmit}
|
||||||
|
>
|
||||||
|
{t("teamPanel.addTeamMember.addButton")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</GenericDialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
AddTeamMember.propTypes = {
|
||||||
|
handleIsRegisterOpen: PropTypes.func.isRequired,
|
||||||
|
isRegisterOpen: PropTypes.bool.isRequired,
|
||||||
|
onMemberAdded: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddTeamMember;
|
||||||
@@ -9,10 +9,12 @@ import { networkService } from "../../../main";
|
|||||||
import { createToast } from "../../../Utils/toastUtils";
|
import { createToast } from "../../../Utils/toastUtils";
|
||||||
import Select from "../../../Components/Inputs/Select";
|
import Select from "../../../Components/Inputs/Select";
|
||||||
import { GenericDialog } from "../../../Components/Dialog/genericDialog";
|
import { GenericDialog } from "../../../Components/Dialog/genericDialog";
|
||||||
|
import AddTeamMember from "../components/AddTeamMember";
|
||||||
import DataTable from "../../../Components/Table";
|
import DataTable from "../../../Components/Table";
|
||||||
import { useGetInviteToken } from "../../../Hooks/inviteHooks";
|
import { useGetInviteToken } from "../../../Hooks/inviteHooks";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useIsSuperAdmin } from "../../../Hooks/useIsAdmin";
|
import { useIsSuperAdmin } from "../../../Hooks/useIsAdmin";
|
||||||
|
import AddMemberMenu from "./AddMemberMenu";
|
||||||
/**
|
/**
|
||||||
* TeamPanel component manages the organization and team members,
|
* TeamPanel component manages the organization and team members,
|
||||||
* providing functionalities like renaming the organization, managing team members,
|
* providing functionalities like renaming the organization, managing team members,
|
||||||
@@ -65,7 +67,10 @@ const TeamPanel = () => {
|
|||||||
render: (row) => row.role,
|
render: (row) => row.role,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const [refreshTrigger, setRefreshTrigger] = useState(false);
|
||||||
|
const refreshTeamList = () => {
|
||||||
|
setRefreshTrigger((prev) => !prev);
|
||||||
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchTeam = async () => {
|
const fetchTeam = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -79,7 +84,7 @@ const TeamPanel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchTeam();
|
fetchTeam();
|
||||||
}, []);
|
}, [refreshTrigger]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ROLE_MAP = {
|
const ROLE_MAP = {
|
||||||
@@ -109,6 +114,10 @@ const TeamPanel = () => {
|
|||||||
setIsDisabled(Object.keys(errors).length !== 0 || toInvite.email === "");
|
setIsDisabled(Object.keys(errors).length !== 0 || toInvite.email === "");
|
||||||
}, [errors, toInvite.email]);
|
}, [errors, toInvite.email]);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [isRegisterOpen, setIsRegisterOpen] = useState(false);
|
||||||
|
const handleIsRegisterOpen = (open) => {
|
||||||
|
setIsRegisterOpen(open);
|
||||||
|
};
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
@@ -138,7 +147,6 @@ const TeamPanel = () => {
|
|||||||
const handleGetToken = async () => {
|
const handleGetToken = async () => {
|
||||||
await getInviteToken({ email: toInvite.email, role: toInvite.role });
|
await getInviteToken({ email: toInvite.email, role: toInvite.role });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInviteMember = async () => {
|
const handleInviteMember = async () => {
|
||||||
if (!toInvite.email) {
|
if (!toInvite.email) {
|
||||||
setErrors((prev) => ({ ...prev, email: "Email is required." }));
|
setErrors((prev) => ({ ...prev, email: "Email is required." }));
|
||||||
@@ -239,13 +247,16 @@ const TeamPanel = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Button
|
|
||||||
variant="contained"
|
<AddTeamMember
|
||||||
color="accent"
|
handleIsRegisterOpen={handleIsRegisterOpen}
|
||||||
onClick={() => setIsOpen(true)}
|
isRegisterOpen={isRegisterOpen}
|
||||||
>
|
onMemberAdded={refreshTeamList}
|
||||||
{t("teamPanel.inviteTeamMember")}
|
/>
|
||||||
</Button>
|
<AddMemberMenu
|
||||||
|
handleInviteOpen={() => setIsOpen(true)}
|
||||||
|
handleIsRegisterOpen={handleIsRegisterOpen}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<DataTable
|
<DataTable
|
||||||
@@ -264,7 +275,6 @@ const TeamPanel = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<GenericDialog
|
<GenericDialog
|
||||||
title={t("teamPanel.inviteNewTeamMember")}
|
title={t("teamPanel.inviteNewTeamMember")}
|
||||||
description={t("teamPanel.inviteDescription")}
|
description={t("teamPanel.inviteDescription")}
|
||||||
|
|||||||
@@ -93,14 +93,14 @@ const PasswordTooltip = ({ feedback, form, children }) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
<span style={{ display: "inline-block", width: "100%" }}>{children}</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PasswordTooltip.propTypes = {
|
PasswordTooltip.propTypes = {
|
||||||
feedback: PropTypes.shape({
|
feedback: PropTypes.shape({
|
||||||
length: PropTypes.string.isRequired,
|
length: PropTypes.string,
|
||||||
special: PropTypes.string,
|
special: PropTypes.string,
|
||||||
number: PropTypes.string,
|
number: PropTypes.string,
|
||||||
uppercase: PropTypes.string,
|
uppercase: PropTypes.string,
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { newOrChangedCredentials } from "../../../Validation/validation";
|
||||||
|
|
||||||
|
const usePasswordFeedback = () => {
|
||||||
|
const [feedback, setFeedback] = useState({});
|
||||||
|
const getFeedbackStatus = (form, errors, field, criteria) => {
|
||||||
|
const fieldErrors = errors?.[field];
|
||||||
|
const isFieldEmpty = form?.[field]?.length === 0;
|
||||||
|
const hasError = fieldErrors?.includes(criteria) || fieldErrors?.includes("empty");
|
||||||
|
const isCorrect = !isFieldEmpty && !hasError;
|
||||||
|
|
||||||
|
if (isCorrect) {
|
||||||
|
return "success";
|
||||||
|
} else if (hasError) {
|
||||||
|
return "error";
|
||||||
|
} else {
|
||||||
|
return "info";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePasswordFeedback = (updatedForm, name, value, form, errors, setErrors) => {
|
||||||
|
const validateValue = { [name]: value };
|
||||||
|
const validateOptions = { abortEarly: false, context: { password: form.password } };
|
||||||
|
if (name === "password" && form.confirm.length > 0) {
|
||||||
|
validateValue.confirm = form.confirm;
|
||||||
|
validateOptions.context = { password: value };
|
||||||
|
} else if (name === "confirm") {
|
||||||
|
validateValue.password = form.password;
|
||||||
|
}
|
||||||
|
const { error } = newOrChangedCredentials.validate(validateValue, validateOptions);
|
||||||
|
|
||||||
|
const pwdErrors = error?.details.map((error) => ({
|
||||||
|
path: error.path[0],
|
||||||
|
type: error.type,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const errorsByPath =
|
||||||
|
pwdErrors &&
|
||||||
|
pwdErrors.reduce((acc, { path, type }) => {
|
||||||
|
if (!acc[path]) {
|
||||||
|
acc[path] = [];
|
||||||
|
}
|
||||||
|
acc[path].push(type);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const oldErrors = { ...errors };
|
||||||
|
if (name === "password") {
|
||||||
|
oldErrors.password = undefined;
|
||||||
|
} else if (name === "confirm") {
|
||||||
|
oldErrors.confirm = undefined;
|
||||||
|
}
|
||||||
|
const newErrors = { ...oldErrors, ...errorsByPath };
|
||||||
|
|
||||||
|
setErrors(newErrors);
|
||||||
|
|
||||||
|
const newFeedback = {
|
||||||
|
length: getFeedbackStatus(updatedForm, errorsByPath, "password", "string.min"),
|
||||||
|
special: getFeedbackStatus(updatedForm, errorsByPath, "password", "special"),
|
||||||
|
number: getFeedbackStatus(updatedForm, errorsByPath, "password", "number"),
|
||||||
|
uppercase: getFeedbackStatus(updatedForm, errorsByPath, "password", "uppercase"),
|
||||||
|
lowercase: getFeedbackStatus(updatedForm, errorsByPath, "password", "lowercase"),
|
||||||
|
confirm: getFeedbackStatus(updatedForm, errorsByPath, "confirm", "different"),
|
||||||
|
};
|
||||||
|
|
||||||
|
setFeedback(newFeedback);
|
||||||
|
};
|
||||||
|
return { feedback, handlePasswordFeedback, getFeedbackStatus };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default usePasswordFeedback;
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
//Components
|
//Components
|
||||||
import Table from "../../../../Components/Table";
|
import Stack from "@mui/material/Stack";
|
||||||
|
import DataTable from "../../../../Components/Table";
|
||||||
|
import Table from "@mui/material/Table";
|
||||||
|
import TableBody from "@mui/material/TableBody";
|
||||||
|
import TableRow from "@mui/material/TableRow";
|
||||||
|
import TableCell from "@mui/material/TableCell";
|
||||||
import TableSkeleton from "../../../../Components/Table/skeleton";
|
import TableSkeleton from "../../../../Components/Table/skeleton";
|
||||||
import Pagination from "../../../../Components/Table/TablePagination";
|
import Pagination from "../../../../Components/Table/TablePagination";
|
||||||
import { StatusLabel } from "../../../../Components/Label";
|
import { StatusLabel } from "../../../../Components/Label";
|
||||||
@@ -16,7 +21,68 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useFetchChecksTeam } from "../../../../Hooks/checkHooks";
|
import { useFetchChecksTeam } from "../../../../Hooks/checkHooks";
|
||||||
import { useFetchChecksByMonitor } from "../../../../Hooks/checkHooks";
|
import { useFetchChecksByMonitor } from "../../../../Hooks/checkHooks";
|
||||||
import { useResolveIncident } from "../../../../Hooks/checkHooks";
|
import { useResolveIncident } from "../../../../Hooks/checkHooks";
|
||||||
import { Button, Typography } from "@mui/material";
|
import { Button, Typography, useTheme } from "@mui/material";
|
||||||
|
import { lighten } from "@mui/material/styles";
|
||||||
|
|
||||||
|
const GetTooltip = (row) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const phases = row?.timings?.phases;
|
||||||
|
|
||||||
|
const phaseKeyFormattingMap = {
|
||||||
|
firstByte: "first byte",
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
backgroundColor={lighten(theme.palette.primary.main, 0.1)}
|
||||||
|
border={`1px solid ${theme.palette.primary.lowContrast}`}
|
||||||
|
borderRadius={theme.shape.borderRadius}
|
||||||
|
py={theme.spacing(2)}
|
||||||
|
px={theme.spacing(4)}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
color={theme.palette.primary.contrastText}
|
||||||
|
>{`Status code: ${row?.statusCode}`}</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
color={theme.palette.primary.contrastText}
|
||||||
|
>{`Response time: ${row?.responseTime} ms`}</Typography>
|
||||||
|
{phases && (
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
color={theme.palette.primary.contrastText}
|
||||||
|
>{`Request timing: `}</Typography>
|
||||||
|
<Table
|
||||||
|
size="small"
|
||||||
|
sx={{ ml: theme.spacing(2), mt: theme.spacing(2) }}
|
||||||
|
>
|
||||||
|
<TableBody>
|
||||||
|
{Object.keys(phases)?.map((phaseKey) => (
|
||||||
|
<TableRow key={phaseKey}>
|
||||||
|
<TableCell sx={{ border: "none", p: 0 }}>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
color="success"
|
||||||
|
>
|
||||||
|
{`${phaseKeyFormattingMap[phaseKey] || phaseKey}:`}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell sx={{ border: "none", p: 0 }}>
|
||||||
|
<Typography
|
||||||
|
color={theme.palette.primary.contrastText}
|
||||||
|
variant="body2"
|
||||||
|
>{`${phases[phaseKey]} ms`}</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const IncidentTable = ({
|
const IncidentTable = ({
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -167,9 +233,10 @@ const IncidentTable = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Table
|
<DataTable
|
||||||
headers={headers}
|
headers={headers}
|
||||||
data={checks}
|
data={checks}
|
||||||
|
config={{ tooltipContent: GetTooltip }}
|
||||||
/>
|
/>
|
||||||
<Pagination
|
<Pagination
|
||||||
paginationLabel={t("incidentsTablePaginationLabel")}
|
paginationLabel={t("incidentsTablePaginationLabel")}
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import ConfigBox from "../../../../Components/ConfigBox";
|
||||||
|
import { Box, Stack, Typography } from "@mui/material";
|
||||||
|
import { CustomThreshold } from "../Components/CustomThreshold";
|
||||||
|
import { capitalizeFirstLetter } from "../../../../Utils/stringUtils";
|
||||||
|
import { useTheme } from "@emotion/react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
const CustomAlertsSection = ({
|
||||||
|
errors,
|
||||||
|
onChange,
|
||||||
|
infrastructureMonitor,
|
||||||
|
handleCheckboxChange,
|
||||||
|
}) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const METRICS = ["cpu", "memory", "disk", "temperature"];
|
||||||
|
const METRIC_PREFIX = "usage_";
|
||||||
|
const hasAlertError = (errors) => {
|
||||||
|
return Object.keys(errors).filter((k) => k.startsWith(METRIC_PREFIX)).length > 0;
|
||||||
|
};
|
||||||
|
const getAlertError = (errors) => {
|
||||||
|
const errorKey = Object.keys(errors).find((key) => key.startsWith(METRIC_PREFIX));
|
||||||
|
return errorKey ? errors[errorKey] : null;
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ConfigBox>
|
||||||
|
<Box>
|
||||||
|
<Typography
|
||||||
|
component="h2"
|
||||||
|
variant="h2"
|
||||||
|
>
|
||||||
|
{t("infrastructureCustomizeAlerts")}
|
||||||
|
</Typography>
|
||||||
|
<Typography component="p">
|
||||||
|
{t("infrastructureAlertNotificationDescription")}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Stack gap={theme.spacing(6)}>
|
||||||
|
{METRICS.map((metric) => {
|
||||||
|
return (
|
||||||
|
<CustomThreshold
|
||||||
|
key={metric}
|
||||||
|
infrastructureMonitor={infrastructureMonitor}
|
||||||
|
errors={errors}
|
||||||
|
checkboxId={metric}
|
||||||
|
checkboxName={metric}
|
||||||
|
checkboxLabel={
|
||||||
|
metric !== "cpu" ? capitalizeFirstLetter(metric) : metric.toUpperCase()
|
||||||
|
}
|
||||||
|
onCheckboxChange={handleCheckboxChange}
|
||||||
|
isChecked={infrastructureMonitor[metric]}
|
||||||
|
fieldId={METRIC_PREFIX + metric}
|
||||||
|
fieldName={METRIC_PREFIX + metric}
|
||||||
|
fieldValue={String(infrastructureMonitor[METRIC_PREFIX + metric])}
|
||||||
|
onFieldChange={onChange}
|
||||||
|
alertUnit={metric == "temperature" ? "°C" : "%"}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{hasAlertError(errors) && (
|
||||||
|
<Typography
|
||||||
|
component="span"
|
||||||
|
className="input-error"
|
||||||
|
color={theme.palette.error.main}
|
||||||
|
mt={theme.spacing(2)}
|
||||||
|
sx={{
|
||||||
|
opacity: 0.8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getAlertError(errors)}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</ConfigBox>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomAlertsSection.propTypes = {
|
||||||
|
errors: PropTypes.object.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
infrastructureMonitor: PropTypes.object.isRequired,
|
||||||
|
handleCheckboxChange: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomAlertsSection;
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Box, Button } from "@mui/material";
|
||||||
|
import { useTheme } from "@emotion/react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
|
||||||
|
import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
|
||||||
|
import Dialog from "../../../../Components/Dialog";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
const MonitorActionButtons = ({ monitor, isBusy, handlePause, handleRemove }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
alignSelf="flex-end"
|
||||||
|
ml="auto"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={handlePause}
|
||||||
|
loading={isBusy}
|
||||||
|
variant="contained"
|
||||||
|
color="secondary"
|
||||||
|
sx={{
|
||||||
|
pl: theme.spacing(4),
|
||||||
|
pr: theme.spacing(6),
|
||||||
|
"& svg": {
|
||||||
|
mr: theme.spacing(2),
|
||||||
|
"& path": {
|
||||||
|
stroke: theme.palette.primary.contrastTextTertiary,
|
||||||
|
strokeWidth: 0.1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{monitor?.isActive ? (
|
||||||
|
<>
|
||||||
|
<PauseCircleOutlineIcon />
|
||||||
|
{t("pause")}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<PlayCircleOutlineRoundedIcon />
|
||||||
|
{t("resume")}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
loading={isBusy}
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
onClick={() => setIsOpen(true)}
|
||||||
|
sx={{ ml: theme.spacing(6) }}
|
||||||
|
>
|
||||||
|
{t("remove")}
|
||||||
|
</Button>
|
||||||
|
<Dialog
|
||||||
|
open={isOpen}
|
||||||
|
theme={theme}
|
||||||
|
title={t("deleteDialogTitle")}
|
||||||
|
description={t("deleteDialogDescription")}
|
||||||
|
onCancel={() => setIsOpen(false)}
|
||||||
|
confirmationButtonLabel={t("delete")}
|
||||||
|
onConfirm={handleRemove}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
MonitorActionButtons.propTypes = {
|
||||||
|
monitor: PropTypes.object.isRequired,
|
||||||
|
isBusy: PropTypes.bool.isRequired,
|
||||||
|
handlePause: PropTypes.func.isRequired,
|
||||||
|
handleRemove: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MonitorActionButtons;
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { Box, Stack, Tooltip, Typography } from "@mui/material";
|
||||||
|
import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils";
|
||||||
|
import { useTheme } from "@emotion/react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import PulseDot from "../../../../Components/Animated/PulseDot";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
const MonitorStatusHeader = ({ monitor, infrastructureMonitor }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { statusColor, pagespeedStatusMsg, determineState } = useMonitorUtils();
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
alignItems="center"
|
||||||
|
height="fit-content"
|
||||||
|
gap={theme.spacing(2)}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title={pagespeedStatusMsg[determineState(monitor)]}
|
||||||
|
disableInteractive
|
||||||
|
slotProps={{
|
||||||
|
popper: {
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: "offset",
|
||||||
|
options: { offset: [0, -8] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
<PulseDot color={statusColor[determineState(monitor)]} />
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
<Typography
|
||||||
|
component="h2"
|
||||||
|
variant="monitorUrl"
|
||||||
|
>
|
||||||
|
{infrastructureMonitor.url?.replace(/^https?:\/\//, "") || "..."}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
position="relative"
|
||||||
|
variant="body2"
|
||||||
|
ml={theme.spacing(6)}
|
||||||
|
mt={theme.spacing(1)}
|
||||||
|
sx={{
|
||||||
|
"&:before": {
|
||||||
|
position: "absolute",
|
||||||
|
content: `""`,
|
||||||
|
width: theme.spacing(2),
|
||||||
|
height: theme.spacing(2),
|
||||||
|
borderRadius: "50%",
|
||||||
|
backgroundColor: theme.palette.primary.contrastTextTertiary,
|
||||||
|
opacity: 0.8,
|
||||||
|
left: theme.spacing(-5),
|
||||||
|
top: "50%",
|
||||||
|
transform: "translateY(-50%)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("editing")}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
MonitorStatusHeader.propTypes = {
|
||||||
|
monitor: PropTypes.object.isRequired,
|
||||||
|
infrastructureMonitor: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MonitorStatusHeader;
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import { useState, useCallback } from "react";
|
||||||
|
const useInfrastructureMonitorForm = () => {
|
||||||
|
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
|
||||||
|
url: "",
|
||||||
|
name: "",
|
||||||
|
notifications: [],
|
||||||
|
notify_email: false,
|
||||||
|
interval: 0.25,
|
||||||
|
statusWindowSize: 5,
|
||||||
|
statusWindowThreshold: 60,
|
||||||
|
cpu: false,
|
||||||
|
usage_cpu: "",
|
||||||
|
memory: false,
|
||||||
|
usage_memory: "",
|
||||||
|
disk: false,
|
||||||
|
usage_disk: "",
|
||||||
|
temperature: false,
|
||||||
|
usage_temperature: "",
|
||||||
|
secret: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const onChangeForm = (name, value) => {
|
||||||
|
setInfrastructureMonitor({
|
||||||
|
...infrastructureMonitor,
|
||||||
|
[name]: value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleCheckboxChange = (event) => {
|
||||||
|
setInfrastructureMonitor({
|
||||||
|
...infrastructureMonitor,
|
||||||
|
[event.target.name]: event.target.checked,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const initializeInfrastructureMonitorForCreate = useCallback((globalSettings) => {
|
||||||
|
const gt = globalSettings?.data?.settings?.globalThresholds || {};
|
||||||
|
setInfrastructureMonitor((prev) => ({
|
||||||
|
...prev,
|
||||||
|
url: "",
|
||||||
|
name: "",
|
||||||
|
notifications: [],
|
||||||
|
interval: 0.25,
|
||||||
|
cpu: gt.cpu !== undefined,
|
||||||
|
usage_cpu: gt.cpu !== undefined ? gt.cpu.toString() : "",
|
||||||
|
memory: gt.memory !== undefined,
|
||||||
|
usage_memory: gt.memory !== undefined ? gt.memory.toString() : "",
|
||||||
|
disk: gt.disk !== undefined,
|
||||||
|
usage_disk: gt.disk !== undefined ? gt.disk.toString() : "",
|
||||||
|
temperature: gt.temperature !== undefined,
|
||||||
|
usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "",
|
||||||
|
secret: "",
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initializeInfrastructureMonitorForUpdate = useCallback((monitor) => {
|
||||||
|
const MS_PER_MINUTE = 60000;
|
||||||
|
const { thresholds = {} } = monitor;
|
||||||
|
setInfrastructureMonitor((prev) => ({
|
||||||
|
...prev,
|
||||||
|
url: monitor.url.replace(/^https?:\/\//, ""),
|
||||||
|
name: monitor.name || "",
|
||||||
|
notifications: monitor.notifications || [],
|
||||||
|
interval: monitor.interval / MS_PER_MINUTE,
|
||||||
|
statusWindowSize: monitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: monitor.statusWindowThreshold,
|
||||||
|
cpu: thresholds.usage_cpu !== undefined,
|
||||||
|
usage_cpu:
|
||||||
|
thresholds.usage_cpu !== undefined ? (thresholds.usage_cpu * 100).toString() : "",
|
||||||
|
memory: thresholds.usage_memory !== undefined,
|
||||||
|
usage_memory:
|
||||||
|
thresholds.usage_memory !== undefined
|
||||||
|
? (thresholds.usage_memory * 100).toString()
|
||||||
|
: "",
|
||||||
|
disk: thresholds.usage_disk !== undefined,
|
||||||
|
usage_disk:
|
||||||
|
thresholds.usage_disk !== undefined
|
||||||
|
? (thresholds.usage_disk * 100).toString()
|
||||||
|
: "",
|
||||||
|
temperature: thresholds.usage_temperature !== undefined,
|
||||||
|
usage_temperature:
|
||||||
|
thresholds.usage_temperature !== undefined
|
||||||
|
? (thresholds.usage_temperature * 100).toString()
|
||||||
|
: "",
|
||||||
|
secret: monitor.secret || "",
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
return {
|
||||||
|
infrastructureMonitor,
|
||||||
|
setInfrastructureMonitor,
|
||||||
|
onChangeForm,
|
||||||
|
handleCheckboxChange,
|
||||||
|
initializeInfrastructureMonitorForCreate,
|
||||||
|
initializeInfrastructureMonitorForUpdate,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useInfrastructureMonitorForm;
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import { useCreateMonitor, useUpdateMonitor } from "../../../../Hooks/monitorHooks";
|
||||||
|
const useInfrastructureSubmit = () => {
|
||||||
|
const [createMonitor, isCreating] = useCreateMonitor();
|
||||||
|
const [updateMonitor, isUpdating] = useUpdateMonitor();
|
||||||
|
const buildForm = (infrastructureMonitor, https) => {
|
||||||
|
const MS_PER_MINUTE = 60000;
|
||||||
|
|
||||||
|
let form = {
|
||||||
|
url: `http${https ? "s" : ""}://` + infrastructureMonitor.url,
|
||||||
|
name:
|
||||||
|
infrastructureMonitor.name === ""
|
||||||
|
? infrastructureMonitor.url
|
||||||
|
: infrastructureMonitor.name,
|
||||||
|
interval: infrastructureMonitor.interval * MS_PER_MINUTE,
|
||||||
|
statusWindowSize: infrastructureMonitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: infrastructureMonitor.statusWindowThreshold,
|
||||||
|
cpu: infrastructureMonitor.cpu,
|
||||||
|
...(infrastructureMonitor.cpu
|
||||||
|
? { usage_cpu: infrastructureMonitor.usage_cpu }
|
||||||
|
: {}),
|
||||||
|
memory: infrastructureMonitor.memory,
|
||||||
|
...(infrastructureMonitor.memory
|
||||||
|
? { usage_memory: infrastructureMonitor.usage_memory }
|
||||||
|
: {}),
|
||||||
|
disk: infrastructureMonitor.disk,
|
||||||
|
...(infrastructureMonitor.disk
|
||||||
|
? { usage_disk: infrastructureMonitor.usage_disk }
|
||||||
|
: {}),
|
||||||
|
temperature: infrastructureMonitor.temperature,
|
||||||
|
...(infrastructureMonitor.temperature
|
||||||
|
? { usage_temperature: infrastructureMonitor.usage_temperature }
|
||||||
|
: {}),
|
||||||
|
secret: infrastructureMonitor.secret,
|
||||||
|
};
|
||||||
|
return form;
|
||||||
|
};
|
||||||
|
const submitInfrastructureForm = async (
|
||||||
|
infrastructureMonitor,
|
||||||
|
form,
|
||||||
|
isCreate,
|
||||||
|
monitorId
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
cpu,
|
||||||
|
usage_cpu,
|
||||||
|
memory,
|
||||||
|
usage_memory,
|
||||||
|
disk,
|
||||||
|
usage_disk,
|
||||||
|
temperature,
|
||||||
|
usage_temperature,
|
||||||
|
...rest
|
||||||
|
} = form;
|
||||||
|
|
||||||
|
const thresholds = {
|
||||||
|
...(cpu ? { usage_cpu: usage_cpu / 100 } : {}),
|
||||||
|
...(memory ? { usage_memory: usage_memory / 100 } : {}),
|
||||||
|
...(disk ? { usage_disk: usage_disk / 100 } : {}),
|
||||||
|
...(temperature ? { usage_temperature: usage_temperature / 100 } : {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalForm = {
|
||||||
|
...(isCreate ? {} : { _id: monitorId }),
|
||||||
|
...rest,
|
||||||
|
description: form.name,
|
||||||
|
type: "hardware",
|
||||||
|
notifications: infrastructureMonitor.notifications,
|
||||||
|
thresholds,
|
||||||
|
};
|
||||||
|
// Handle create or update
|
||||||
|
isCreate
|
||||||
|
? await createMonitor({ monitor: finalForm, redirect: "/infrastructure" })
|
||||||
|
: await updateMonitor({ monitor: finalForm, redirect: "/infrastructure" });
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
buildForm,
|
||||||
|
submitInfrastructureForm,
|
||||||
|
isCreating,
|
||||||
|
isUpdating,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default useInfrastructureSubmit;
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { infrastructureMonitorValidation } from "../../../../Validation/validation";
|
||||||
|
import { createToast } from "../../../../Utils/toastUtils";
|
||||||
|
const useValidateInfrastructureForm = () => {
|
||||||
|
const [errors, setErrors] = useState({});
|
||||||
|
|
||||||
|
const validateField = (name, value) => {
|
||||||
|
const { error } = infrastructureMonitorValidation.validate(
|
||||||
|
{ [name]: value },
|
||||||
|
{ abortEarly: false }
|
||||||
|
);
|
||||||
|
setErrors((prev) => ({
|
||||||
|
...prev,
|
||||||
|
...(error ? { [name]: error.details[0].message } : { [name]: undefined }),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateForm = (form) => {
|
||||||
|
const { error } = infrastructureMonitorValidation.validate(form, {
|
||||||
|
abortEarly: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
const newErrors = {};
|
||||||
|
error.details.forEach((err) => {
|
||||||
|
newErrors[err.path[0]] = err.message;
|
||||||
|
});
|
||||||
|
console.log(newErrors);
|
||||||
|
setErrors(newErrors);
|
||||||
|
createToast({ body: "Please check the form for errors." });
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
return { errors, validateField, validateForm };
|
||||||
|
};
|
||||||
|
export default useValidateInfrastructureForm;
|
||||||
@@ -1,40 +1,33 @@
|
|||||||
//Components
|
//Components
|
||||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||||
import ConfigBox from "../../../Components/ConfigBox";
|
import ConfigBox from "../../../Components/ConfigBox";
|
||||||
import Dialog from "../../../Components/Dialog";
|
|
||||||
import FieldWrapper from "../../../Components/Inputs/FieldWrapper";
|
import FieldWrapper from "../../../Components/Inputs/FieldWrapper";
|
||||||
import Link from "../../../Components/Link";
|
import Link from "../../../Components/Link";
|
||||||
import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
|
|
||||||
import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
|
|
||||||
import PulseDot from "../../../Components/Animated/PulseDot";
|
|
||||||
import Select from "../../../Components/Inputs/Select";
|
import Select from "../../../Components/Inputs/Select";
|
||||||
import TextInput from "../../../Components/Inputs/TextInput";
|
import TextInput from "../../../Components/Inputs/TextInput";
|
||||||
import { Box, Stack, Tooltip, Typography, Button, ButtonGroup } from "@mui/material";
|
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
|
||||||
import { CustomThreshold } from "./Components/CustomThreshold";
|
|
||||||
import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
|
import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
|
||||||
import { createToast } from "../../../Utils/toastUtils";
|
import MonitorStatusHeader from "./Components/MonitorStatusHeader";
|
||||||
|
import MonitorActionButtons from "./Components/MonitorActionButtons";
|
||||||
|
import CustomAlertsSection from "./Components/CustomAlertsSection";
|
||||||
// Utils
|
// Utils
|
||||||
import NotificationsConfig from "../../../Components/NotificationConfig";
|
import NotificationsConfig from "../../../Components/NotificationConfig";
|
||||||
import { capitalizeFirstLetter } from "../../../Utils/stringUtils";
|
|
||||||
import { infrastructureMonitorValidation } from "../../../Validation/validation";
|
|
||||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||||
import { useMonitorUtils } from "../../../Hooks/useMonitorUtils";
|
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
useCreateMonitor,
|
|
||||||
useDeleteMonitor,
|
useDeleteMonitor,
|
||||||
useFetchGlobalSettings,
|
useFetchGlobalSettings,
|
||||||
useFetchHardwareMonitorById,
|
useFetchHardwareMonitorById,
|
||||||
usePauseMonitor,
|
usePauseMonitor,
|
||||||
useUpdateMonitor,
|
|
||||||
} from "../../../Hooks/monitorHooks";
|
} from "../../../Hooks/monitorHooks";
|
||||||
|
import useInfrastructureMonitorForm from "./hooks/useInfrastructureMonitorForm";
|
||||||
|
import useValidateInfrastructureForm from "./hooks/useValidateInfrastructureForm";
|
||||||
|
import useInfrastructureSubmit from "./hooks/useInfrastructureSubmit";
|
||||||
|
|
||||||
const CreateInfrastructureMonitor = () => {
|
const CreateInfrastructureMonitor = () => {
|
||||||
const { user } = useSelector((state) => state.auth);
|
|
||||||
const { monitorId } = useParams();
|
const { monitorId } = useParams();
|
||||||
const isCreate = typeof monitorId === "undefined";
|
const isCreate = typeof monitorId === "undefined";
|
||||||
|
|
||||||
@@ -42,39 +35,29 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// State
|
// State
|
||||||
const [errors, setErrors] = useState({});
|
|
||||||
const [https, setHttps] = useState(false);
|
const [https, setHttps] = useState(false);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
|
||||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||||
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
|
|
||||||
url: "",
|
|
||||||
name: "",
|
|
||||||
notifications: [],
|
|
||||||
notify_email: false,
|
|
||||||
interval: 0.25,
|
|
||||||
cpu: false,
|
|
||||||
usage_cpu: "",
|
|
||||||
memory: false,
|
|
||||||
usage_memory: "",
|
|
||||||
disk: false,
|
|
||||||
usage_disk: "",
|
|
||||||
temperature: false,
|
|
||||||
usage_temperature: "",
|
|
||||||
secret: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch monitor details if editing
|
// Fetch monitor details if editing
|
||||||
const { statusColor, pagespeedStatusMsg, determineState } = useMonitorUtils();
|
|
||||||
const [monitor, isLoading] = useFetchHardwareMonitorById({
|
const [monitor, isLoading] = useFetchHardwareMonitorById({
|
||||||
monitorId,
|
monitorId,
|
||||||
updateTrigger,
|
updateTrigger,
|
||||||
});
|
});
|
||||||
const [createMonitor, isCreating] = useCreateMonitor();
|
|
||||||
const [deleteMonitor, isDeleting] = useDeleteMonitor();
|
const [deleteMonitor, isDeleting] = useDeleteMonitor();
|
||||||
const [globalSettings, globalSettingsLoading] = useFetchGlobalSettings();
|
const [globalSettings, globalSettingsLoading] = useFetchGlobalSettings();
|
||||||
const [notifications, notificationsAreLoading] = useGetNotificationsByTeamId();
|
const [notifications, notificationsAreLoading] = useGetNotificationsByTeamId();
|
||||||
const [pauseMonitor, isPausing] = usePauseMonitor();
|
const [pauseMonitor, isPausing] = usePauseMonitor();
|
||||||
const [updateMonitor, isUpdating] = useUpdateMonitor();
|
const {
|
||||||
|
infrastructureMonitor,
|
||||||
|
setInfrastructureMonitor,
|
||||||
|
onChangeForm,
|
||||||
|
handleCheckboxChange,
|
||||||
|
initializeInfrastructureMonitorForCreate,
|
||||||
|
initializeInfrastructureMonitorForUpdate,
|
||||||
|
} = useInfrastructureMonitorForm();
|
||||||
|
const { errors, validateField, validateForm } = useValidateInfrastructureForm();
|
||||||
|
const { buildForm, submitInfrastructureForm, isCreating, isUpdating } =
|
||||||
|
useInfrastructureSubmit();
|
||||||
|
|
||||||
const FREQUENCIES = [
|
const FREQUENCIES = [
|
||||||
{ _id: 0.25, name: t("time.fifteenSeconds") },
|
{ _id: 0.25, name: t("time.fifteenSeconds") },
|
||||||
@@ -93,157 +76,34 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
{ name: "Configure", path: `/infrastructure/configure/${monitorId}` },
|
{ name: "Configure", path: `/infrastructure/configure/${monitorId}` },
|
||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
const METRICS = ["cpu", "memory", "disk", "temperature"];
|
|
||||||
const METRIC_PREFIX = "usage_";
|
|
||||||
const MS_PER_MINUTE = 60000;
|
|
||||||
|
|
||||||
const hasAlertError = (errors) => {
|
|
||||||
return Object.keys(errors).filter((k) => k.startsWith(METRIC_PREFIX)).length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAlertError = (errors) => {
|
|
||||||
const errorKey = Object.keys(errors).find((key) => key.startsWith(METRIC_PREFIX));
|
|
||||||
return errorKey ? errors[errorKey] : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Populate form fields if editing
|
// Populate form fields if editing
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isCreate) {
|
if (isCreate) {
|
||||||
if (globalSettingsLoading) return;
|
if (globalSettingsLoading) return;
|
||||||
|
|
||||||
const gt = globalSettings?.data?.settings?.globalThresholds || {};
|
|
||||||
|
|
||||||
setHttps(false);
|
setHttps(false);
|
||||||
|
initializeInfrastructureMonitorForCreate(globalSettings);
|
||||||
setInfrastructureMonitor({
|
|
||||||
url: "",
|
|
||||||
name: "",
|
|
||||||
notifications: [],
|
|
||||||
interval: 0.25,
|
|
||||||
cpu: gt.cpu !== undefined,
|
|
||||||
usage_cpu: gt.cpu !== undefined ? gt.cpu.toString() : "",
|
|
||||||
memory: gt.memory !== undefined,
|
|
||||||
usage_memory: gt.memory !== undefined ? gt.memory.toString() : "",
|
|
||||||
disk: gt.disk !== undefined,
|
|
||||||
usage_disk: gt.disk !== undefined ? gt.disk.toString() : "",
|
|
||||||
temperature: gt.temperature !== undefined,
|
|
||||||
usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "",
|
|
||||||
secret: "",
|
|
||||||
});
|
|
||||||
} else if (monitor) {
|
} else if (monitor) {
|
||||||
const { thresholds = {} } = monitor;
|
|
||||||
|
|
||||||
setHttps(monitor.url.startsWith("https"));
|
setHttps(monitor.url.startsWith("https"));
|
||||||
|
initializeInfrastructureMonitorForUpdate(monitor);
|
||||||
setInfrastructureMonitor({
|
|
||||||
url: monitor.url.replace(/^https?:\/\//, ""),
|
|
||||||
name: monitor.name || "",
|
|
||||||
notifications: monitor.notifications || [],
|
|
||||||
interval: monitor.interval / MS_PER_MINUTE,
|
|
||||||
cpu: thresholds.usage_cpu !== undefined,
|
|
||||||
usage_cpu:
|
|
||||||
thresholds.usage_cpu !== undefined
|
|
||||||
? (thresholds.usage_cpu * 100).toString()
|
|
||||||
: "",
|
|
||||||
memory: thresholds.usage_memory !== undefined,
|
|
||||||
usage_memory:
|
|
||||||
thresholds.usage_memory !== undefined
|
|
||||||
? (thresholds.usage_memory * 100).toString()
|
|
||||||
: "",
|
|
||||||
disk: thresholds.usage_disk !== undefined,
|
|
||||||
usage_disk:
|
|
||||||
thresholds.usage_disk !== undefined
|
|
||||||
? (thresholds.usage_disk * 100).toString()
|
|
||||||
: "",
|
|
||||||
temperature: thresholds.usage_temperature !== undefined,
|
|
||||||
usage_temperature:
|
|
||||||
thresholds.usage_temperature !== undefined
|
|
||||||
? (thresholds.usage_temperature * 100).toString()
|
|
||||||
: "",
|
|
||||||
secret: monitor.secret || "",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, [isCreate, monitor, globalSettings, globalSettingsLoading]);
|
}, [
|
||||||
|
isCreate,
|
||||||
|
monitor,
|
||||||
|
globalSettings,
|
||||||
|
globalSettingsLoading,
|
||||||
|
initializeInfrastructureMonitorForCreate,
|
||||||
|
initializeInfrastructureMonitorForUpdate,
|
||||||
|
]);
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
const onSubmit = async (event) => {
|
const onSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
const form = buildForm(infrastructureMonitor, https);
|
||||||
// Build the form
|
const error = validateForm(form);
|
||||||
let form = {
|
|
||||||
url: `http${https ? "s" : ""}://` + infrastructureMonitor.url,
|
|
||||||
name:
|
|
||||||
infrastructureMonitor.name === ""
|
|
||||||
? infrastructureMonitor.url
|
|
||||||
: infrastructureMonitor.name,
|
|
||||||
interval: infrastructureMonitor.interval * MS_PER_MINUTE,
|
|
||||||
cpu: infrastructureMonitor.cpu,
|
|
||||||
...(infrastructureMonitor.cpu
|
|
||||||
? { usage_cpu: infrastructureMonitor.usage_cpu }
|
|
||||||
: {}),
|
|
||||||
memory: infrastructureMonitor.memory,
|
|
||||||
...(infrastructureMonitor.memory
|
|
||||||
? { usage_memory: infrastructureMonitor.usage_memory }
|
|
||||||
: {}),
|
|
||||||
disk: infrastructureMonitor.disk,
|
|
||||||
...(infrastructureMonitor.disk
|
|
||||||
? { usage_disk: infrastructureMonitor.usage_disk }
|
|
||||||
: {}),
|
|
||||||
temperature: infrastructureMonitor.temperature,
|
|
||||||
...(infrastructureMonitor.temperature
|
|
||||||
? { usage_temperature: infrastructureMonitor.usage_temperature }
|
|
||||||
: {}),
|
|
||||||
secret: infrastructureMonitor.secret,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { error } = infrastructureMonitorValidation.validate(form, {
|
|
||||||
abortEarly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
const newErrors = {};
|
|
||||||
error.details.forEach((err) => {
|
|
||||||
newErrors[err.path[0]] = err.message;
|
|
||||||
});
|
|
||||||
console.log(newErrors);
|
|
||||||
setErrors(newErrors);
|
|
||||||
createToast({ body: "Please check the form for errors." });
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
submitInfrastructureForm(infrastructureMonitor, form, isCreate, monitorId);
|
||||||
// Build the thresholds for the form
|
|
||||||
const {
|
|
||||||
cpu,
|
|
||||||
usage_cpu,
|
|
||||||
memory,
|
|
||||||
usage_memory,
|
|
||||||
disk,
|
|
||||||
usage_disk,
|
|
||||||
temperature,
|
|
||||||
usage_temperature,
|
|
||||||
...rest
|
|
||||||
} = form;
|
|
||||||
|
|
||||||
const thresholds = {
|
|
||||||
...(cpu ? { usage_cpu: usage_cpu / 100 } : {}),
|
|
||||||
...(memory ? { usage_memory: usage_memory / 100 } : {}),
|
|
||||||
...(disk ? { usage_disk: usage_disk / 100 } : {}),
|
|
||||||
...(temperature ? { usage_temperature: usage_temperature / 100 } : {}),
|
|
||||||
};
|
|
||||||
|
|
||||||
form = {
|
|
||||||
...(isCreate ? {} : { _id: monitorId }),
|
|
||||||
...rest,
|
|
||||||
description: form.name,
|
|
||||||
type: "hardware",
|
|
||||||
notifications: infrastructureMonitor.notifications,
|
|
||||||
thresholds,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle create or update
|
|
||||||
isCreate
|
|
||||||
? await createMonitor({ monitor: form, redirect: "/infrastructure" })
|
|
||||||
: await updateMonitor({ monitor: form, redirect: "/infrastructure" });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerUpdate = () => {
|
const triggerUpdate = () => {
|
||||||
@@ -252,28 +112,8 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
|
|
||||||
const onChange = (event) => {
|
const onChange = (event) => {
|
||||||
const { value, name } = event.target;
|
const { value, name } = event.target;
|
||||||
setInfrastructureMonitor({
|
onChangeForm(name, value);
|
||||||
...infrastructureMonitor,
|
validateField(name, value);
|
||||||
[name]: value,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { error } = infrastructureMonitorValidation.validate(
|
|
||||||
{ [name]: value },
|
|
||||||
{ abortEarly: false }
|
|
||||||
);
|
|
||||||
setErrors((prev) => ({
|
|
||||||
...prev,
|
|
||||||
...(error ? { [name]: error.details[0].message } : { [name]: undefined }),
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCheckboxChange = (event) => {
|
|
||||||
const { name } = event.target;
|
|
||||||
const { checked } = event.target;
|
|
||||||
setInfrastructureMonitor({
|
|
||||||
...infrastructureMonitor,
|
|
||||||
[name]: checked,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePause = async () => {
|
const handlePause = async () => {
|
||||||
@@ -336,105 +176,19 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
{!isCreate && (
|
{!isCreate && (
|
||||||
<Stack
|
<MonitorStatusHeader
|
||||||
direction="row"
|
monitor={monitor}
|
||||||
alignItems="center"
|
infrastructureMonitor={infrastructureMonitor}
|
||||||
height="fit-content"
|
/>
|
||||||
gap={theme.spacing(2)}
|
|
||||||
>
|
|
||||||
<Tooltip
|
|
||||||
title={pagespeedStatusMsg[determineState(monitor)]}
|
|
||||||
disableInteractive
|
|
||||||
slotProps={{
|
|
||||||
popper: {
|
|
||||||
modifiers: [
|
|
||||||
{
|
|
||||||
name: "offset",
|
|
||||||
options: { offset: [0, -8] },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box>
|
|
||||||
<PulseDot color={statusColor[determineState(monitor)]} />
|
|
||||||
</Box>
|
|
||||||
</Tooltip>
|
|
||||||
<Typography
|
|
||||||
component="h2"
|
|
||||||
variant="monitorUrl"
|
|
||||||
>
|
|
||||||
{infrastructureMonitor.url?.replace(/^https?:\/\//, "") || "..."}
|
|
||||||
</Typography>
|
|
||||||
<Typography
|
|
||||||
position="relative"
|
|
||||||
variant="body2"
|
|
||||||
ml={theme.spacing(6)}
|
|
||||||
mt={theme.spacing(1)}
|
|
||||||
sx={{
|
|
||||||
"&:before": {
|
|
||||||
position: "absolute",
|
|
||||||
content: `""`,
|
|
||||||
width: theme.spacing(2),
|
|
||||||
height: theme.spacing(2),
|
|
||||||
borderRadius: "50%",
|
|
||||||
backgroundColor: theme.palette.primary.contrastTextTertiary,
|
|
||||||
opacity: 0.8,
|
|
||||||
left: theme.spacing(-5),
|
|
||||||
top: "50%",
|
|
||||||
transform: "translateY(-50%)",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("editing")}
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
{!isCreate && (
|
{!isCreate && (
|
||||||
<Box
|
<MonitorActionButtons
|
||||||
alignSelf="flex-end"
|
monitor={monitor}
|
||||||
ml="auto"
|
isBusy={isBusy}
|
||||||
>
|
handlePause={handlePause}
|
||||||
<Button
|
handleRemove={handleRemove}
|
||||||
onClick={handlePause}
|
/>
|
||||||
loading={isBusy}
|
|
||||||
variant="contained"
|
|
||||||
color="secondary"
|
|
||||||
sx={{
|
|
||||||
pl: theme.spacing(4),
|
|
||||||
pr: theme.spacing(6),
|
|
||||||
"& svg": {
|
|
||||||
mr: theme.spacing(2),
|
|
||||||
"& path": {
|
|
||||||
stroke: theme.palette.primary.contrastTextTertiary,
|
|
||||||
strokeWidth: 0.1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{monitor?.isActive ? (
|
|
||||||
<>
|
|
||||||
<PauseCircleOutlineIcon />
|
|
||||||
{t("pause")}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<PlayCircleOutlineRoundedIcon />
|
|
||||||
{t("resume")}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
loading={isBusy}
|
|
||||||
variant="contained"
|
|
||||||
color="error"
|
|
||||||
onClick={() => setIsOpen(true)}
|
|
||||||
sx={{ ml: theme.spacing(6) }}
|
|
||||||
>
|
|
||||||
{t("remove")}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
<ConfigBox>
|
<ConfigBox>
|
||||||
@@ -540,52 +294,39 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
component="h2"
|
component="h2"
|
||||||
variant="h2"
|
variant="h2"
|
||||||
>
|
>
|
||||||
{t("infrastructureCustomizeAlerts")}
|
{t("createMonitorPage.incidentConfigTitle")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography component="p">
|
<Typography component="p">
|
||||||
{t("infrastructureAlertNotificationDescription")}
|
{t("createMonitorPage.incidentConfigDescription")}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Stack gap={theme.spacing(6)}>
|
<Stack gap={theme.spacing(20)}>
|
||||||
{METRICS.map((metric) => {
|
<TextInput
|
||||||
return (
|
name="statusWindowSize"
|
||||||
<CustomThreshold
|
label={t("createMonitorPage.incidentConfigStatusWindowLabel")}
|
||||||
key={metric}
|
type="number"
|
||||||
infrastructureMonitor={infrastructureMonitor}
|
value={infrastructureMonitor.statusWindowSize}
|
||||||
errors={errors}
|
onChange={onChange}
|
||||||
checkboxId={metric}
|
error={errors["statusWindowSize"] ? true : false}
|
||||||
checkboxName={metric}
|
helperText={errors["statusWindowSize"]}
|
||||||
checkboxLabel={
|
/>
|
||||||
metric !== "cpu"
|
<TextInput
|
||||||
? capitalizeFirstLetter(metric)
|
name="statusWindowThreshold"
|
||||||
: metric.toUpperCase()
|
label={t("createMonitorPage.incidentConfigStatusWindowThresholdLabel")}
|
||||||
}
|
type="number"
|
||||||
onCheckboxChange={handleCheckboxChange}
|
value={infrastructureMonitor.statusWindowThreshold}
|
||||||
isChecked={infrastructureMonitor[metric]}
|
onChange={onChange}
|
||||||
fieldId={METRIC_PREFIX + metric}
|
error={errors["statusWindowThreshold"] ? true : false}
|
||||||
fieldName={METRIC_PREFIX + metric}
|
helperText={errors["statusWindowThreshold"]}
|
||||||
fieldValue={String(infrastructureMonitor[METRIC_PREFIX + metric])}
|
/>
|
||||||
onFieldChange={onChange}
|
|
||||||
alertUnit={metric == "temperature" ? "°C" : "%"}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{/* Error text */}
|
|
||||||
{hasAlertError(errors) && (
|
|
||||||
<Typography
|
|
||||||
component="span"
|
|
||||||
className="input-error"
|
|
||||||
color={theme.palette.error.main}
|
|
||||||
mt={theme.spacing(2)}
|
|
||||||
sx={{
|
|
||||||
opacity: 0.8,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{getAlertError(errors)}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</ConfigBox>
|
</ConfigBox>
|
||||||
|
<CustomAlertsSection
|
||||||
|
errors={errors}
|
||||||
|
onChange={onChange}
|
||||||
|
infrastructureMonitor={infrastructureMonitor}
|
||||||
|
handleCheckboxChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
<ConfigBox>
|
<ConfigBox>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
@@ -620,17 +361,6 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
{!isCreate && (
|
|
||||||
<Dialog
|
|
||||||
open={isOpen}
|
|
||||||
theme={theme}
|
|
||||||
title={t("deleteDialogTitle")}
|
|
||||||
description={t("deleteDialogDescription")}
|
|
||||||
onCancel={() => setIsOpen(false)}
|
|
||||||
confirmationButtonLabel={t("delete")}
|
|
||||||
onConfirm={handleRemove}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { FormControl, InputLabel, Select, MenuItem, Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
|
import Select from "../../../../../Components/Inputs/Select";
|
||||||
import NetworkStatBoxes from "./NetworkStatBoxes";
|
import NetworkStatBoxes from "./NetworkStatBoxes";
|
||||||
import NetworkCharts from "./NetworkCharts";
|
import NetworkCharts from "./NetworkCharts";
|
||||||
import MonitorTimeFrameHeader from "../../../../../Components/MonitorTimeFrameHeader";
|
import MonitorTimeFrameHeader from "../../../../../Components/MonitorTimeFrameHeader";
|
||||||
@@ -63,27 +64,17 @@ const Network = ({ net, checks, isLoading, dateRange, setDateRange }) => {
|
|||||||
gap={theme.spacing(4)}
|
gap={theme.spacing(4)}
|
||||||
>
|
>
|
||||||
{availableInterfaces.length > 0 && (
|
{availableInterfaces.length > 0 && (
|
||||||
<FormControl
|
<Select
|
||||||
variant="outlined"
|
name="networkInterface"
|
||||||
size="small"
|
label={t("networkInterface")}
|
||||||
|
value={selectedInterface}
|
||||||
|
onChange={(e) => setSelectedInterface(e.target.value)}
|
||||||
|
items={availableInterfaces.map((interfaceName) => ({
|
||||||
|
_id: interfaceName,
|
||||||
|
name: interfaceName,
|
||||||
|
}))}
|
||||||
sx={{ minWidth: 200 }}
|
sx={{ minWidth: 200 }}
|
||||||
>
|
/>
|
||||||
<InputLabel>{t("networkInterface")}</InputLabel>
|
|
||||||
<Select
|
|
||||||
value={selectedInterface}
|
|
||||||
onChange={(e) => setSelectedInterface(e.target.value)}
|
|
||||||
label={t("networkInterface")}
|
|
||||||
>
|
|
||||||
{availableInterfaces.map((interfaceName) => (
|
|
||||||
<MenuItem
|
|
||||||
key={interfaceName}
|
|
||||||
value={interfaceName}
|
|
||||||
>
|
|
||||||
{interfaceName}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
<MonitorTimeFrameHeader
|
<MonitorTimeFrameHeader
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ const InfrastructureDetails = () => {
|
|||||||
<AreaChartBoxes
|
<AreaChartBoxes
|
||||||
shouldRender={!isLoading}
|
shouldRender={!isLoading}
|
||||||
monitor={monitor}
|
monitor={monitor}
|
||||||
|
dateRange={dateRange}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
// Components
|
// Components
|
||||||
import { Stack, Typography } from "@mui/material";
|
import { Stack } from "@mui/material";
|
||||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||||
import MonitorCreateHeader from "../../../Components/MonitorCreateHeader";
|
import MonitorCreateHeader from "../../../Components/MonitorCreateHeader";
|
||||||
import MonitorsTable from "./Components/MonitorsTable";
|
import MonitorsTable from "./Components/MonitorsTable";
|
||||||
import Pagination from "../../..//Components/Table/TablePagination";
|
import Pagination from "../../..//Components/Table/TablePagination";
|
||||||
import GenericFallback from "../../../Components/GenericFallback";
|
import PageStateWrapper from "../../../Components/PageStateWrapper";
|
||||||
import Fallback from "../../../Components/Fallback";
|
|
||||||
import Filter from "./Components/Filters";
|
import Filter from "./Components/Filters";
|
||||||
import SearchComponent from "../../Uptime/Monitors/Components/SearchComponent";
|
import SearchComponent from "../../Uptime/Monitors/Components/SearchComponent";
|
||||||
// Utils
|
// Utils
|
||||||
@@ -81,75 +80,58 @@ const InfrastructureMonitors = () => {
|
|||||||
updateTrigger,
|
updateTrigger,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (networkError === true) {
|
|
||||||
return (
|
|
||||||
<GenericFallback>
|
|
||||||
<Typography
|
|
||||||
variant="h1"
|
|
||||||
marginY={theme.spacing(4)}
|
|
||||||
color={theme.palette.primary.contrastTextTertiary}
|
|
||||||
>
|
|
||||||
{t("common.toasts.networkError")}
|
|
||||||
</Typography>
|
|
||||||
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
|
||||||
</GenericFallback>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLoading && typeof summary?.totalMonitors === "undefined") {
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
type="infrastructureMonitor"
|
|
||||||
title={t("infrastructureMonitor.fallback.title")}
|
|
||||||
checks={t("infrastructureMonitor.fallback.checks", { returnObjects: true })}
|
|
||||||
link="/infrastructure/create"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(10)}>
|
<>
|
||||||
<Breadcrumbs list={BREADCRUMBS} />
|
<PageStateWrapper
|
||||||
<MonitorCreateHeader
|
networkError={networkError}
|
||||||
isAdmin={isAdmin}
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
path="/infrastructure/create"
|
items={monitors}
|
||||||
/>
|
type="infrastructureMonitor"
|
||||||
<Stack direction={"row"}>
|
fallbackLink="/infrastructure/create"
|
||||||
<MonitorCountHeader
|
>
|
||||||
isLoading={isLoading}
|
<Stack gap={theme.spacing(10)}>
|
||||||
monitorCount={summary?.totalMonitors ?? 0}
|
<Breadcrumbs list={BREADCRUMBS} />
|
||||||
/>
|
<MonitorCreateHeader
|
||||||
<Filter
|
isAdmin={isAdmin}
|
||||||
selectedStatus={selectedStatus}
|
isLoading={isLoading}
|
||||||
setSelectedStatus={setSelectedStatus}
|
path="/infrastructure/create"
|
||||||
setToFilterStatus={setToFilterStatus}
|
/>
|
||||||
handleReset={handleReset}
|
<Stack direction={"row"}>
|
||||||
/>
|
<MonitorCountHeader
|
||||||
<SearchComponent
|
isLoading={isLoading}
|
||||||
monitors={monitors}
|
monitorCount={summary?.totalMonitors ?? 0}
|
||||||
onSearchChange={setSearch}
|
/>
|
||||||
setIsSearching={setIsSearching}
|
<Filter
|
||||||
/>
|
selectedStatus={selectedStatus}
|
||||||
</Stack>
|
setSelectedStatus={setSelectedStatus}
|
||||||
|
setToFilterStatus={setToFilterStatus}
|
||||||
|
handleReset={handleReset}
|
||||||
|
/>
|
||||||
|
<SearchComponent
|
||||||
|
monitors={monitors}
|
||||||
|
onSearchChange={setSearch}
|
||||||
|
setIsSearching={setIsSearching}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<MonitorsTable
|
<MonitorsTable
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
monitors={monitors}
|
monitors={monitors}
|
||||||
isAdmin={isAdmin}
|
isAdmin={isAdmin}
|
||||||
handleActionMenuDelete={handleActionMenuDelete}
|
handleActionMenuDelete={handleActionMenuDelete}
|
||||||
isSearching={isSearching}
|
isSearching={isSearching}
|
||||||
/>
|
/>
|
||||||
<Pagination
|
<Pagination
|
||||||
itemCount={summary?.totalMonitors}
|
itemCount={summary?.totalMonitors}
|
||||||
paginationLabel={t("monitors")}
|
paginationLabel={t("monitors")}
|
||||||
page={page}
|
page={page}
|
||||||
rowsPerPage={rowsPerPage}
|
rowsPerPage={rowsPerPage}
|
||||||
handleChangePage={handleChangePage}
|
handleChangePage={handleChangePage}
|
||||||
handleChangeRowsPerPage={handleChangeRowsPerPage}
|
handleChangeRowsPerPage={handleChangeRowsPerPage}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
</PageStateWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,34 +51,14 @@ const Logs = () => {
|
|||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(4)}>
|
<Stack gap={theme.spacing(4)}>
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "sticky",
|
|
||||||
top: theme.spacing(17),
|
|
||||||
backdropFilter: "blur(10px)",
|
|
||||||
paddingY: theme.spacing(5),
|
|
||||||
paddingLeft: theme.spacing(6),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="h2">{t("logsPage.description")}</Typography>
|
|
||||||
</Box>
|
|
||||||
<Divider
|
|
||||||
color={theme.palette.accent.main}
|
|
||||||
sx={{
|
|
||||||
position: "sticky",
|
|
||||||
top: theme.spacing(33),
|
|
||||||
backdropFilter: "blur(10px)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack
|
<Stack
|
||||||
direction="row"
|
direction="row"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
gap={theme.spacing(4)}
|
gap={theme.spacing(4)}
|
||||||
mt={theme.spacing(10)}
|
|
||||||
sx={{
|
sx={{
|
||||||
position: "sticky",
|
position: "sticky",
|
||||||
top: theme.spacing(34),
|
top: theme.spacing(17),
|
||||||
backdropFilter: "blur(10px)",
|
backdropFilter: "blur(10px)",
|
||||||
paddingTop: theme.spacing(4),
|
paddingTop: theme.spacing(4),
|
||||||
paddingLeft: theme.spacing(6),
|
paddingLeft: theme.spacing(6),
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ const JobTable = ({ jobs = [] }) => {
|
|||||||
content: t("queuePage.jobTable.urlHeader"),
|
content: t("queuePage.jobTable.urlHeader"),
|
||||||
render: (row) => row.monitorUrl,
|
render: (row) => row.monitorUrl,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "interval",
|
||||||
|
content: t("queuePage.jobTable.intervalHeader"),
|
||||||
|
render: (row) => `${row.monitorInterval} ms`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "type",
|
id: "type",
|
||||||
content: t("queuePage.jobTable.typeHeader"),
|
content: t("queuePage.jobTable.typeHeader"),
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ const QueueDetails = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(4)}>
|
<Stack gap={theme.spacing(4)}>
|
||||||
<Typography variant="h2">{t("queuePage.metricsTable.title")}</Typography>
|
|
||||||
<Divider color={theme.palette.accent.main} />
|
|
||||||
<Stack
|
<Stack
|
||||||
gap={theme.spacing(20)}
|
gap={theme.spacing(20)}
|
||||||
mt={theme.spacing(10)}
|
mt={theme.spacing(10)}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const Logs = () => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
// Local state
|
// Local state
|
||||||
const [value, setValue] = useState(2);
|
const [value, setValue] = useState(0);
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
const handleChange = (event, newValue) => {
|
const handleChange = (event, newValue) => {
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import Select from "../../../../../Components/Inputs/Select";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
const ConfigSelect = ({ configSelection, valueSelect, onChange, ...props }) => {
|
||||||
|
const getValueById = (config, id) => {
|
||||||
|
const item = config.find((config) => config._id === id);
|
||||||
|
return item ? (item.value ? item.value : item.name) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getIdByValue = (config, name) => {
|
||||||
|
const item = config.find((config) => {
|
||||||
|
if (config.value) {
|
||||||
|
return config.value === name;
|
||||||
|
} else {
|
||||||
|
return config.name === name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return item ? item._id : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
value={getIdByValue(configSelection, valueSelect)}
|
||||||
|
onChange={(event) => {
|
||||||
|
const newValue = getValueById(configSelection, event.target.value);
|
||||||
|
onChange(newValue);
|
||||||
|
}}
|
||||||
|
items={configSelection}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ConfigSelect.propTypes = {
|
||||||
|
configSelection: PropTypes.array.isRequired,
|
||||||
|
valueSelect: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
export default ConfigSelect;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { networkService } from "../../../../main";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import {
|
||||||
|
MS_PER_SECOND,
|
||||||
|
MS_PER_MINUTE,
|
||||||
|
MS_PER_HOUR,
|
||||||
|
MS_PER_DAY,
|
||||||
|
MS_PER_WEEK,
|
||||||
|
} from "../../../../Utils/timeUtils";
|
||||||
|
|
||||||
|
const useMaintenanceActions = () => {
|
||||||
|
const MS_LOOKUP = {
|
||||||
|
seconds: MS_PER_SECOND,
|
||||||
|
minutes: MS_PER_MINUTE,
|
||||||
|
hours: MS_PER_HOUR,
|
||||||
|
days: MS_PER_DAY,
|
||||||
|
weeks: MS_PER_WEEK,
|
||||||
|
};
|
||||||
|
const REPEAT_LOOKUP = {
|
||||||
|
none: 0,
|
||||||
|
daily: MS_PER_DAY,
|
||||||
|
weekly: MS_PER_DAY * 7,
|
||||||
|
};
|
||||||
|
const handleSubmitForm = async (maintenanceWindowId, form) => {
|
||||||
|
const start = dayjs(form.startDate)
|
||||||
|
.set("hour", form.startTime.hour())
|
||||||
|
.set("minute", form.startTime.minute());
|
||||||
|
|
||||||
|
const MS_MULTIPLIER = MS_LOOKUP[form.durationUnit];
|
||||||
|
const durationInMs = form.duration * MS_MULTIPLIER;
|
||||||
|
const end = start.add(durationInMs);
|
||||||
|
|
||||||
|
const repeat = REPEAT_LOOKUP[form.repeat];
|
||||||
|
|
||||||
|
const submit = {
|
||||||
|
monitors: form.monitors.map((monitor) => monitor._id),
|
||||||
|
name: form.name,
|
||||||
|
start: start.toISOString(),
|
||||||
|
end: end.toISOString(),
|
||||||
|
repeat,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (repeat === 0) {
|
||||||
|
submit.expiry = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestConfig = { maintenanceWindow: submit };
|
||||||
|
|
||||||
|
if (maintenanceWindowId !== undefined) {
|
||||||
|
requestConfig.maintenanceWindowId = maintenanceWindowId;
|
||||||
|
}
|
||||||
|
const request =
|
||||||
|
maintenanceWindowId === undefined
|
||||||
|
? networkService.createMaintenanceWindow(requestConfig)
|
||||||
|
: networkService.editMaintenanceWindow(requestConfig);
|
||||||
|
return request;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
handleSubmitForm,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useMaintenanceActions;
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { networkService } from "../../../../main";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import {
|
||||||
|
MS_PER_SECOND,
|
||||||
|
MS_PER_MINUTE,
|
||||||
|
MS_PER_HOUR,
|
||||||
|
MS_PER_DAY,
|
||||||
|
MS_PER_WEEK,
|
||||||
|
} from "../../../../Utils/timeUtils";
|
||||||
|
const useMaintenanceData = () => {
|
||||||
|
const REVERSE_REPEAT_LOOKUP = {
|
||||||
|
0: "none",
|
||||||
|
[MS_PER_DAY]: "daily",
|
||||||
|
[MS_PER_WEEK]: "weekly",
|
||||||
|
};
|
||||||
|
const getDurationAndUnit = (durationInMs) => {
|
||||||
|
if (durationInMs % MS_PER_DAY === 0) {
|
||||||
|
return {
|
||||||
|
duration: (durationInMs / MS_PER_DAY).toString(),
|
||||||
|
durationUnit: "days",
|
||||||
|
};
|
||||||
|
} else if (durationInMs % MS_PER_HOUR === 0) {
|
||||||
|
return {
|
||||||
|
duration: (durationInMs / MS_PER_HOUR).toString(),
|
||||||
|
durationUnit: "hours",
|
||||||
|
};
|
||||||
|
} else if (durationInMs % MS_PER_MINUTE === 0) {
|
||||||
|
return {
|
||||||
|
duration: (durationInMs / MS_PER_MINUTE).toString(),
|
||||||
|
durationUnit: "minutes",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
duration: (durationInMs / MS_PER_SECOND).toString(),
|
||||||
|
durationUnit: "seconds",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const fetchMonitorsMaintenance = async () => {
|
||||||
|
const response = await networkService.getMonitorsByTeamId({
|
||||||
|
limit: null,
|
||||||
|
types: ["http", "ping", "pagespeed", "port"],
|
||||||
|
});
|
||||||
|
const fetchedMonitors = response.data.data.monitors;
|
||||||
|
return fetchedMonitors;
|
||||||
|
};
|
||||||
|
|
||||||
|
const initializeMaintenanceForEdit = async (maintenanceWindowId, monitorList) => {
|
||||||
|
const res = await networkService.getMaintenanceWindowById({
|
||||||
|
maintenanceWindowId: maintenanceWindowId,
|
||||||
|
});
|
||||||
|
const maintenanceWindow = res.data.data;
|
||||||
|
const { name, start, end, repeat, monitorId } = maintenanceWindow;
|
||||||
|
const startTime = dayjs(start);
|
||||||
|
const endTime = dayjs(end);
|
||||||
|
const durationInMs = endTime.diff(startTime, "milliseconds").toString();
|
||||||
|
const { duration, durationUnit } = getDurationAndUnit(durationInMs);
|
||||||
|
const monitor = monitorList.find((monitor) => monitor._id === monitorId);
|
||||||
|
const maintenanceWindowInformation = {
|
||||||
|
name,
|
||||||
|
repeat: REVERSE_REPEAT_LOOKUP[repeat],
|
||||||
|
startDate: startTime,
|
||||||
|
startTime,
|
||||||
|
duration,
|
||||||
|
durationUnit,
|
||||||
|
monitors: monitor ? [monitor] : [],
|
||||||
|
};
|
||||||
|
return maintenanceWindowInformation;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { fetchMonitorsMaintenance, initializeMaintenanceForEdit };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useMaintenanceData;
|
||||||
@@ -10,71 +10,21 @@ import { MobileTimePicker } from "@mui/x-date-pickers/MobileTimePicker";
|
|||||||
import { maintenanceWindowValidation } from "../../../Validation/validation";
|
import { maintenanceWindowValidation } from "../../../Validation/validation";
|
||||||
import { createToast } from "../../../Utils/toastUtils";
|
import { createToast } from "../../../Utils/toastUtils";
|
||||||
import MonitorList from "./Components/MonitorList";
|
import MonitorList from "./Components/MonitorList";
|
||||||
import Checkbox from "../../../Components/Inputs/Checkbox";
|
import ConfigSelect from "./Components/ConfigSelect";
|
||||||
|
import useMaintenanceData from "./hooks/useMaintenanceData";
|
||||||
|
import useMaintenanceActions from "./hooks/useMaintenanceActions";
|
||||||
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import Select from "../../../Components/Inputs/Select";
|
|
||||||
import TextInput from "../../../Components/Inputs/TextInput";
|
import TextInput from "../../../Components/Inputs/TextInput";
|
||||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||||
import CalendarIcon from "../../../assets/icons/calendar.svg?react";
|
import CalendarIcon from "../../../assets/icons/calendar.svg?react";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import Search from "../../../Components/Inputs/Search";
|
import Search from "../../../Components/Inputs/Search";
|
||||||
import { networkService } from "../../../main";
|
|
||||||
import { logger } from "../../../Utils/Logger";
|
import { logger } from "../../../Utils/Logger";
|
||||||
import {
|
|
||||||
MS_PER_SECOND,
|
|
||||||
MS_PER_MINUTE,
|
|
||||||
MS_PER_HOUR,
|
|
||||||
MS_PER_DAY,
|
|
||||||
MS_PER_WEEK,
|
|
||||||
} from "../../../Utils/timeUtils";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { buildErrors, hasValidationErrors } from "../../../Validation/error";
|
import { buildErrors, hasValidationErrors } from "../../../Validation/error";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import dayjs from "dayjs";
|
||||||
const getDurationAndUnit = (durationInMs) => {
|
|
||||||
if (durationInMs % MS_PER_DAY === 0) {
|
|
||||||
return {
|
|
||||||
duration: (durationInMs / MS_PER_DAY).toString(),
|
|
||||||
durationUnit: "days",
|
|
||||||
};
|
|
||||||
} else if (durationInMs % MS_PER_HOUR === 0) {
|
|
||||||
return {
|
|
||||||
duration: (durationInMs / MS_PER_HOUR).toString(),
|
|
||||||
durationUnit: "hours",
|
|
||||||
};
|
|
||||||
} else if (durationInMs % MS_PER_MINUTE === 0) {
|
|
||||||
return {
|
|
||||||
duration: (durationInMs / MS_PER_MINUTE).toString(),
|
|
||||||
durationUnit: "minutes",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
duration: (durationInMs / MS_PER_SECOND).toString(),
|
|
||||||
durationUnit: "seconds",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MS_LOOKUP = {
|
|
||||||
seconds: MS_PER_SECOND,
|
|
||||||
minutes: MS_PER_MINUTE,
|
|
||||||
hours: MS_PER_HOUR,
|
|
||||||
days: MS_PER_DAY,
|
|
||||||
weeks: MS_PER_WEEK,
|
|
||||||
};
|
|
||||||
|
|
||||||
const REPEAT_LOOKUP = {
|
|
||||||
none: 0,
|
|
||||||
daily: MS_PER_DAY,
|
|
||||||
weekly: MS_PER_DAY * 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
const REVERSE_REPEAT_LOOKUP = {
|
|
||||||
0: "none",
|
|
||||||
[MS_PER_DAY]: "daily",
|
|
||||||
[MS_PER_WEEK]: "weekly",
|
|
||||||
};
|
|
||||||
|
|
||||||
const repeatConfig = [
|
const repeatConfig = [
|
||||||
{ _id: 0, name: "Don't repeat", value: "none" },
|
{ _id: 0, name: "Don't repeat", value: "none" },
|
||||||
@@ -96,24 +46,10 @@ const durationConfig = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const getValueById = (config, id) => {
|
|
||||||
const item = config.find((config) => config._id === id);
|
|
||||||
return item ? (item.value ? item.value : item.name) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getIdByValue = (config, name) => {
|
|
||||||
const item = config.find((config) => {
|
|
||||||
if (config.value) {
|
|
||||||
return config.value === name;
|
|
||||||
} else {
|
|
||||||
return config.name === name;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return item ? item._id : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const CreateMaintenance = () => {
|
const CreateMaintenance = () => {
|
||||||
const { maintenanceWindowId } = useParams();
|
const { maintenanceWindowId } = useParams();
|
||||||
|
const { handleSubmitForm } = useMaintenanceActions();
|
||||||
|
const { fetchMonitorsMaintenance, initializeMaintenanceForEdit } = useMaintenanceData();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -121,6 +57,7 @@ const CreateMaintenance = () => {
|
|||||||
const [monitors, setMonitors] = useState([]);
|
const [monitors, setMonitors] = useState([]);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [errors, setErrors] = useState({});
|
||||||
const [form, setForm] = useState({
|
const [form, setForm] = useState({
|
||||||
repeat: "none",
|
repeat: "none",
|
||||||
startDate: dayjs(),
|
startDate: dayjs(),
|
||||||
@@ -130,43 +67,35 @@ const CreateMaintenance = () => {
|
|||||||
name: "",
|
name: "",
|
||||||
monitors: [],
|
monitors: [],
|
||||||
});
|
});
|
||||||
const [errors, setErrors] = useState({});
|
const handleFormChange = (key, value) => {
|
||||||
|
setForm((prev) => ({ ...prev, [key]: value }));
|
||||||
|
const { error } = maintenanceWindowValidation.validate(
|
||||||
|
{ [key]: value },
|
||||||
|
{ abortEarly: false }
|
||||||
|
);
|
||||||
|
setErrors((prev) => {
|
||||||
|
return buildErrors(prev, key, error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchMonitors = async () => {
|
const fetchMonitors = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await networkService.getMonitorsByTeamId({
|
const fetchedMonitors = await fetchMonitorsMaintenance();
|
||||||
limit: null,
|
setMonitors(fetchedMonitors);
|
||||||
types: ["http", "ping", "pagespeed", "port"],
|
|
||||||
});
|
|
||||||
const monitors = response.data.data.monitors;
|
|
||||||
setMonitors(monitors);
|
|
||||||
|
|
||||||
if (maintenanceWindowId === undefined) {
|
if (maintenanceWindowId === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const maintenanceWindowInformation = await initializeMaintenanceForEdit(
|
||||||
const res = await networkService.getMaintenanceWindowById({
|
maintenanceWindowId,
|
||||||
maintenanceWindowId: maintenanceWindowId,
|
fetchedMonitors
|
||||||
});
|
);
|
||||||
const maintenanceWindow = res.data.data;
|
setForm((prev) => ({
|
||||||
const { name, start, end, repeat, monitorId } = maintenanceWindow;
|
...prev,
|
||||||
const startTime = dayjs(start);
|
...maintenanceWindowInformation,
|
||||||
const endTime = dayjs(end);
|
}));
|
||||||
const durationInMs = endTime.diff(startTime, "milliseconds").toString();
|
|
||||||
const { duration, durationUnit } = getDurationAndUnit(durationInMs);
|
|
||||||
const monitor = monitors.find((monitor) => monitor._id === monitorId);
|
|
||||||
setForm({
|
|
||||||
...form,
|
|
||||||
name,
|
|
||||||
repeat: REVERSE_REPEAT_LOOKUP[repeat],
|
|
||||||
startDate: startTime,
|
|
||||||
startTime,
|
|
||||||
duration,
|
|
||||||
durationUnit,
|
|
||||||
monitors: monitor ? [monitor] : [],
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
createToast({ body: "Failed to fetch data" });
|
createToast({ body: "Failed to fetch data" });
|
||||||
logger.error("Failed to fetch monitors", error);
|
logger.error("Failed to fetch monitors", error);
|
||||||
@@ -177,90 +106,9 @@ const CreateMaintenance = () => {
|
|||||||
fetchMonitors();
|
fetchMonitors();
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
const handleSearch = (value) => {
|
|
||||||
setSearch(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelectMonitors = (monitors) => {
|
|
||||||
setForm({ ...form, monitors });
|
|
||||||
const { error } = maintenanceWindowValidation.validate(
|
|
||||||
{ monitors },
|
|
||||||
{ abortEarly: false }
|
|
||||||
);
|
|
||||||
setErrors((prev) => {
|
|
||||||
return buildErrors(prev, "monitors", error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFormChange = (key, value) => {
|
|
||||||
setForm({ ...form, [key]: value });
|
|
||||||
const { error } = maintenanceWindowValidation.validate(
|
|
||||||
{ [key]: value },
|
|
||||||
{ abortEarly: false }
|
|
||||||
);
|
|
||||||
setErrors((prev) => {
|
|
||||||
return buildErrors(prev, key, error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTimeChange = (key, newTime) => {
|
|
||||||
setForm({ ...form, [key]: newTime });
|
|
||||||
const { error } = maintenanceWindowValidation.validate(
|
|
||||||
{ [key]: newTime },
|
|
||||||
{ abortEarly: false }
|
|
||||||
);
|
|
||||||
setErrors((prev) => {
|
|
||||||
return buildErrors(prev, key, error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMonitorsChange = (selected) => {
|
|
||||||
setForm((prev) => ({ ...prev, monitors: selected }));
|
|
||||||
const { error } = maintenanceWindowValidation.validate(
|
|
||||||
{ monitors: selected },
|
|
||||||
{ abortEarly: false }
|
|
||||||
);
|
|
||||||
setErrors((prev) => {
|
|
||||||
return buildErrors(prev, "monitors", error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (hasValidationErrors(form, maintenanceWindowValidation, setErrors)) return;
|
if (hasValidationErrors(form, maintenanceWindowValidation, setErrors)) return;
|
||||||
// Build timestamp for maintenance window from startDate and startTime
|
const request = handleSubmitForm(maintenanceWindowId, form);
|
||||||
const start = dayjs(form.startDate)
|
|
||||||
.set("hour", form.startTime.hour())
|
|
||||||
.set("minute", form.startTime.minute());
|
|
||||||
// Build end timestamp for maintenance window
|
|
||||||
const MS_MULTIPLIER = MS_LOOKUP[form.durationUnit];
|
|
||||||
const durationInMs = form.duration * MS_MULTIPLIER;
|
|
||||||
const end = start.add(durationInMs);
|
|
||||||
|
|
||||||
// Get repeat value in milliseconds
|
|
||||||
const repeat = REPEAT_LOOKUP[form.repeat];
|
|
||||||
|
|
||||||
const submit = {
|
|
||||||
monitors: form.monitors.map((monitor) => monitor._id),
|
|
||||||
name: form.name,
|
|
||||||
start: start.toISOString(),
|
|
||||||
end: end.toISOString(),
|
|
||||||
repeat,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (repeat === 0) {
|
|
||||||
submit.expiry = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
const requestConfig = { maintenanceWindow: submit };
|
|
||||||
|
|
||||||
if (maintenanceWindowId !== undefined) {
|
|
||||||
requestConfig.maintenanceWindowId = maintenanceWindowId;
|
|
||||||
}
|
|
||||||
const request =
|
|
||||||
maintenanceWindowId === undefined
|
|
||||||
? networkService.createMaintenanceWindow(requestConfig)
|
|
||||||
: networkService.editMaintenanceWindow(requestConfig);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await request;
|
await request;
|
||||||
@@ -353,18 +201,13 @@ const CreateMaintenance = () => {
|
|||||||
error={errors["name"] ? true : false}
|
error={errors["name"] ? true : false}
|
||||||
helperText={errors["name"]}
|
helperText={errors["name"]}
|
||||||
/>
|
/>
|
||||||
<Select
|
<ConfigSelect
|
||||||
id="repeat"
|
id="repeat"
|
||||||
name="maintenance-repeat"
|
name="maintenance-repeat"
|
||||||
label={t("maintenanceRepeat")}
|
label={t("maintenanceRepeat")}
|
||||||
value={getIdByValue(repeatConfig, form.repeat)}
|
valueSelect={form.repeat}
|
||||||
onChange={(event) => {
|
configSelection={repeatConfig}
|
||||||
handleFormChange(
|
onChange={(value) => handleFormChange("repeat", value)}
|
||||||
"repeat",
|
|
||||||
getValueById(repeatConfig, event.target.value)
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
items={repeatConfig}
|
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||||
@@ -437,7 +280,7 @@ const CreateMaintenance = () => {
|
|||||||
}}
|
}}
|
||||||
sx={{}}
|
sx={{}}
|
||||||
onChange={(newDate) => {
|
onChange={(newDate) => {
|
||||||
handleTimeChange("startDate", newDate);
|
handleFormChange("startDate", newDate);
|
||||||
}}
|
}}
|
||||||
error={errors["startDate"]}
|
error={errors["startDate"]}
|
||||||
/>
|
/>
|
||||||
@@ -453,7 +296,7 @@ const CreateMaintenance = () => {
|
|||||||
>
|
>
|
||||||
{t("startTime")}
|
{t("startTime")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>{t("timeZoneInfo")}</Typography>
|
<Typography> {t("timeZoneInfo")} </Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Stack gap={theme.spacing(15)}>
|
<Stack gap={theme.spacing(15)}>
|
||||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||||
@@ -462,7 +305,7 @@ const CreateMaintenance = () => {
|
|||||||
label={t("startTime")}
|
label={t("startTime")}
|
||||||
value={form.startTime}
|
value={form.startTime}
|
||||||
onChange={(newTime) => {
|
onChange={(newTime) => {
|
||||||
handleTimeChange("startTime", newTime);
|
handleFormChange("startTime", newTime);
|
||||||
}}
|
}}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
nextIconButton: { sx: { ml: theme.spacing(2) } },
|
nextIconButton: { sx: { ml: theme.spacing(2) } },
|
||||||
@@ -508,16 +351,11 @@ const CreateMaintenance = () => {
|
|||||||
error={errors["duration"] ? true : false}
|
error={errors["duration"] ? true : false}
|
||||||
helperText={errors["duration"]}
|
helperText={errors["duration"]}
|
||||||
/>
|
/>
|
||||||
<Select
|
<ConfigSelect
|
||||||
id="durationUnit"
|
id="durationUnit"
|
||||||
value={getIdByValue(durationConfig, form.durationUnit)}
|
valueSelect={form.durationUnit}
|
||||||
items={durationConfig}
|
configSelection={durationConfig}
|
||||||
onChange={(event) => {
|
onChange={(value) => handleFormChange("durationUnit", value)}
|
||||||
handleFormChange(
|
|
||||||
"durationUnit",
|
|
||||||
getValueById(durationConfig, event.target.value)
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
error={errors["durationUnit"]}
|
error={errors["durationUnit"]}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -545,7 +383,9 @@ const CreateMaintenance = () => {
|
|||||||
inputValue={search}
|
inputValue={search}
|
||||||
value={form.monitors}
|
value={form.monitors}
|
||||||
handleInputChange={setSearch}
|
handleInputChange={setSearch}
|
||||||
handleChange={handleMonitorsChange}
|
handleChange={(selected) => {
|
||||||
|
handleFormChange("monitors", selected);
|
||||||
|
}}
|
||||||
error={errors["monitors"]}
|
error={errors["monitors"]}
|
||||||
/>
|
/>
|
||||||
<MonitorList
|
<MonitorList
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Stack, Button } from "@mui/material";
|
import { Stack, Button } from "@mui/material";
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import Fallback from "../../Components/Fallback";
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import MaintenanceTable from "./MaintenanceTable";
|
import MaintenanceTable from "./MaintenanceTable";
|
||||||
@@ -8,24 +7,21 @@ import { useSelector } from "react-redux";
|
|||||||
import { networkService } from "../../main";
|
import { networkService } from "../../main";
|
||||||
import Breadcrumbs from "../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../Components/Breadcrumbs";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useIsAdmin } from "../../Hooks/useIsAdmin";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Typography } from "@mui/material";
|
import PageStateWrapper from "../../Components/PageStateWrapper";
|
||||||
import GenericFallback from "../../Components/GenericFallback";
|
|
||||||
|
|
||||||
const Maintenance = () => {
|
const Maintenance = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const rowsPerPage = useSelector((state) => state?.ui?.maintenance?.rowsPerPage ?? 5);
|
const rowsPerPage = useSelector((state) => state?.ui?.maintenance?.rowsPerPage ?? 5);
|
||||||
const isAdmin = useIsAdmin();
|
const [maintenanceWindows, setMaintenanceWindows] = useState(undefined);
|
||||||
const [maintenanceWindows, setMaintenanceWindows] = useState([]);
|
|
||||||
const [maintenanceWindowCount, setMaintenanceWindowCount] = useState(0);
|
const [maintenanceWindowCount, setMaintenanceWindowCount] = useState(0);
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const [sort, setSort] = useState({});
|
const [sort, setSort] = useState({});
|
||||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||||
const [networkError, setNetworkError] = useState(false);
|
const [networkError, setNetworkError] = useState(false);
|
||||||
const [isDataFetched, setIsDataFetched] = useState(false);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
const handleActionMenuDelete = () => {
|
const handleActionMenuDelete = () => {
|
||||||
setUpdateTrigger((prev) => !prev);
|
setUpdateTrigger((prev) => !prev);
|
||||||
@@ -34,80 +30,65 @@ const Maintenance = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchMaintenanceWindows = async () => {
|
const fetchMaintenanceWindows = async () => {
|
||||||
try {
|
try {
|
||||||
|
setNetworkError(false);
|
||||||
|
setIsLoading(true);
|
||||||
const response = await networkService.getMaintenanceWindowsByTeamId({
|
const response = await networkService.getMaintenanceWindowsByTeamId({
|
||||||
page: page,
|
page: page,
|
||||||
rowsPerPage: rowsPerPage,
|
rowsPerPage: rowsPerPage,
|
||||||
});
|
});
|
||||||
const { maintenanceWindows, maintenanceWindowCount } = response.data.data;
|
const { maintenanceWindows, maintenanceWindowCount } = response.data.data;
|
||||||
setMaintenanceWindows(maintenanceWindows);
|
setMaintenanceWindows(maintenanceWindows ?? []);
|
||||||
setMaintenanceWindowCount(maintenanceWindowCount);
|
setMaintenanceWindowCount(maintenanceWindowCount ?? 0);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setNetworkError(true);
|
setNetworkError(true);
|
||||||
} finally {
|
} finally {
|
||||||
setIsDataFetched(true);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchMaintenanceWindows();
|
fetchMaintenanceWindows();
|
||||||
}, [page, rowsPerPage, updateTrigger]);
|
}, [page, rowsPerPage, updateTrigger]);
|
||||||
|
|
||||||
if (networkError) {
|
|
||||||
return (
|
|
||||||
<GenericFallback>
|
|
||||||
<Typography
|
|
||||||
variant="h1"
|
|
||||||
marginY={theme.spacing(4)}
|
|
||||||
color={theme.palette.primary.contrastTextTertiary}
|
|
||||||
>
|
|
||||||
{t("common.toasts.networkError")}
|
|
||||||
</Typography>
|
|
||||||
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
|
||||||
</GenericFallback>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Only show the fallback if we've fetched data and there are no maintenance windows
|
|
||||||
if (isDataFetched && maintenanceWindows.length === 0) {
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
type="maintenanceWindow"
|
|
||||||
title={t("maintenanceWindow.fallback.title")}
|
|
||||||
checks={t("maintenanceWindow.fallback.checks", { returnObjects: true })}
|
|
||||||
link="/maintenance/create"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(10)}>
|
<>
|
||||||
<Stack
|
<PageStateWrapper
|
||||||
direction="row"
|
networkError={networkError}
|
||||||
justifyContent="space-between"
|
isLoading={isLoading}
|
||||||
alignItems="center"
|
items={maintenanceWindows}
|
||||||
mt={theme.spacing(5)}
|
type="maintenanceWindow"
|
||||||
|
fallbackLink="/maintenance/create"
|
||||||
>
|
>
|
||||||
<Breadcrumbs list={[{ name: "maintenance", path: "/maintenance" }]} />
|
<Stack gap={theme.spacing(10)}>
|
||||||
<Button
|
<Stack
|
||||||
variant="contained"
|
direction="row"
|
||||||
color="accent"
|
justifyContent="space-between"
|
||||||
onClick={() => {
|
alignItems="center"
|
||||||
navigate("/maintenance/create");
|
mt={theme.spacing(5)}
|
||||||
}}
|
>
|
||||||
sx={{ fontWeight: 500 }}
|
<Breadcrumbs list={[{ name: "maintenance", path: "/maintenance" }]} />
|
||||||
>
|
<Button
|
||||||
{t("createMaintenanceWindow")}
|
variant="contained"
|
||||||
</Button>
|
color="accent"
|
||||||
</Stack>
|
onClick={() => {
|
||||||
<MaintenanceTable
|
navigate("/maintenance/create");
|
||||||
page={page}
|
}}
|
||||||
setPage={setPage}
|
sx={{ fontWeight: 500 }}
|
||||||
rowsPerPage={rowsPerPage}
|
>
|
||||||
sort={sort}
|
{t("createMaintenanceWindow")}
|
||||||
setSort={setSort}
|
</Button>
|
||||||
maintenanceWindows={maintenanceWindows}
|
</Stack>
|
||||||
maintenanceWindowCount={maintenanceWindowCount}
|
<MaintenanceTable
|
||||||
updateCallback={handleActionMenuDelete}
|
page={page}
|
||||||
/>
|
setPage={setPage}
|
||||||
</Stack>
|
rowsPerPage={rowsPerPage}
|
||||||
|
sort={sort}
|
||||||
|
setSort={setSort}
|
||||||
|
maintenanceWindows={maintenanceWindows}
|
||||||
|
maintenanceWindowCount={maintenanceWindowCount}
|
||||||
|
updateCallback={handleActionMenuDelete}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</PageStateWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -89,8 +89,6 @@ const CreateNotifications = () => {
|
|||||||
error.details.forEach((err) => {
|
error.details.forEach((err) => {
|
||||||
newErrors[err.path[0]] = err.message;
|
newErrors[err.path[0]] = err.message;
|
||||||
});
|
});
|
||||||
console.log(JSON.stringify(newErrors));
|
|
||||||
console.log(JSON.stringify(form, null, 2));
|
|
||||||
createToast({ body: Object.values(newErrors)[0] });
|
createToast({ body: Object.values(newErrors)[0] });
|
||||||
setErrors(newErrors);
|
setErrors(newErrors);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Breadcrumbs from "../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../Components/Breadcrumbs";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import DataTable from "../../Components/Table";
|
import DataTable from "../../Components/Table";
|
||||||
import Fallback from "../../Components/Fallback";
|
|
||||||
import ActionMenu from "./components/ActionMenu";
|
import ActionMenu from "./components/ActionMenu";
|
||||||
|
import PageStateWrapper from "../../Components/PageStateWrapper";
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { useIsAdmin } from "../../Hooks/useIsAdmin";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
@@ -23,7 +22,6 @@ const Notifications = () => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const BREADCRUMBS = [{ name: "notifications", path: "/notifications" }];
|
const BREADCRUMBS = [{ name: "notifications", path: "/notifications" }];
|
||||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||||
const isAdmin = useIsAdmin();
|
|
||||||
const [notifications, isLoading, error] = useGetNotificationsByTeamId(updateTrigger);
|
const [notifications, isLoading, error] = useGetNotificationsByTeamId(updateTrigger);
|
||||||
const [deleteNotification, isDeleting, deleteError] = useDeleteNotification();
|
const [deleteNotification, isDeleting, deleteError] = useDeleteNotification();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -76,49 +74,47 @@ const Notifications = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (notifications?.length === 0) {
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
type="notifications"
|
|
||||||
title={t("notifications.fallback.title")}
|
|
||||||
checks={t("notifications.fallback.checks", { returnObjects: true })}
|
|
||||||
link="/notifications/create"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(10)}>
|
<>
|
||||||
<Breadcrumbs list={BREADCRUMBS} />
|
<PageStateWrapper
|
||||||
<Stack
|
networkError={error}
|
||||||
direction="row"
|
isLoading={isLoading}
|
||||||
justifyContent="flex-end"
|
items={notifications}
|
||||||
|
type="notifications"
|
||||||
|
fallbackLink="/notifications/create"
|
||||||
>
|
>
|
||||||
<Button
|
<Stack gap={theme.spacing(10)}>
|
||||||
variant="contained"
|
<Breadcrumbs list={BREADCRUMBS} />
|
||||||
color="accent"
|
<Stack
|
||||||
onClick={() => navigate("/notifications/create")}
|
direction="row"
|
||||||
>
|
justifyContent="flex-end"
|
||||||
{t("notifications.createButton")}
|
>
|
||||||
</Button>
|
<Button
|
||||||
</Stack>
|
variant="contained"
|
||||||
<Typography variant="h1">{t("notifications.createTitle")}</Typography>
|
color="accent"
|
||||||
<DataTable
|
onClick={() => navigate("/notifications/create")}
|
||||||
config={{
|
>
|
||||||
onRowClick: (row) => navigate(`/notifications/${row._id}`),
|
{t("notifications.createButton")}
|
||||||
rowSX: {
|
</Button>
|
||||||
cursor: "pointer",
|
</Stack>
|
||||||
"&:hover td": {
|
<Typography variant="h1">{t("notifications.createTitle")}</Typography>
|
||||||
backgroundColor: theme.palette.tertiary.main,
|
<DataTable
|
||||||
transition: "background-color .3s ease",
|
config={{
|
||||||
},
|
onRowClick: (row) => navigate(`/notifications/${row._id}`),
|
||||||
},
|
rowSX: {
|
||||||
}}
|
cursor: "pointer",
|
||||||
headers={headers}
|
"&:hover td": {
|
||||||
data={notifications}
|
backgroundColor: theme.palette.tertiary.main,
|
||||||
/>
|
transition: "background-color .3s ease",
|
||||||
</Stack>
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
headers={headers}
|
||||||
|
data={notifications}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</PageStateWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const NOTIFICATION_TYPES = [
|
|||||||
export const TITLE_MAP = {
|
export const TITLE_MAP = {
|
||||||
email: "createNotifications.emailSettings.title",
|
email: "createNotifications.emailSettings.title",
|
||||||
slack: "createNotifications.slackSettings.title",
|
slack: "createNotifications.slackSettings.title",
|
||||||
pager_duty: "createNotifications.pagerDutySettings.title",
|
pager_duty: "createNotifications.pagerdutySettings.title",
|
||||||
webhook: "createNotifications.webhookSettings.title",
|
webhook: "createNotifications.webhookSettings.title",
|
||||||
discord: "createNotifications.discordSettings.title",
|
discord: "createNotifications.discordSettings.title",
|
||||||
};
|
};
|
||||||
@@ -17,7 +17,7 @@ export const TITLE_MAP = {
|
|||||||
export const DESCRIPTION_MAP = {
|
export const DESCRIPTION_MAP = {
|
||||||
email: "createNotifications.emailSettings.description",
|
email: "createNotifications.emailSettings.description",
|
||||||
slack: "createNotifications.slackSettings.description",
|
slack: "createNotifications.slackSettings.description",
|
||||||
pager_duty: "createNotifications.pagerDutySettings.description",
|
pager_duty: "createNotifications.pagerdutySettings.description",
|
||||||
webhook: "createNotifications.webhookSettings.description",
|
webhook: "createNotifications.webhookSettings.description",
|
||||||
discord: "createNotifications.discordSettings.description",
|
discord: "createNotifications.discordSettings.description",
|
||||||
};
|
};
|
||||||
@@ -25,7 +25,7 @@ export const DESCRIPTION_MAP = {
|
|||||||
export const LABEL_MAP = {
|
export const LABEL_MAP = {
|
||||||
email: "createNotifications.emailSettings.emailLabel",
|
email: "createNotifications.emailSettings.emailLabel",
|
||||||
slack: "createNotifications.slackSettings.webhookLabel",
|
slack: "createNotifications.slackSettings.webhookLabel",
|
||||||
pager_duty: "createNotifications.pagerDutySettings.integrationKeyLabel",
|
pager_duty: "createNotifications.pagerdutySettings.integrationKeyLabel",
|
||||||
webhook: "createNotifications.webhookSettings.webhookLabel",
|
webhook: "createNotifications.webhookSettings.webhookLabel",
|
||||||
discord: "createNotifications.discordSettings.webhookLabel",
|
discord: "createNotifications.discordSettings.webhookLabel",
|
||||||
};
|
};
|
||||||
@@ -33,7 +33,7 @@ export const LABEL_MAP = {
|
|||||||
export const PLACEHOLDER_MAP = {
|
export const PLACEHOLDER_MAP = {
|
||||||
email: "createNotifications.emailSettings.emailPlaceholder",
|
email: "createNotifications.emailSettings.emailPlaceholder",
|
||||||
slack: "createNotifications.slackSettings.webhookPlaceholder",
|
slack: "createNotifications.slackSettings.webhookPlaceholder",
|
||||||
pager_duty: "createNotifications.pagerDutySettings.integrationKeyPlaceholder",
|
pager_duty: "createNotifications.pagerdutySettings.integrationKeyPlaceholder",
|
||||||
webhook: "createNotifications.webhookSettings.webhookPlaceholder",
|
webhook: "createNotifications.webhookSettings.webhookPlaceholder",
|
||||||
discord: "createNotifications.discordSettings.webhookPlaceholder",
|
discord: "createNotifications.discordSettings.webhookPlaceholder",
|
||||||
};
|
};
|
||||||
@@ -152,7 +152,7 @@ const PageSpeedSetup = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { error } = monitorValidation.validate(
|
const { error } = monitorValidation.validate(
|
||||||
{ [name]: value },
|
{ [name]: value, type: monitor.type },
|
||||||
{ abortEarly: false }
|
{ abortEarly: false }
|
||||||
);
|
);
|
||||||
setErrors((prev) => ({
|
setErrors((prev) => ({
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const PieChartLegend = ({ audits }) => {
|
|||||||
: theme.palette.tertiary.main;
|
: theme.palette.tertiary.main;
|
||||||
|
|
||||||
// Find the position where the number ends and the unit begins
|
// Find the position where the number ends and the unit begins
|
||||||
const match = audit.displayValue.match(/(\d+\.?\d*)\s*([a-zA-Z]+)/);
|
const match = audit?.displayValue?.match(/(\d+\.?\d*)\s*([a-zA-Z]+)/);
|
||||||
let value;
|
let value;
|
||||||
let unit;
|
let unit;
|
||||||
if (match) {
|
if (match) {
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
// Components
|
// Components
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||||
import { Stack, Typography } from "@mui/material";
|
import { Stack } from "@mui/material";
|
||||||
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
||||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||||
import MonitorGrid from "./Components/MonitorGrid";
|
import MonitorGrid from "./Components/MonitorGrid";
|
||||||
import Fallback from "../../../Components/Fallback";
|
import PageStateWrapper from "../../../Components/PageStateWrapper";
|
||||||
import GenericFallback from "../../../Components/GenericFallback";
|
|
||||||
import FallbackPageSpeedWarning from "../../../Components/Fallback/FallbackPageSpeedWarning";
|
import FallbackPageSpeedWarning from "../../../Components/Fallback/FallbackPageSpeedWarning";
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { useFetchMonitorsByTeamId } from "../../../Hooks/monitorHooks";
|
import { useFetchMonitorsByTeamId } from "../../../Hooks/monitorHooks";
|
||||||
import { useFetchSettings } from "../../../Hooks/settingsHooks";
|
import { useFetchSettings } from "../../../Hooks/settingsHooks";
|
||||||
// Constants
|
// Constants
|
||||||
@@ -20,7 +18,6 @@ const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
|
|||||||
const TYPES = ["pagespeed"];
|
const TYPES = ["pagespeed"];
|
||||||
const PageSpeed = () => {
|
const PageSpeed = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
|
||||||
const isAdmin = useIsAdmin();
|
const isAdmin = useIsAdmin();
|
||||||
|
|
||||||
const [monitors, monitorsSummary, isLoading, networkError] = useFetchMonitorsByTeamId({
|
const [monitors, monitorsSummary, isLoading, networkError] = useFetchMonitorsByTeamId({
|
||||||
@@ -40,56 +37,42 @@ const PageSpeed = () => {
|
|||||||
setIsEmailPasswordSet: () => {},
|
setIsEmailPasswordSet: () => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (networkError === true) {
|
|
||||||
return (
|
|
||||||
<GenericFallback>
|
|
||||||
<Typography
|
|
||||||
variant="h1"
|
|
||||||
marginY={theme.spacing(4)}
|
|
||||||
color={theme.palette.primary.contrastTextTertiary}
|
|
||||||
>
|
|
||||||
{t("common.toasts.networkError")}
|
|
||||||
</Typography>
|
|
||||||
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
|
||||||
</GenericFallback>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLoading && monitors?.length === 0) {
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
type="pageSpeed"
|
|
||||||
title={t("pageSpeed.fallback.title")}
|
|
||||||
checks={t("pageSpeed.fallback.checks", { returnObjects: true })}
|
|
||||||
link="/pagespeed/create"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
>
|
|
||||||
{isAdmin && settingsData && !settingsData.pagespeedApiKey && (
|
|
||||||
<FallbackPageSpeedWarning settingsData={settingsData} />
|
|
||||||
)}
|
|
||||||
</Fallback>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(10)}>
|
<>
|
||||||
<Breadcrumbs list={BREADCRUMBS} />
|
<PageStateWrapper
|
||||||
<CreateMonitorHeader
|
networkError={networkError}
|
||||||
isAdmin={isAdmin}
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
path="/pagespeed/create"
|
items={monitors}
|
||||||
/>
|
type="pageSpeed"
|
||||||
<MonitorCountHeader
|
fallbackLink="/pagespeed/create"
|
||||||
isLoading={isLoading}
|
fallbackChildren={
|
||||||
monitorCount={monitorsSummary?.totalMonitors}
|
isAdmin &&
|
||||||
sx={{ mb: theme.spacing(8) }}
|
settingsData &&
|
||||||
/>
|
!settingsData.pagespeedApiKey && (
|
||||||
<MonitorGrid
|
<FallbackPageSpeedWarning settingsData={settingsData} />
|
||||||
size={6}
|
)
|
||||||
shouldRender={!isLoading}
|
}
|
||||||
monitors={monitors}
|
>
|
||||||
/>
|
<Stack gap={theme.spacing(10)}>
|
||||||
</Stack>
|
<Breadcrumbs list={BREADCRUMBS} />
|
||||||
|
<CreateMonitorHeader
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
isLoading={isLoading}
|
||||||
|
path="/pagespeed/create"
|
||||||
|
/>
|
||||||
|
<MonitorCountHeader
|
||||||
|
isLoading={isLoading}
|
||||||
|
monitorCount={monitorsSummary?.totalMonitors}
|
||||||
|
sx={{ mb: theme.spacing(8) }}
|
||||||
|
/>
|
||||||
|
<MonitorGrid
|
||||||
|
size={6}
|
||||||
|
shouldRender={!isLoading}
|
||||||
|
monitors={monitors}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</PageStateWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const SettingsURL = ({ HEADING_SX, handleChange, showURL = false }) => {
|
|||||||
<Select
|
<Select
|
||||||
name="showURL"
|
name="showURL"
|
||||||
label={t("settingsPage.urlSettings.label")}
|
label={t("settingsPage.urlSettings.label")}
|
||||||
value={showURL || ""}
|
value={showURL === true}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
items={[
|
items={[
|
||||||
{ _id: true, name: t("settingsPage.urlSettings.selectEnabled") },
|
{ _id: true, name: t("settingsPage.urlSettings.selectEnabled") },
|
||||||
|
|||||||
@@ -11,7 +11,12 @@ import PropTypes from "prop-types";
|
|||||||
|
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
const MonitorsList = ({ isLoading = false, shouldRender = true, monitors = [] }) => {
|
const MonitorsList = ({
|
||||||
|
isLoading = false,
|
||||||
|
shouldRender = true,
|
||||||
|
monitors = [],
|
||||||
|
statusPage = {},
|
||||||
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { determineState } = useMonitorUtils();
|
const { determineState } = useMonitorUtils();
|
||||||
|
|
||||||
@@ -40,10 +45,12 @@ const MonitorsList = ({ isLoading = false, shouldRender = true, monitors = [] })
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
gap={theme.spacing(20)}
|
gap={theme.spacing(20)}
|
||||||
>
|
>
|
||||||
<Box flex={9}>
|
{statusPage.showCharts !== false && (
|
||||||
<StatusPageBarChart checks={monitor?.checks?.slice().reverse()} />
|
<Box flex={9}>
|
||||||
</Box>
|
<StatusPageBarChart checks={monitor?.checks?.slice().reverse()} />
|
||||||
<Box flex={1}>
|
</Box>
|
||||||
|
)}
|
||||||
|
<Box flex={statusPage.showCharts !== false ? 1 : 10}>
|
||||||
<StatusLabel
|
<StatusLabel
|
||||||
status={status}
|
status={status}
|
||||||
text={status}
|
text={status}
|
||||||
@@ -60,6 +67,7 @@ const MonitorsList = ({ isLoading = false, shouldRender = true, monitors = [] })
|
|||||||
|
|
||||||
MonitorsList.propTypes = {
|
MonitorsList.propTypes = {
|
||||||
monitors: PropTypes.array.isRequired,
|
monitors: PropTypes.array.isRequired,
|
||||||
|
statusPage: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MonitorsList;
|
export default MonitorsList;
|
||||||
@@ -154,7 +154,10 @@ const PublicStatus = () => {
|
|||||||
/>
|
/>
|
||||||
<Typography variant="h2">{t("statusPageStatusServiceStatus")}</Typography>
|
<Typography variant="h2">{t("statusPageStatusServiceStatus")}</Typography>
|
||||||
<StatusBar monitors={monitors} />
|
<StatusBar monitors={monitors} />
|
||||||
<MonitorsList monitors={monitors} />
|
<MonitorsList
|
||||||
|
monitors={monitors}
|
||||||
|
statusPage={statusPage}
|
||||||
|
/>
|
||||||
{link}
|
{link}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
// Components
|
// Components
|
||||||
import { Stack, Typography } from "@mui/material";
|
import { Stack } from "@mui/material";
|
||||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||||
import Fallback from "../../../Components/Fallback";
|
|
||||||
import MonitorCreateHeader from "../../../Components/MonitorCreateHeader";
|
import MonitorCreateHeader from "../../../Components/MonitorCreateHeader";
|
||||||
import GenericFallback from "../../../Components/GenericFallback";
|
|
||||||
import StatusPagesTable from "./Components/StatusPagesTable";
|
import StatusPagesTable from "./Components/StatusPagesTable";
|
||||||
import SkeletonLayout from "../../../Components/Skeletons/FullPage";
|
import PageStateWrapper from "../../../Components/PageStateWrapper";
|
||||||
// Utils
|
// Utils
|
||||||
import { useTheme } from "@emotion/react";
|
import { useTheme } from "@emotion/react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { useStatusPagesFetch } from "./Hooks/useStatusPagesFetch";
|
import { useStatusPagesFetch } from "./Hooks/useStatusPagesFetch";
|
||||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||||
const BREADCRUMBS = [{ name: `Status Pages`, path: "" }];
|
const BREADCRUMBS = [{ name: `Status Pages`, path: "" }];
|
||||||
@@ -16,52 +13,30 @@ const BREADCRUMBS = [{ name: `Status Pages`, path: "" }];
|
|||||||
const StatusPages = () => {
|
const StatusPages = () => {
|
||||||
// Utils
|
// Utils
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
|
||||||
const isAdmin = useIsAdmin();
|
const isAdmin = useIsAdmin();
|
||||||
const [isLoading, networkError, statusPages] = useStatusPagesFetch();
|
const [isLoading, networkError, statusPages] = useStatusPagesFetch();
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <SkeletonLayout />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkError === true) {
|
|
||||||
return (
|
|
||||||
<GenericFallback>
|
|
||||||
<Typography
|
|
||||||
variant="h1"
|
|
||||||
marginY={theme.spacing(4)}
|
|
||||||
color={theme.palette.primary.contrastTextTertiary}
|
|
||||||
>
|
|
||||||
{t("common.toasts.networkError")}
|
|
||||||
</Typography>
|
|
||||||
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
|
||||||
</GenericFallback>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLoading && typeof statusPages !== "undefined" && statusPages.length === 0) {
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
title={t("statusPage.fallback.title")}
|
|
||||||
checks={t("statusPage.fallback.checks", { returnObjects: true })}
|
|
||||||
type="statusPage"
|
|
||||||
link="/status/uptime/create"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={theme.spacing(10)}>
|
<>
|
||||||
<Breadcrumbs list={BREADCRUMBS} />
|
<PageStateWrapper
|
||||||
<MonitorCreateHeader
|
networkError={networkError}
|
||||||
label="Create status page"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
path="/status/uptime/create"
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
items={statusPages}
|
||||||
<StatusPagesTable data={statusPages} />
|
type="statusPage"
|
||||||
</Stack>
|
fallbackLink="/status/uptime/create"
|
||||||
|
>
|
||||||
|
<Stack gap={theme.spacing(10)}>
|
||||||
|
<Breadcrumbs list={BREADCRUMBS} />
|
||||||
|
<MonitorCreateHeader
|
||||||
|
label="Create status page"
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
path="/status/uptime/create"
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<StatusPagesTable data={statusPages} />
|
||||||
|
</Stack>
|
||||||
|
</PageStateWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,20 +44,6 @@ import {
|
|||||||
useFetchMonitorGames,
|
useFetchMonitorGames,
|
||||||
} from "../../../Hooks/monitorHooks";
|
} from "../../../Hooks/monitorHooks";
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a URL string and returns a URL object.
|
|
||||||
*
|
|
||||||
* @param {string} url - The URL string to parse.
|
|
||||||
* @returns {URL} - The parsed URL object if valid, otherwise an empty string.
|
|
||||||
*/
|
|
||||||
const parseUrl = (url) => {
|
|
||||||
try {
|
|
||||||
return new URL(url);
|
|
||||||
} catch (error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create page renders monitor creation or configuration views.
|
* Create page renders monitor creation or configuration views.
|
||||||
* @component
|
* @component
|
||||||
@@ -69,6 +55,8 @@ const UptimeCreate = ({ isClone = false }) => {
|
|||||||
// States
|
// States
|
||||||
const [monitor, setMonitor] = useState({
|
const [monitor, setMonitor] = useState({
|
||||||
type: "http",
|
type: "http",
|
||||||
|
statusWindowSize: 5,
|
||||||
|
statusWindowThreshold: 60,
|
||||||
matchMethod: "equal",
|
matchMethod: "equal",
|
||||||
expectedValue: "",
|
expectedValue: "",
|
||||||
jsonPath: "",
|
jsonPath: "",
|
||||||
@@ -191,7 +179,10 @@ const UptimeCreate = ({ isClone = false }) => {
|
|||||||
? `http${https ? "s" : ""}://` + monitor.url
|
? `http${https ? "s" : ""}://` + monitor.url
|
||||||
: monitor.url,
|
: monitor.url,
|
||||||
name: monitor.name || monitor.url.substring(0, 50),
|
name: monitor.name || monitor.url.substring(0, 50),
|
||||||
|
statusWindowSize: monitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: monitor.statusWindowThreshold,
|
||||||
type: monitor.type,
|
type: monitor.type,
|
||||||
|
|
||||||
port:
|
port:
|
||||||
monitor.type === "port" || monitor.type === "game" ? monitor.port : undefined,
|
monitor.type === "port" || monitor.type === "game" ? monitor.port : undefined,
|
||||||
interval: monitor.interval,
|
interval: monitor.interval,
|
||||||
@@ -206,6 +197,8 @@ const UptimeCreate = ({ isClone = false }) => {
|
|||||||
_id: monitor._id,
|
_id: monitor._id,
|
||||||
url: monitor.url,
|
url: monitor.url,
|
||||||
name: monitor.name || monitor.url.substring(0, 50),
|
name: monitor.name || monitor.url.substring(0, 50),
|
||||||
|
statusWindowSize: monitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: monitor.statusWindowThreshold,
|
||||||
type: monitor.type,
|
type: monitor.type,
|
||||||
matchMethod: monitor.matchMethod,
|
matchMethod: monitor.matchMethod,
|
||||||
expectedValue: monitor.expectedValue,
|
expectedValue: monitor.expectedValue,
|
||||||
@@ -299,7 +292,7 @@ const UptimeCreate = ({ isClone = false }) => {
|
|||||||
|
|
||||||
const isBusy = isLoading || isCreating || isDeleting || isUpdating || isPausing;
|
const isBusy = isLoading || isCreating || isDeleting || isUpdating || isPausing;
|
||||||
const displayInterval = monitor?.interval / MS_PER_MINUTE || 1;
|
const displayInterval = monitor?.interval / MS_PER_MINUTE || 1;
|
||||||
const parsedUrl = parseUrl(monitor?.url);
|
const parsedUrl = monitor?.url;
|
||||||
const protocol = parsedUrl?.protocol?.replace(":", "") || "";
|
const protocol = parsedUrl?.protocol?.replace(":", "") || "";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -616,6 +609,39 @@ const UptimeCreate = ({ isClone = false }) => {
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</ConfigBox>
|
</ConfigBox>
|
||||||
|
<ConfigBox>
|
||||||
|
<Box>
|
||||||
|
<Typography
|
||||||
|
component="h2"
|
||||||
|
variant="h2"
|
||||||
|
>
|
||||||
|
{t("createMonitorPage.incidentConfigTitle")}
|
||||||
|
</Typography>
|
||||||
|
<Typography component="p">
|
||||||
|
{t("createMonitorPage.incidentConfigDescription")}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Stack gap={theme.spacing(20)}>
|
||||||
|
<TextInput
|
||||||
|
name="statusWindowSize"
|
||||||
|
label={t("createMonitorPage.incidentConfigStatusWindowLabel")}
|
||||||
|
type="number"
|
||||||
|
value={monitor.statusWindowSize}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors["statusWindowSize"] ? true : false}
|
||||||
|
helperText={errors["statusWindowSize"]}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
name="statusWindowThreshold"
|
||||||
|
label={t("createMonitorPage.incidentConfigStatusWindowThresholdLabel")}
|
||||||
|
type="number"
|
||||||
|
value={monitor.statusWindowThreshold}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors["statusWindowThreshold"] ? true : false}
|
||||||
|
helperText={errors["statusWindowThreshold"]}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</ConfigBox>
|
||||||
<ConfigBox>
|
<ConfigBox>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
|
|||||||
@@ -10,16 +10,14 @@ import StatusBoxes from "./Components/StatusBoxes";
|
|||||||
import UptimeDataTable from "./Components/UptimeDataTable";
|
import UptimeDataTable from "./Components/UptimeDataTable";
|
||||||
import Pagination from "../../../Components/Table/TablePagination";
|
import Pagination from "../../../Components/Table/TablePagination";
|
||||||
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
||||||
import Fallback from "../../../Components/Fallback";
|
|
||||||
import GenericFallback from "../../../Components/GenericFallback";
|
|
||||||
import SearchComponent from "./Components/SearchComponent";
|
import SearchComponent from "./Components/SearchComponent";
|
||||||
import Filter from "./Components/Filter";
|
import Filter from "./Components/Filter";
|
||||||
|
import PageStateWrapper from "../../../Components/PageStateWrapper";
|
||||||
|
|
||||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||||
|
|
||||||
// MUI Components
|
// MUI Components
|
||||||
import { Stack, Box, Button, Typography } from "@mui/material";
|
import { Stack, Box, Button } from "@mui/material";
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { useState, useCallback, useEffect } from "react";
|
import { useState, useCallback, useEffect } from "react";
|
||||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||||
@@ -153,93 +151,75 @@ const UptimeMonitors = () => {
|
|||||||
}, [isSearching]);
|
}, [isSearching]);
|
||||||
|
|
||||||
const isLoading = monitorsWithSummaryIsLoading || monitorsWithChecksIsLoading;
|
const isLoading = monitorsWithSummaryIsLoading || monitorsWithChecksIsLoading;
|
||||||
if (networkError) {
|
|
||||||
return (
|
|
||||||
<GenericFallback>
|
|
||||||
<Typography
|
|
||||||
variant="h1"
|
|
||||||
marginY={theme.spacing(4)}
|
|
||||||
color={theme.palette.primary.contrastTextTertiary}
|
|
||||||
>
|
|
||||||
{t("common.toasts.networkError")}
|
|
||||||
</Typography>
|
|
||||||
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
|
||||||
</GenericFallback>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!isLoading &&
|
|
||||||
(monitorsSummary?.totalMonitors === 0 ||
|
|
||||||
typeof monitorsSummary?.totalMonitors === "undefined")
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
type="uptimeMonitor"
|
|
||||||
title={t("uptimeMonitor.fallback.title")}
|
|
||||||
checks={t("uptimeMonitor.fallback.checks", { returnObjects: true })}
|
|
||||||
link="/uptime/create"
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Stack
|
|
||||||
className="monitors"
|
|
||||||
gap={theme.spacing(10)}
|
|
||||||
>
|
|
||||||
<Breadcrumbs list={BREADCRUMBS} />
|
|
||||||
<CreateMonitorHeader
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
isLoading={isLoading}
|
|
||||||
path="/uptime/create"
|
|
||||||
bulkPath="/uptime/bulk-import"
|
|
||||||
/>
|
|
||||||
<Greeting type="uptime" />
|
|
||||||
<StatusBoxes
|
|
||||||
monitorsSummary={monitorsSummary}
|
|
||||||
shouldRender={!monitorsWithSummaryIsLoading}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack direction={"row"}>
|
return (
|
||||||
<MonitorCountHeader
|
<>
|
||||||
isLoading={monitorsWithSummaryIsLoading}
|
<PageStateWrapper
|
||||||
monitorCount={monitorsSummary?.totalMonitors}
|
networkError={networkError}
|
||||||
/>
|
isLoading={isLoading}
|
||||||
<Filter
|
items={monitors}
|
||||||
selectedTypes={selectedTypes}
|
type="uptimeMonitor"
|
||||||
setSelectedTypes={setSelectedTypes}
|
fallbackLink="/uptime/create"
|
||||||
selectedStatus={selectedStatus}
|
>
|
||||||
setSelectedStatus={setSelectedStatus}
|
<Stack
|
||||||
selectedState={selectedState}
|
className="monitors"
|
||||||
setSelectedState={setSelectedState}
|
gap={theme.spacing(10)}
|
||||||
setToFilterStatus={setToFilterStatus}
|
>
|
||||||
setToFilterActive={setToFilterActive}
|
<Breadcrumbs list={BREADCRUMBS} />
|
||||||
handleReset={handleReset}
|
<CreateMonitorHeader
|
||||||
/>
|
isAdmin={isAdmin}
|
||||||
<SearchComponent
|
isLoading={isLoading}
|
||||||
monitors={monitors}
|
path="/uptime/create"
|
||||||
onSearchChange={setSearch}
|
bulkPath="/uptime/bulk-import"
|
||||||
setIsSearching={setIsSearching}
|
/>
|
||||||
/>
|
<Greeting type="uptime" />
|
||||||
</Stack>
|
<StatusBoxes
|
||||||
<UptimeDataTable
|
monitorsSummary={monitorsSummary}
|
||||||
isAdmin={isAdmin}
|
shouldRender={!monitorsWithSummaryIsLoading}
|
||||||
isSearching={isSearching}
|
/>
|
||||||
filteredMonitors={monitorsWithChecks}
|
|
||||||
sort={sort}
|
<Stack direction={"row"}>
|
||||||
setSort={setSort}
|
<MonitorCountHeader
|
||||||
monitorsAreLoading={monitorsWithChecksIsLoading}
|
isLoading={monitorsWithSummaryIsLoading}
|
||||||
triggerUpdate={triggerUpdate}
|
monitorCount={monitorsSummary?.totalMonitors}
|
||||||
/>
|
/>
|
||||||
<Pagination
|
<Filter
|
||||||
itemCount={monitorsWithChecksCount}
|
selectedTypes={selectedTypes}
|
||||||
paginationLabel="monitors"
|
setSelectedTypes={setSelectedTypes}
|
||||||
page={page}
|
selectedStatus={selectedStatus}
|
||||||
rowsPerPage={rowsPerPage}
|
setSelectedStatus={setSelectedStatus}
|
||||||
handleChangePage={handleChangePage}
|
selectedState={selectedState}
|
||||||
handleChangeRowsPerPage={handleChangeRowsPerPage}
|
setSelectedState={setSelectedState}
|
||||||
/>
|
setToFilterStatus={setToFilterStatus}
|
||||||
</Stack>
|
setToFilterActive={setToFilterActive}
|
||||||
|
handleReset={handleReset}
|
||||||
|
/>
|
||||||
|
<SearchComponent
|
||||||
|
monitors={monitors}
|
||||||
|
onSearchChange={setSearch}
|
||||||
|
setIsSearching={setIsSearching}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
<UptimeDataTable
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
isSearching={isSearching}
|
||||||
|
filteredMonitors={monitorsWithChecks}
|
||||||
|
sort={sort}
|
||||||
|
setSort={setSort}
|
||||||
|
monitorsAreLoading={monitorsWithChecksIsLoading}
|
||||||
|
triggerUpdate={triggerUpdate}
|
||||||
|
/>
|
||||||
|
<Pagination
|
||||||
|
itemCount={monitorsWithChecksCount}
|
||||||
|
paginationLabel="monitors"
|
||||||
|
page={page}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
handleChangePage={handleChangePage}
|
||||||
|
handleChangeRowsPerPage={handleChangeRowsPerPage}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</PageStateWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ const Routes = () => {
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/register/:token"
|
path="/register/:token"
|
||||||
element={<AuthRegister />}
|
element={<AuthRegister superAdminExists={true} />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
@@ -564,6 +564,10 @@ const baseTheme = (palette) => ({
|
|||||||
"& .MuiSelect-icon": {
|
"& .MuiSelect-icon": {
|
||||||
color: theme.palette.primary.contrastTextSecondary, // Dropdown + color
|
color: theme.palette.primary.contrastTextSecondary, // Dropdown + color
|
||||||
},
|
},
|
||||||
|
"& .MuiSelect-select": {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: theme.palette.primary.main, // Background on hover
|
backgroundColor: theme.palette.primary.main, // Background on hover
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -115,15 +115,27 @@ const monitorValidation = joi.object({
|
|||||||
_id: joi.string(),
|
_id: joi.string(),
|
||||||
userId: joi.string(),
|
userId: joi.string(),
|
||||||
teamId: joi.string(),
|
teamId: joi.string(),
|
||||||
|
statusWindowSize: joi.number().min(1).max(20).default(5).messages({
|
||||||
|
"number.base": "Status window size must be a number.",
|
||||||
|
"number.min": "Status window size must be at least 1.",
|
||||||
|
"number.max": "Status window size must be at most 20.",
|
||||||
|
}),
|
||||||
|
statusWindowThreshold: joi.number().min(1).max(100).default(60).messages({
|
||||||
|
"number.base": "Incident percentage must be a number.",
|
||||||
|
"number.min": "Incident percentage must be at least 1.",
|
||||||
|
"number.max": "Incident percentage must be at most 100.",
|
||||||
|
}),
|
||||||
url: joi.when("type", {
|
url: joi.when("type", {
|
||||||
is: "docker",
|
is: "docker",
|
||||||
then: joi
|
then: joi
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
.regex(/^[a-z0-9]{64}$/)
|
.regex(
|
||||||
|
/^(\/+)?([a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9]|[a-zA-Z0-9]+|[a-f0-9]{12,64})$/
|
||||||
|
)
|
||||||
.messages({
|
.messages({
|
||||||
"string.empty": "This field is required.",
|
"string.empty": "This field is required.",
|
||||||
"string.pattern.base": "Please enter a valid 64-character Docker container ID.",
|
"string.pattern.base": "Please enter a valid container name or ID.",
|
||||||
}),
|
}),
|
||||||
otherwise: joi
|
otherwise: joi
|
||||||
.string()
|
.string()
|
||||||
@@ -150,6 +162,11 @@ const monitorValidation = joi.object({
|
|||||||
// can be replaced by a shortest alternative
|
// can be replaced by a shortest alternative
|
||||||
// (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
|
// (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
|
||||||
"(?:" +
|
"(?:" +
|
||||||
|
// Single hostname without dots (like localhost)
|
||||||
|
"[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
||||||
|
"|" +
|
||||||
|
// Domain with dots
|
||||||
|
"(?:" +
|
||||||
"(?:" +
|
"(?:" +
|
||||||
"[a-z0-9\\u00a1-\\uffff]" +
|
"[a-z0-9\\u00a1-\\uffff]" +
|
||||||
"[a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
"[a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
||||||
@@ -159,6 +176,7 @@ const monitorValidation = joi.object({
|
|||||||
// TLD identifier name, may end with dot
|
// TLD identifier name, may end with dot
|
||||||
"(?:[a-z\\u00a1-\\uffff]{2,}\\.?)" +
|
"(?:[a-z\\u00a1-\\uffff]{2,}\\.?)" +
|
||||||
")" +
|
")" +
|
||||||
|
")" +
|
||||||
// port number (optional)
|
// port number (optional)
|
||||||
"(?::\\d{2,5})?" +
|
"(?::\\d{2,5})?" +
|
||||||
// resource path (optional)
|
// resource path (optional)
|
||||||
@@ -419,6 +437,16 @@ const infrastructureMonitorValidation = joi.object({
|
|||||||
"number.base": "Frequency must be a number.",
|
"number.base": "Frequency must be a number.",
|
||||||
"any.required": "Frequency is required.",
|
"any.required": "Frequency is required.",
|
||||||
}),
|
}),
|
||||||
|
statusWindowSize: joi.number().min(1).max(20).messages({
|
||||||
|
"number.base": "Status window size must be a number.",
|
||||||
|
"number.min": "Status window size must be at least 1.",
|
||||||
|
"number.max": "Status window size cannot exceed 20.",
|
||||||
|
}),
|
||||||
|
statusWindowThreshold: joi.number().min(1).max(100).messages({
|
||||||
|
"number.base": "Status window threshold must be a number.",
|
||||||
|
"number.min": "Status window threshold must be at least 1%.",
|
||||||
|
"number.max": "Status window threshold cannot exceed 100%.",
|
||||||
|
}),
|
||||||
notifications: joi.array().items(joi.string()),
|
notifications: joi.array().items(joi.string()),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -439,21 +467,35 @@ const notificationValidation = joi.object({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
address: joi.when("type", {
|
address: joi.when("type", {
|
||||||
is: "email",
|
switch: [
|
||||||
then: joi
|
{
|
||||||
.string()
|
is: "email",
|
||||||
.email({ tlds: { allow: false } })
|
then: joi
|
||||||
.required()
|
.string()
|
||||||
.messages({
|
.email({ tlds: { allow: false } })
|
||||||
"string.empty": "E-mail address cannot be empty",
|
.required()
|
||||||
"any.required": "E-mail address is required",
|
.messages({
|
||||||
"string.email": "Please enter a valid e-mail address",
|
"string.empty": "E-mail address cannot be empty",
|
||||||
}),
|
"any.required": "E-mail address is required",
|
||||||
otherwise: joi.string().uri().required().messages({
|
"string.email": "Please enter a valid e-mail address",
|
||||||
"string.empty": "Webhook URL cannot be empty",
|
}),
|
||||||
"any.required": "Webhook URL is required",
|
},
|
||||||
"string.uri": "Please enter a valid Webhook URL",
|
{
|
||||||
}),
|
is: "pager_duty",
|
||||||
|
then: joi.string().required().messages({
|
||||||
|
"string.empty": "PagerDuty routing key cannot be empty",
|
||||||
|
"any.required": "PagerDuty routing key is required",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
is: joi.valid("webhook", "slack", "discord"),
|
||||||
|
then: joi.string().uri().required().messages({
|
||||||
|
"string.empty": "Webhook URL cannot be empty",
|
||||||
|
"any.required": "Webhook URL is required",
|
||||||
|
"string.uri": "Please enter a valid Webhook URL",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+133
-7
@@ -260,7 +260,6 @@
|
|||||||
"notifyEmails": "",
|
"notifyEmails": "",
|
||||||
"seperateEmails": "",
|
"seperateEmails": "",
|
||||||
"checkFrequency": "",
|
"checkFrequency": "",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "",
|
"matchMethod": "",
|
||||||
"expectedValue": "",
|
"expectedValue": "",
|
||||||
"deleteDialogTitle": "",
|
"deleteDialogTitle": "",
|
||||||
@@ -377,7 +376,52 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"role": "",
|
"role": "",
|
||||||
"created": ""
|
"created": ""
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "",
|
"paused": "",
|
||||||
@@ -569,7 +613,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -595,7 +640,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": ""
|
"success": ""
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
@@ -741,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -847,6 +894,10 @@
|
|||||||
"selectDisabled": "",
|
"selectDisabled": "",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -915,7 +966,12 @@
|
|||||||
"twentyMinutes": "",
|
"twentyMinutes": "",
|
||||||
"oneHour": "",
|
"oneHour": "",
|
||||||
"oneDay": "",
|
"oneDay": "",
|
||||||
"oneWeek": ""
|
"oneWeek": "",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -967,5 +1023,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+133
-7
@@ -260,7 +260,6 @@
|
|||||||
"notifyEmails": "",
|
"notifyEmails": "",
|
||||||
"seperateEmails": "",
|
"seperateEmails": "",
|
||||||
"checkFrequency": "",
|
"checkFrequency": "",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "",
|
"matchMethod": "",
|
||||||
"expectedValue": "",
|
"expectedValue": "",
|
||||||
"deleteDialogTitle": "",
|
"deleteDialogTitle": "",
|
||||||
@@ -377,7 +376,52 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"role": "",
|
"role": "",
|
||||||
"created": ""
|
"created": ""
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "",
|
"paused": "",
|
||||||
@@ -569,7 +613,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -595,7 +640,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "Vítejte! Váš účet byl úspěšně vytvořen."
|
"success": "Vítejte! Váš účet byl úspěšně vytvořen."
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "Zapomenuté heslo",
|
"heading": "Zapomenuté heslo",
|
||||||
@@ -741,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -847,6 +894,10 @@
|
|||||||
"selectDisabled": "",
|
"selectDisabled": "",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -915,7 +966,12 @@
|
|||||||
"twentyMinutes": "",
|
"twentyMinutes": "",
|
||||||
"oneHour": "",
|
"oneHour": "",
|
||||||
"oneDay": "",
|
"oneDay": "",
|
||||||
"oneWeek": ""
|
"oneWeek": "",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -967,5 +1023,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+373
-222
@@ -51,14 +51,14 @@
|
|||||||
"label": "Slack",
|
"label": "Slack",
|
||||||
"description": "Um Slack-Benachrichtigungen zu aktivieren, erstelle eine Slack-App und aktiviere eingehende Webhooks. Danach gib einfach die Webhook-URL hier ein.",
|
"description": "Um Slack-Benachrichtigungen zu aktivieren, erstelle eine Slack-App und aktiviere eingehende Webhooks. Danach gib einfach die Webhook-URL hier ein.",
|
||||||
"webhookLabel": "Webhook URL",
|
"webhookLabel": "Webhook URL",
|
||||||
"webhookPlaceholder": "",
|
"webhookPlaceholder": "https://hooks.slack.com/services/...",
|
||||||
"webhookRequired": "Slack webhook URL wird benötigt"
|
"webhookRequired": "Slack webhook URL wird benötigt"
|
||||||
},
|
},
|
||||||
"discord": {
|
"discord": {
|
||||||
"label": "Discord",
|
"label": "Discord",
|
||||||
"description": "Um Daten von Checkmate an einen Discord-Kanal über Discord-Benachrichtigungen mithilfe von Webhooks zu senden, kannst Du die eingehenden Webhooks von Discord verwenden.",
|
"description": "Um Daten von Checkmate an einen Discord-Kanal über Discord-Benachrichtigungen mithilfe von Webhooks zu senden, kannst Du die eingehenden Webhooks von Discord verwenden.",
|
||||||
"webhookLabel": "Discord Webhook URL",
|
"webhookLabel": "Discord Webhook URL",
|
||||||
"webhookPlaceholder": "",
|
"webhookPlaceholder": "https://discord.com/api/webhooks/...",
|
||||||
"webhookRequired": "Discord webhook URL wird benötigt"
|
"webhookRequired": "Discord webhook URL wird benötigt"
|
||||||
},
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
@@ -78,33 +78,37 @@
|
|||||||
"urlRequired": "Webhook URL wird benötigt"
|
"urlRequired": "Webhook URL wird benötigt"
|
||||||
},
|
},
|
||||||
"testNotificationDevelop": "Testbenachrichtigung 2",
|
"testNotificationDevelop": "Testbenachrichtigung 2",
|
||||||
"integrationButton": "",
|
"integrationButton": "Benachrichtigungsintegration",
|
||||||
"testSuccess": "",
|
"testSuccess": "Testbenachrichtigung erfolgreich gesendet!",
|
||||||
"testFailed": "",
|
"testFailed": "Senden der Testbenachrichtigung fehlgeschlagen",
|
||||||
"unsupportedType": "",
|
"unsupportedType": "Nicht unterstützter Benachrichtigungstyp",
|
||||||
"networkError": "",
|
"networkError": "Netzwerkfehler aufgetreten",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"title": "",
|
"title": "Ein Benachrichtigungskanal wird verwendet, um:",
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"actionButton": ""
|
"Teams über Ausfallzeiten oder Leistungsprobleme informieren",
|
||||||
|
"Informieren Sie Techniker über Vorfälle",
|
||||||
|
"Informieren Sie Administratoren über Systemänderungen"
|
||||||
|
],
|
||||||
|
"actionButton": "Lassen Sie uns Ihren ersten Benachrichtigungskanal erstellen!"
|
||||||
},
|
},
|
||||||
"createButton": "",
|
"createButton": "Benachrichtigungskanal erstellen",
|
||||||
"createTitle": "",
|
"createTitle": "Benachrichtigungskanal",
|
||||||
"create": {
|
"create": {
|
||||||
"success": "",
|
"success": "Benachrichtigung erfolgreich erstellt",
|
||||||
"failed": ""
|
"failed": "Benachrichtigung konnte nicht erstellt werden"
|
||||||
},
|
},
|
||||||
"fetch": {
|
"fetch": {
|
||||||
"success": "",
|
"success": "Benachrichtigungen erfolgreich abgerufen",
|
||||||
"failed": ""
|
"failed": "Abrufen der Benachrichtigungen fehlgeschlagen"
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"success": "",
|
"success": "Benachrichtigung erfolgreich gelöscht",
|
||||||
"failed": ""
|
"failed": "Benachrichtigung konnte nicht gelöscht werden"
|
||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"success": "",
|
"success": "Benachrichtigung erfolgreich aktualisiert",
|
||||||
"failed": ""
|
"failed": "Benachrichtigung konnte nicht aktualisiert werden"
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"success": "Test Benachrichtigung erfolgreich gesendet",
|
"success": "Test Benachrichtigung erfolgreich gesendet",
|
||||||
@@ -227,7 +231,7 @@
|
|||||||
"createMaintenance": "Erstelle Wartungsfenster",
|
"createMaintenance": "Erstelle Wartungsfenster",
|
||||||
"editMaintenance": "Ändere Wartungsfenster",
|
"editMaintenance": "Ändere Wartungsfenster",
|
||||||
"maintenanceWindowName": "Name des Wartungsfensters",
|
"maintenanceWindowName": "Name des Wartungsfensters",
|
||||||
"friendlyNameInput": "",
|
"friendlyNameInput": "Freundlicher Name",
|
||||||
"friendlyNamePlaceholder": "Wartung um __ : __ für ___ Minuten",
|
"friendlyNamePlaceholder": "Wartung um __ : __ für ___ Minuten",
|
||||||
"maintenanceRepeat": "Wartungsfenster wiederholen",
|
"maintenanceRepeat": "Wartungsfenster wiederholen",
|
||||||
"maintenance": "Wartungsfenster",
|
"maintenance": "Wartungsfenster",
|
||||||
@@ -247,7 +251,7 @@
|
|||||||
"edit": "Ändern",
|
"edit": "Ändern",
|
||||||
"createA": "Erstelle ein",
|
"createA": "Erstelle ein",
|
||||||
"remove": "Löschen",
|
"remove": "Löschen",
|
||||||
"maintenanceWindowDescription": "",
|
"maintenanceWindowDescription": "Pings werden während dieses Zeitraums nicht gesendet",
|
||||||
"startTime": "Anfangszeit",
|
"startTime": "Anfangszeit",
|
||||||
"timeZoneInfo": "Alle Daten und Zeiten sind in der Zeitzone GMT+0.",
|
"timeZoneInfo": "Alle Daten und Zeiten sind in der Zeitzone GMT+0.",
|
||||||
"monitorsToApply": "Monitore, auf die das Wartungsfenster angewendet werden soll",
|
"monitorsToApply": "Monitore, auf die das Wartungsfenster angewendet werden soll",
|
||||||
@@ -260,79 +264,78 @@
|
|||||||
"notifyEmails": "Benachrichtige auch per E-Mail an mehrere Adressen (kommt bald)",
|
"notifyEmails": "Benachrichtige auch per E-Mail an mehrere Adressen (kommt bald)",
|
||||||
"seperateEmails": "Du kannst mehrere E-Mails mit einem Komma trennen",
|
"seperateEmails": "Du kannst mehrere E-Mails mit einem Komma trennen",
|
||||||
"checkFrequency": "Überprüfungsfrequenz",
|
"checkFrequency": "Überprüfungsfrequenz",
|
||||||
"chooseGame": "",
|
"matchMethod": "Übereinstimmungsmethode",
|
||||||
"matchMethod": "",
|
|
||||||
"expectedValue": "Erwarteter Wert",
|
"expectedValue": "Erwarteter Wert",
|
||||||
"deleteDialogTitle": "Möchtest du diesen Monitor wirklich löschen?",
|
"deleteDialogTitle": "Möchtest du diesen Monitor wirklich löschen?",
|
||||||
"deleteDialogDescription": "Sobald dieser Monitor gelöscht ist, kann er nicht wiederhergestellt werden.",
|
"deleteDialogDescription": "Sobald dieser Monitor gelöscht ist, kann er nicht wiederhergestellt werden.",
|
||||||
"pageSpeedMonitor": "",
|
"pageSpeedMonitor": "PageSpeed-Monitor",
|
||||||
"shown": "",
|
"shown": "Gezeigt",
|
||||||
"ago": "vor",
|
"ago": "vor",
|
||||||
"companyName": "",
|
"companyName": "Name der Firma",
|
||||||
"pageSpeedDetailsPerformanceReport": "",
|
"pageSpeedDetailsPerformanceReport": "Die Werte sind geschätzt und können variieren.",
|
||||||
"pageSpeedDetailsPerformanceReportCalculator": "",
|
"pageSpeedDetailsPerformanceReportCalculator": "Rechner öffnen",
|
||||||
"checkingEvery": "",
|
"checkingEvery": "Überprüfen alle",
|
||||||
"statusPageCreateSettings": "",
|
"statusPageCreateSettings": "Wenn Ihre Statusseite fertig ist, können Sie sie als veröffentlicht markieren.",
|
||||||
"basicInformation": "",
|
"basicInformation": "Grundlegende Informationen",
|
||||||
"statusPageCreateBasicInfoDescription": "",
|
"statusPageCreateBasicInfoDescription": "Definieren Sie den Firmennamen und die Subdomäne, auf die Ihre Statusseite verweist.",
|
||||||
"statusPageCreateSelectTimeZoneDescription": "",
|
"statusPageCreateSelectTimeZoneDescription": "Wählen Sie die Zeitzone aus, in der Ihre Statusseite angezeigt wird.",
|
||||||
"statusPageCreateAppearanceDescription": "",
|
"statusPageCreateAppearanceDescription": "Definieren Sie das Standard-Erscheinungsbild Ihrer öffentlichen Statusseite.",
|
||||||
"statusPageCreateSettingsCheckboxLabel": "",
|
"statusPageCreateSettingsCheckboxLabel": "Veröffentlicht und für die Öffentlichkeit sichtbar",
|
||||||
"statusPageCreateBasicInfoStatusPageAddress": "",
|
"statusPageCreateBasicInfoStatusPageAddress": "Ihre Statusseitenadresse",
|
||||||
"statusPageCreateTabsContent": "",
|
"statusPageCreateTabsContent": "Statusseitenserver",
|
||||||
"statusPageCreateTabsContentDescription": "",
|
"statusPageCreateTabsContentDescription": "Sie können Ihrer Statusseite beliebig viele Server hinzufügen, die Sie überwachen. Sie die Reihenfolge der Server ändern.",
|
||||||
"statusPageCreateTabsContentFeaturesDescription": "",
|
"statusPageCreateTabsContentFeaturesDescription": "Mehr Details auf der Statusseite anzeigen",
|
||||||
"showCharts": "",
|
"showCharts": "Diagramme anzeigen",
|
||||||
"showUptimePercentage": "",
|
"showUptimePercentage": "Verfügbarkeitsprozentsatz anzeigen",
|
||||||
"removeLogo": "Entferne Logo",
|
"removeLogo": "Entferne Logo",
|
||||||
"statusPageStatus": "",
|
"statusPageStatus": "Eine öffentliche Statusseite ist nicht eingerichtet.",
|
||||||
"statusPageStatusContactAdmin": "",
|
"statusPageStatusContactAdmin": "Bitte wenden Sie sich an Ihren Administrator",
|
||||||
"statusPageStatusNotPublic": "",
|
"statusPageStatusNotPublic": "Diese Statusseite ist nicht öffentlich.",
|
||||||
"statusPageStatusNoPage": "",
|
"statusPageStatusNoPage": "Hier gibt es keine Statusseite.",
|
||||||
"statusPageStatusServiceStatus": "",
|
"statusPageStatusServiceStatus": "Dienststatus",
|
||||||
"deleteStatusPage": "",
|
"deleteStatusPage": "Möchten Sie diese Statusseite löschen?",
|
||||||
"deleteStatusPageConfirm": "",
|
"deleteStatusPageConfirm": "Ja, Statusseite löschen",
|
||||||
"deleteStatusPageDescription": "",
|
"deleteStatusPageDescription": "Nach dem Löschen kann Ihre Statusseite nicht mehr abgerufen werden.",
|
||||||
"uptimeCreate": "",
|
"uptimeCreate": "Der erwartete Wert wird zum Abgleich mit dem Antwortergebnis verwendet und die Übereinstimmung bestimmt den Status.",
|
||||||
"uptimeCreateJsonPath": "",
|
"uptimeCreateJsonPath": "Dieser Ausdruck wird anhand der JSON-Antwortdaten ausgewertet und das Ergebnis wird zum Abgleich mit dem erwarteten Wert verwendet. Siehe",
|
||||||
"uptimeCreateJsonPathQuery": "",
|
"uptimeCreateJsonPathQuery": "für die Dokumentation der Abfragesprache.",
|
||||||
"maintenanceTableActionMenuDialogTitle": "",
|
"maintenanceTableActionMenuDialogTitle": "Möchten Sie dieses Wartungsfenster wirklich entfernen?",
|
||||||
"infrastructureEditYour": "",
|
"infrastructureEditYour": "Bearbeiten Sie Ihre",
|
||||||
"infrastructureEditMonitor": "",
|
"infrastructureEditMonitor": "Infrastrukturmonitor speichern",
|
||||||
"infrastructureMonitorCreated": "",
|
"infrastructureMonitorCreated": "Infrastrukturmonitor erfolgreich erstellt!",
|
||||||
"infrastructureMonitorUpdated": "",
|
"infrastructureMonitorUpdated": "Infrastrukturmonitor erfolgreich aktualisiert!",
|
||||||
"errorInvalidTypeId": "",
|
"errorInvalidTypeId": "Ungültiger Benachrichtigungstyp angegeben",
|
||||||
"errorInvalidFieldId": "",
|
"errorInvalidFieldId": "Ungültige Feld-ID angegeben",
|
||||||
"inviteNoTokenFound": "",
|
"inviteNoTokenFound": "Kein Einladungstoken gefunden",
|
||||||
"pageSpeedWarning": "",
|
"pageSpeedWarning": "Warnung: Sie haben noch keinen Google PageSpeed API-Schlüssel hinzugefügt. Ohne diesen funktioniert der PageSpeed-Monitor nicht.",
|
||||||
"pageSpeedLearnMoreLink": "Hier klicken",
|
"pageSpeedLearnMoreLink": "Hier klicken",
|
||||||
"pageSpeedAddApiKey": "um einen API key einzutragen",
|
"pageSpeedAddApiKey": "um einen API key einzutragen",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
"invalidFileFormat": "Nicht unterstützes Dateiformat",
|
"invalidFileFormat": "Nicht unterstützes Dateiformat",
|
||||||
"invalidFileSize": "Dateigröße zu groß!",
|
"invalidFileSize": "Dateigröße zu groß!",
|
||||||
"ClickUpload": "",
|
"ClickUpload": "Zum Hochladen klicken",
|
||||||
"DragandDrop": "drag and drop",
|
"DragandDrop": "drag and drop",
|
||||||
"MaxSize": "Maximalgröße",
|
"MaxSize": "Maximalgröße",
|
||||||
"SupportedFormats": "Unterstützte Formate",
|
"SupportedFormats": "Unterstützte Formate",
|
||||||
"FirstName": "Vorname",
|
"FirstName": "Vorname",
|
||||||
"LastName": "Zuname",
|
"LastName": "Zuname",
|
||||||
"EmailDescriptionText": "",
|
"EmailDescriptionText": "Dies ist Ihre aktuelle E-Mail-Adresse – sie kann nicht geändert werden.",
|
||||||
"YourPhoto": "Profilphoto",
|
"YourPhoto": "Profilphoto",
|
||||||
"PhotoDescriptionText": "",
|
"PhotoDescriptionText": "Dieses Foto wird auf Ihrer Profilseite angezeigt.",
|
||||||
"save": "Speichern",
|
"save": "Speichern",
|
||||||
"DeleteDescriptionText": "",
|
"DeleteDescriptionText": "Dadurch werden das Konto und alle zugehörigen Daten vom Server entfernt. Dieser Vorgang kann nicht rückgängig gemacht werden.",
|
||||||
"DeleteAccountWarning": "",
|
"DeleteAccountWarning": "Wenn Sie Ihr Konto löschen, können Sie sich nicht mehr anmelden und alle Ihre Daten werden gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.",
|
||||||
"DeleteWarningTitle": "Account wirklich löschen?",
|
"DeleteWarningTitle": "Account wirklich löschen?",
|
||||||
"bulkImport": {
|
"bulkImport": {
|
||||||
"title": "",
|
"title": "Massenimport",
|
||||||
"selectFileTips": "",
|
"selectFileTips": "Wählen Sie die CSV-Datei zum Hochladen aus",
|
||||||
"selectFileDescription": "",
|
"selectFileDescription": "Sie können unsere <template>Vorlage</template> oder <sample>Beispiel</sample> herunterladen.",
|
||||||
"selectFile": "Datei auswählen",
|
"selectFile": "Datei auswählen",
|
||||||
"parsingFailed": "",
|
"parsingFailed": "Parsen fehlgeschlagen",
|
||||||
"uploadSuccess": "Monitore erfolgreich erstellt!",
|
"uploadSuccess": "Monitore erfolgreich erstellt!",
|
||||||
"validationFailed": "Prüfung fehlgeschlagen",
|
"validationFailed": "Prüfung fehlgeschlagen",
|
||||||
"noFileSelected": "Keine Datei ausgewählt",
|
"noFileSelected": "Keine Datei ausgewählt",
|
||||||
"fallbackPage": "",
|
"fallbackPage": "Importieren Sie eine Datei, um eine Liste von Servern gleichzeitig hochzuladen",
|
||||||
"invalidFileType": "Ungültiger Dateityp",
|
"invalidFileType": "Ungültiger Dateityp",
|
||||||
"uploadFailed": "Upload fehlgeschlagen"
|
"uploadFailed": "Upload fehlgeschlagen"
|
||||||
},
|
},
|
||||||
@@ -347,8 +350,8 @@
|
|||||||
"createNew": "Neu anlegen",
|
"createNew": "Neu anlegen",
|
||||||
"greeting": {
|
"greeting": {
|
||||||
"prepend": "Hallo",
|
"prepend": "Hallo",
|
||||||
"append": "",
|
"append": "Der Nachmittag gehört Ihnen – machen wir ihn episch!",
|
||||||
"overview": ""
|
"overview": "Hier ist eine Übersicht Ihrer {{type}}-Monitore."
|
||||||
},
|
},
|
||||||
"roles": {
|
"roles": {
|
||||||
"superAdmin": "Super admin",
|
"superAdmin": "Super admin",
|
||||||
@@ -364,7 +367,7 @@
|
|||||||
},
|
},
|
||||||
"inviteTeamMember": "Team Mirglied einladen",
|
"inviteTeamMember": "Team Mirglied einladen",
|
||||||
"inviteNewTeamMember": "Neues Team Mirglied einladen",
|
"inviteNewTeamMember": "Neues Team Mirglied einladen",
|
||||||
"inviteDescription": "",
|
"inviteDescription": "Wenn Sie ein neues Teammitglied hinzufügen, erhält dieses Zugriff auf alle Monitore.",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"selectRole": "Rolle auswählen",
|
"selectRole": "Rolle auswählen",
|
||||||
"inviteLink": "Einladungslink",
|
"inviteLink": "Einladungslink",
|
||||||
@@ -377,21 +380,66 @@
|
|||||||
"email": "Email",
|
"email": "Email",
|
||||||
"role": "Rolle",
|
"role": "Rolle",
|
||||||
"created": "Angelegt"
|
"created": "Angelegt"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Pausiert",
|
"paused": "Pausiert",
|
||||||
"resumed": "",
|
"resumed": "Wiederaufgenommen",
|
||||||
"active": "Aktiv"
|
"active": "Aktiv"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"uptime": "Uptime",
|
"uptime": "Uptime",
|
||||||
"pagespeed": "",
|
"pagespeed": "Pagespeed",
|
||||||
"infrastructure": "",
|
"infrastructure": "Infrastruktur",
|
||||||
"incidents": "",
|
"incidents": "Vorfälle",
|
||||||
"statusPages": "Statusseite",
|
"statusPages": "Statusseite",
|
||||||
"maintenance": "Wartung",
|
"maintenance": "Wartung",
|
||||||
"integrations": "",
|
"integrations": "Integrationen",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
"support": "Support",
|
"support": "Support",
|
||||||
"discussions": "Diskussionen",
|
"discussions": "Diskussionen",
|
||||||
@@ -404,12 +452,12 @@
|
|||||||
"notifications": "Benachrichtigungen",
|
"notifications": "Benachrichtigungen",
|
||||||
"logs": "Logs"
|
"logs": "Logs"
|
||||||
},
|
},
|
||||||
"settingsEmailUser": "",
|
"settingsEmailUser": "E-Mail-Benutzer – Benutzername zur Authentifizierung, überschreibt die E-Mail-Adresse, falls angegeben",
|
||||||
"state": "",
|
"state": "Zustand",
|
||||||
"statusBreadCrumbsStatusPages": "Statusseite",
|
"statusBreadCrumbsStatusPages": "Statusseite",
|
||||||
"statusBreadCrumbsDetails": "Details",
|
"statusBreadCrumbsDetails": "Details",
|
||||||
"commonSaving": "Speichere...",
|
"commonSaving": "Speichere...",
|
||||||
"navControls": "",
|
"navControls": "Steuerungen",
|
||||||
"incidentsPageTitle": "Ereignisse",
|
"incidentsPageTitle": "Ereignisse",
|
||||||
"passwordPanel": {
|
"passwordPanel": {
|
||||||
"passwordChangedSuccess": "Dein Passwort wurde erfolgreich geändert.",
|
"passwordChangedSuccess": "Dein Passwort wurde erfolgreich geändert.",
|
||||||
@@ -430,22 +478,22 @@
|
|||||||
"settingsTestEmailUnknownError": "Unbekannter Fehler",
|
"settingsTestEmailUnknownError": "Unbekannter Fehler",
|
||||||
"statusMsg": {
|
"statusMsg": {
|
||||||
"paused": "Monitoring pausiert",
|
"paused": "Monitoring pausiert",
|
||||||
"up": "",
|
"up": "Ihre Site ist online.",
|
||||||
"down": "",
|
"down": "Ihre Site ist nicht erreichbar.",
|
||||||
"pending": ""
|
"pending": "Ausstehend..."
|
||||||
},
|
},
|
||||||
"uptimeGeneralInstructions": {
|
"uptimeGeneralInstructions": {
|
||||||
"http": "",
|
"http": "Geben Sie die zu überwachende URL oder IP ein (z. B. https://example.com/ oder 192.168.1.100) und fügen Sie einen eindeutigen Anzeigenamen hinzu, der auf dem Dashboard angezeigt wird.",
|
||||||
"ping": "",
|
"ping": "Geben Sie die IP-Adresse oder den Hostnamen ein, der angepingt werden soll (z. B. 192.168.1.100 oder example.com), und fügen Sie einen eindeutigen Anzeigenamen hinzu, der auf dem Dashboard angezeigt wird.",
|
||||||
"docker": "",
|
"docker": "Geben Sie die Docker-ID Ihres Containers ein. Docker-IDs müssen die vollständige 64-Zeichen-ID sein. Sie können docker inspect <short_id> ausführen, um die vollständige Container-ID abzurufen.",
|
||||||
"port": "",
|
"port": "Geben Sie die URL oder IP des Servers, die Portnummer und einen eindeutigen Anzeigenamen ein, der auf dem Dashboard angezeigt wird.",
|
||||||
"game": ""
|
"game": ""
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"appName": "Checkmate",
|
"appName": "Checkmate",
|
||||||
"monitoringAgentName": "Capture",
|
"monitoringAgentName": "Capture",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"toggleTheme": ""
|
"toggleTheme": "Schaltet hell und dunkel um"
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"networkError": "Netzwerkfehler",
|
"networkError": "Netzwerkfehler",
|
||||||
@@ -465,7 +513,7 @@
|
|||||||
"placeholder": "jordan.ellis@domain.com",
|
"placeholder": "jordan.ellis@domain.com",
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "Email adresse eingeben um fortzufahren",
|
"empty": "Email adresse eingeben um fortzufahren",
|
||||||
"invalid": ""
|
"invalid": "Bitte überprüfen Sie die Gültigkeit der eingegebenen E-Mail-Adresse erneut"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
@@ -492,7 +540,7 @@
|
|||||||
"highlighted": "einen Kleinbuchstaben enthalten"
|
"highlighted": "einen Kleinbuchstaben enthalten"
|
||||||
},
|
},
|
||||||
"match": {
|
"match": {
|
||||||
"beginning": "",
|
"beginning": "Passwort und Kennwort bestätigen",
|
||||||
"highlighted": "muß übereinstimmen"
|
"highlighted": "muß übereinstimmen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -544,7 +592,7 @@
|
|||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"min": ""
|
"min": "Mindestens eine Rolle ist erforderlich"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -569,7 +617,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": "Das Passwort stimmt nicht mit dem gespeicherten überein"
|
"incorrect": "Das Passwort stimmt nicht mit dem gespeicherten überein"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -577,25 +626,26 @@
|
|||||||
"user": "Anmelden"
|
"user": "Anmelden"
|
||||||
},
|
},
|
||||||
"subheadings": {
|
"subheadings": {
|
||||||
"stepOne": "",
|
"stepOne": "Geben Sie Ihre persönlichen Daten ein",
|
||||||
"stepTwo": "Email eingeben",
|
"stepTwo": "Email eingeben",
|
||||||
"stepThree": "Passwort eingeben"
|
"stepThree": "Passwort eingeben"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"superAdmin": "Super admin account anlegen um zu beginnen",
|
"superAdmin": "Super admin account anlegen um zu beginnen",
|
||||||
"user": ""
|
"user": "Melden Sie sich als Benutzer an und bitten Sie den Superadministrator um Zugriff auf Ihre Monitore"
|
||||||
},
|
},
|
||||||
"gettingStartedButton": {
|
"gettingStartedButton": {
|
||||||
"superAdmin": "Super admin account anlegen",
|
"superAdmin": "Super admin account anlegen",
|
||||||
"user": "Normalen Benutzer anlegen"
|
"user": "Normalen Benutzer anlegen"
|
||||||
},
|
},
|
||||||
"termsAndPolicies": "",
|
"termsAndPolicies": "Indem Sie ein Konto erstellen, stimmen Sie unseren <a1>Servicebedingungen</a1> und <a2>Datenschutzrichtlinien</a2> zu.",
|
||||||
"links": {
|
"links": {
|
||||||
"login": "Du hast bereits einen Benutzer? <a>Anmelden</a>"
|
"login": "Du hast bereits einen Benutzer? <a>Anmelden</a>"
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "Willkommen! Benutzer erfolgreich angelegt"
|
"success": "Willkommen! Benutzer erfolgreich angelegt"
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "Passwort vergessen?",
|
"heading": "Passwort vergessen?",
|
||||||
@@ -624,7 +674,7 @@
|
|||||||
"emailNotFound": "Email nicht gefunden.",
|
"emailNotFound": "Email nicht gefunden.",
|
||||||
"redirect": "Umleitung in <seconds/>...",
|
"redirect": "Umleitung in <seconds/>...",
|
||||||
"success": "Passwort erfolgreich zurückgesetzt.",
|
"success": "Passwort erfolgreich zurückgesetzt.",
|
||||||
"error": ""
|
"error": "Kennwort konnte nicht zurückgesetzt werden. Bitte versuchen Sie es später erneut oder wenden Sie sich an den Support."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -635,7 +685,7 @@
|
|||||||
"stillUnreachable": "Server immer noch nicht erreichbar. Bitte später erneut versuchen."
|
"stillUnreachable": "Server immer noch nicht erreichbar. Bitte später erneut versuchen."
|
||||||
},
|
},
|
||||||
"alertBox": "Server Verbindungsfehler",
|
"alertBox": "Server Verbindungsfehler",
|
||||||
"description": "",
|
"description": "Wir können keine Verbindung zum Server herstellen. Bitte überprüfen Sie Ihre Internetverbindung oder Ihre Bereitstellungskonfiguration, falls das Problem weiterhin besteht.",
|
||||||
"retryButton": {
|
"retryButton": {
|
||||||
"default": "Verbindung erneut versuchen",
|
"default": "Verbindung erneut versuchen",
|
||||||
"processing": "Verbinde..."
|
"processing": "Verbinde..."
|
||||||
@@ -643,16 +693,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"createNotifications": {
|
"createNotifications": {
|
||||||
"title": "",
|
"title": "Benachrichtigungskanal erstellen",
|
||||||
"nameSettings": {
|
"nameSettings": {
|
||||||
"title": "Name",
|
"title": "Name",
|
||||||
"description": "",
|
"description": "Ein beschreibender Name für Ihre Integration.",
|
||||||
"nameLabel": "Name",
|
"nameLabel": "Name",
|
||||||
"namePlaceholder": "z.B. Slack Benachrichtigung"
|
"namePlaceholder": "z.B. Slack Benachrichtigung"
|
||||||
},
|
},
|
||||||
"typeSettings": {
|
"typeSettings": {
|
||||||
"title": "Typ",
|
"title": "Typ",
|
||||||
"description": "",
|
"description": "Wählen Sie den Typ des Benachrichtigungskanals aus, den Sie erstellen möchten.",
|
||||||
"typeLabel": "Typ"
|
"typeLabel": "Typ"
|
||||||
},
|
},
|
||||||
"emailSettings": {
|
"emailSettings": {
|
||||||
@@ -665,7 +715,7 @@
|
|||||||
"title": "Slack",
|
"title": "Slack",
|
||||||
"description": "Slack webhook hier konfigurieren",
|
"description": "Slack webhook hier konfigurieren",
|
||||||
"webhookLabel": "Slack webhook URL",
|
"webhookLabel": "Slack webhook URL",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": "https://hooks.slack.com/services/..."
|
||||||
},
|
},
|
||||||
"pagerdutySettings": {
|
"pagerdutySettings": {
|
||||||
"title": "PagerDuty",
|
"title": "PagerDuty",
|
||||||
@@ -685,38 +735,38 @@
|
|||||||
"webhookLabel": "Webhook URL",
|
"webhookLabel": "Webhook URL",
|
||||||
"webhookPlaceholder": "https://your-server.com/webhook"
|
"webhookPlaceholder": "https://your-server.com/webhook"
|
||||||
},
|
},
|
||||||
"testNotification": "",
|
"testNotification": "Testbenachrichtigung",
|
||||||
"dialogDeleteTitle": "",
|
"dialogDeleteTitle": "Möchten Sie diese Benachrichtigung wirklich löschen?",
|
||||||
"dialogDeleteConfirm": ""
|
"dialogDeleteConfirm": "Löschen"
|
||||||
},
|
},
|
||||||
"notificationConfig": {
|
"notificationConfig": {
|
||||||
"title": "Benachrichtigungen",
|
"title": "Benachrichtigungen",
|
||||||
"description": ""
|
"description": "Wählen Sie die Benachrichtigungskanäle aus, die Sie verwenden möchten"
|
||||||
},
|
},
|
||||||
"monitorStatus": {
|
"monitorStatus": {
|
||||||
"checkingEvery": "",
|
"checkingEvery": "Überprüfung alle {{interval}}",
|
||||||
"withCaptureAgent": "",
|
"withCaptureAgent": "mit Capture-Agent {{version}}",
|
||||||
"up": "hoch",
|
"up": "hoch",
|
||||||
"down": "runter",
|
"down": "runter",
|
||||||
"paused": "pausiert"
|
"paused": "pausiert"
|
||||||
},
|
},
|
||||||
"advancedMatching": "",
|
"advancedMatching": "Erweiterter Abgleich",
|
||||||
"sendTestNotifications": "Test Benachrichtigung senden",
|
"sendTestNotifications": "Test Benachrichtigung senden",
|
||||||
"selectAll": "Alle auswählen",
|
"selectAll": "Alle auswählen",
|
||||||
"showAdminLoginLink": "",
|
"showAdminLoginLink": "Link „Administrator? Hier anmelden“ auf der Statusseite anzeigen",
|
||||||
"logsPage": {
|
"logsPage": {
|
||||||
"title": "Logs",
|
"title": "Logs",
|
||||||
"description": "",
|
"description": "Systemprotokolle – letzte 1000 Zeilen",
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"queue": "Warteschlange",
|
"queue": "Warteschlange",
|
||||||
"logs": "Server logs",
|
"logs": "Server logs",
|
||||||
"diagnostics": ""
|
"diagnostics": "Diagnose"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"fetchLogsSuccess": ""
|
"fetchLogsSuccess": "Protokolle erfolgreich abgerufen"
|
||||||
},
|
},
|
||||||
"logLevelSelect": {
|
"logLevelSelect": {
|
||||||
"title": "",
|
"title": "Protokollebene",
|
||||||
"values": {
|
"values": {
|
||||||
"all": "Alle",
|
"all": "Alle",
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
@@ -736,16 +786,17 @@
|
|||||||
"urlHeader": "URL",
|
"urlHeader": "URL",
|
||||||
"typeHeader": "Typ",
|
"typeHeader": "Typ",
|
||||||
"activeHeader": "Aktiv",
|
"activeHeader": "Aktiv",
|
||||||
"lockedAtHeader": "",
|
"lockedAtHeader": "Gesperrt bei",
|
||||||
"runCountHeader": "Anzahl Läufe",
|
"runCountHeader": "Anzahl Läufe",
|
||||||
"failCountHeader": "Anzahl Fehler",
|
"failCountHeader": "Anzahl Fehler",
|
||||||
"lastRunHeader": "Letzter Lauf um",
|
"lastRunHeader": "Letzter Lauf um",
|
||||||
"lastFinishedAtHeader": "Zuletzt abgeschlossen um",
|
"lastFinishedAtHeader": "Zuletzt abgeschlossen um",
|
||||||
"lastRunTookHeader": "Letzter Lauf dauerte"
|
"lastRunTookHeader": "Letzter Lauf dauerte",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "Warteschlangenmetriken",
|
||||||
"metricHeader": "",
|
"metricHeader": "Metrisch",
|
||||||
"valueHeader": "Wert"
|
"valueHeader": "Wert"
|
||||||
},
|
},
|
||||||
"failedJobTable": {
|
"failedJobTable": {
|
||||||
@@ -766,9 +817,9 @@
|
|||||||
"title": "Export/Import",
|
"title": "Export/Import",
|
||||||
"import": "Monitore importieren",
|
"import": "Monitore importieren",
|
||||||
"export": "Monitore exportieren",
|
"export": "Monitore exportieren",
|
||||||
"deleteSuccess": "",
|
"deleteSuccess": "Monitor erfolgreich gelöscht",
|
||||||
"deleteFailed": "",
|
"deleteFailed": "Monitor konnte nicht gelöscht werden",
|
||||||
"details": ""
|
"details": "Details"
|
||||||
},
|
},
|
||||||
"settingsPage": {
|
"settingsPage": {
|
||||||
"aboutSettings": {
|
"aboutSettings": {
|
||||||
@@ -783,43 +834,43 @@
|
|||||||
},
|
},
|
||||||
"emailSettings": {
|
"emailSettings": {
|
||||||
"buttonSendTestEmail": "Test-Email senden",
|
"buttonSendTestEmail": "Test-Email senden",
|
||||||
"description": "",
|
"description": "Konfigurieren Sie die E-Mail-Einstellungen für Ihr System. Diese werden zum Senden von Benachrichtigungen und Warnungen verwendet.",
|
||||||
"descriptionTransport": "",
|
"descriptionTransport": "Dies erstellt einen SMTP-Transport für NodeMailer",
|
||||||
"labelAddress": "",
|
"labelAddress": "E-Mail-Adresse - Wird zur Authentifizierung verwendet",
|
||||||
"labelConnectionHost": "",
|
"labelConnectionHost": "E-Mail-Verbindungshost – Hostname zur Verwendung in der HELO/EHLO-Begrüßung",
|
||||||
"labelHost": "",
|
"labelHost": "E-Mail-Host – Hostname oder IP-Adresse, mit der eine Verbindung hergestellt werden soll",
|
||||||
"labelIgnoreTLS": "STARTTLS abschalten: TLS nicht nutzen, selbst wenn der Server es unterstützt",
|
"labelIgnoreTLS": "STARTTLS abschalten: TLS nicht nutzen, selbst wenn der Server es unterstützt",
|
||||||
"labelPassword": "Email password - Password für Anmeldung",
|
"labelPassword": "Email password - Password für Anmeldung",
|
||||||
"labelPasswordSet": "Passwort erstellt. Reset drücken um es zu ändern.",
|
"labelPasswordSet": "Passwort erstellt. Reset drücken um es zu ändern.",
|
||||||
"labelPool": "",
|
"labelPool": "Verbindungspooling aktivieren: Vorhandene Verbindungen wiederverwenden, um die Leistung zu verbessern",
|
||||||
"labelPort": "Email port - Port zum verbinden",
|
"labelPort": "Email port - Port zum verbinden",
|
||||||
"labelRejectUnauthorized": "Ungültige Zertifikate ablehnen. Verbindungen mit self-signed oder nicht vertrauenswürdigen Zertifikaten ablehnen.",
|
"labelRejectUnauthorized": "Ungültige Zertifikate ablehnen. Verbindungen mit self-signed oder nicht vertrauenswürdigen Zertifikaten ablehnen.",
|
||||||
"labelRequireTLS": "",
|
"labelRequireTLS": "STARTTLS erzwingen: TLS-Upgrade erforderlich, schlägt fehl, wenn nicht unterstützt",
|
||||||
"labelSecure": "SSL verwenden (empfohlen): Verbindung mit SSL/TLS verschlüsseln",
|
"labelSecure": "SSL verwenden (empfohlen): Verbindung mit SSL/TLS verschlüsseln",
|
||||||
"labelTLSServername": "",
|
"labelTLSServername": "TLS-Servername – Optionaler Hostname für die TLS-Validierung, wenn der Host eine IP ist",
|
||||||
"labelUser": "",
|
"labelUser": "E-Mail-Benutzer – Benutzername zur Authentifizierung, überschreibt die E-Mail-Adresse, falls angegeben",
|
||||||
"linkTransport": "",
|
"linkTransport": "Spezifikationen finden Sie hier",
|
||||||
"placeholderUser": "Leer lassen, wenn nicht benötigt",
|
"placeholderUser": "Leer lassen, wenn nicht benötigt",
|
||||||
"title": "Email",
|
"title": "Email",
|
||||||
"toastEmailRequiredFieldsError": ""
|
"toastEmailRequiredFieldsError": "E-Mail-Adresse, Host, Port und Passwort sind erforderlich"
|
||||||
},
|
},
|
||||||
"pageSpeedSettings": {
|
"pageSpeedSettings": {
|
||||||
"description": "",
|
"description": "Geben Sie Ihren Google PageSpeed API-Schlüssel ein, um die Google PageSpeed-Überwachung zu aktivieren. Klicken Sie auf „Zurücksetzen“, um den Schlüssel zu aktualisieren.",
|
||||||
"labelApiKeySet": "API key erstellt. Reset drücken um ihn zu ändern.",
|
"labelApiKeySet": "API key erstellt. Reset drücken um ihn zu ändern.",
|
||||||
"labelApiKey": "PageSpeed API key",
|
"labelApiKey": "PageSpeed API key",
|
||||||
"title": "Google PageSpeed API key"
|
"title": "Google PageSpeed API key"
|
||||||
},
|
},
|
||||||
"saveButtonLabel": "Speichern",
|
"saveButtonLabel": "Speichern",
|
||||||
"statsSettings": {
|
"statsSettings": {
|
||||||
"clearAllStatsButton": "",
|
"clearAllStatsButton": "Alle Statistiken löschen",
|
||||||
"clearAllStatsDescription": "",
|
"clearAllStatsDescription": "Alle Statistiken löschen. Dies ist irreversibel.",
|
||||||
"clearAllStatsDialogConfirm": "",
|
"clearAllStatsDialogConfirm": "Ja, alle Statistiken löschen",
|
||||||
"clearAllStatsDialogDescription": "",
|
"clearAllStatsDialogDescription": "Nach dem Entfernen können der Überwachungsverlauf und die Statistiken nicht mehr abgerufen werden.",
|
||||||
"clearAllStatsDialogTitle": "",
|
"clearAllStatsDialogTitle": "Möchten Sie alle Statistiken löschen?",
|
||||||
"description": "",
|
"description": "Legen Sie fest, wie lange Sie historische Daten aufbewahren möchten. Sie können auch alle vorhandenen Daten löschen.",
|
||||||
"labelTTL": "",
|
"labelTTL": "Die Tage, an denen Sie den Überwachungsverlauf beibehalten möchten.",
|
||||||
"labelTTLOptional": "0 für unendlich",
|
"labelTTLOptional": "0 für unendlich",
|
||||||
"title": ""
|
"title": "Monitorverlauf"
|
||||||
},
|
},
|
||||||
"systemResetSettings": {
|
"systemResetSettings": {
|
||||||
"buttonRemoveAllMonitors": "Alle Monitore löschen",
|
"buttonRemoveAllMonitors": "Alle Monitore löschen",
|
||||||
@@ -830,142 +881,242 @@
|
|||||||
"title": "System zurücksetzen"
|
"title": "System zurücksetzen"
|
||||||
},
|
},
|
||||||
"timezoneSettings": {
|
"timezoneSettings": {
|
||||||
"description": "",
|
"description": "Wählen Sie die Zeitzone aus, die zum Anzeigen von Datum und Uhrzeit in der gesamten Anwendung verwendet wird.",
|
||||||
"label": "Zeitzone",
|
"label": "Zeitzone",
|
||||||
"title": "Zeitzone"
|
"title": "Zeitzone"
|
||||||
},
|
},
|
||||||
"title": "Einstellungen",
|
"title": "Einstellungen",
|
||||||
"uiSettings": {
|
"uiSettings": {
|
||||||
"description": "",
|
"description": "Wechseln Sie zwischen hellem und dunklem Modus oder ändern Sie die Sprache der Benutzeroberfläche.",
|
||||||
"labelLanguage": "Sprache",
|
"labelLanguage": "Sprache",
|
||||||
"labelTheme": "",
|
"labelTheme": "Themenmodus",
|
||||||
"title": ""
|
"title": "Aussehen"
|
||||||
},
|
},
|
||||||
"urlSettings": {
|
"urlSettings": {
|
||||||
"description": "",
|
"description": "Zeigt die IP-Adresse oder URL des Monitors auf der öffentlichen Statusseite an. Wenn diese Option deaktiviert ist, wird zum Schutz vertraulicher Informationen nur der Monitorname angezeigt.",
|
||||||
"label": "",
|
"label": "IP/URL auf der Statusseite anzeigen",
|
||||||
"selectDisabled": "Inaktiv",
|
"selectDisabled": "Inaktiv",
|
||||||
"selectEnabled": "Aktiv",
|
"selectEnabled": "Aktiv",
|
||||||
"title": ""
|
"title": "Überwachen Sie IP/URL auf der Statusseite"
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
"buttonSave": "Speichern"
|
"buttonSave": "Speichern"
|
||||||
},
|
},
|
||||||
"incidentsOptionsHeaderFilterResolved": "",
|
"incidentsOptionsHeaderFilterResolved": "Gelöst",
|
||||||
"settingsSave": "Speichern",
|
"settingsSave": "Speichern",
|
||||||
"statusPageCreateAppearanceTitle": "",
|
"statusPageCreateAppearanceTitle": "Aussehen",
|
||||||
"confirmPassword": "Passwort bestätigen",
|
"confirmPassword": "Passwort bestätigen",
|
||||||
"monitorHooks": {
|
"monitorHooks": {
|
||||||
"failureAddDemoMonitors": "Demo Monitor konnte nicht hinzugefügt werden",
|
"failureAddDemoMonitors": "Demo Monitor konnte nicht hinzugefügt werden",
|
||||||
"successAddDemoMonitors": "Demo Monitor erfolgreich hinzugefügt"
|
"successAddDemoMonitors": "Demo Monitor erfolgreich hinzugefügt"
|
||||||
},
|
},
|
||||||
"settingsAppearance": "",
|
"settingsAppearance": "Aussehen",
|
||||||
"settingsDisplayTimezone": "",
|
"settingsDisplayTimezone": "Zeitzone anzeigen",
|
||||||
"settingsGeneralSettings": "",
|
"settingsGeneralSettings": "Allgemeine Einstellungen",
|
||||||
"incidentsOptionsHeaderTotalIncidents": "",
|
"incidentsOptionsHeaderTotalIncidents": "Gesamtanzahl der Vorfälle",
|
||||||
"statusPage": {
|
"statusPage": {
|
||||||
"deleteSuccess": "",
|
"deleteSuccess": "Statusseite erfolgreich gelöscht",
|
||||||
"deleteFailed": "",
|
"deleteFailed": "Löschen der Statusseite fehlgeschlagen",
|
||||||
"createSuccess": "",
|
"createSuccess": "Statusseite erfolgreich erstellt",
|
||||||
"updateSuccess": "",
|
"updateSuccess": "Statusseite erfolgreich aktualisiert",
|
||||||
"generalSettings": "",
|
"generalSettings": "Allgemeine Einstellungen",
|
||||||
"contents": "",
|
"contents": "Inhalt",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Überwachen und zeigen Sie den Zustand Ihrer Dienste in Echtzeit an.",
|
||||||
"actionButton": ""
|
"Verfolgen Sie mehrere Dienste und teilen Sie deren Status.",
|
||||||
|
"Informieren Sie Nutzer über Ausfälle und Leistung."
|
||||||
|
],
|
||||||
|
"title": "Eine Statusseite wird verwendet, um:",
|
||||||
|
"actionButton": "Lassen Sie uns Ihre erste Statusseite erstellen!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testNotificationsDisabled": "",
|
"testNotificationsDisabled": "Für diesen Monitor sind keine Benachrichtigungen eingerichtet. Sie müssen eine hinzufügen, indem Sie auf die Schaltfläche „Konfigurieren“ klicken.",
|
||||||
"incidentsTableResolvedAt": "",
|
"incidentsTableResolvedAt": "Gelöst am",
|
||||||
"incidentsTableActionResolve": "",
|
"incidentsTableActionResolve": "Lösen",
|
||||||
"checkHooks": {
|
"checkHooks": {
|
||||||
"failureResolveOne": "",
|
"failureResolveOne": "Der Vorfall konnte nicht gelöst werden.",
|
||||||
"failureResolveAll": "",
|
"failureResolveAll": "Es konnten nicht alle Vorfälle gelöst werden.",
|
||||||
"failureResolveMonitor": ""
|
"failureResolveMonitor": "Monitorvorfälle konnten nicht behoben werden."
|
||||||
},
|
},
|
||||||
"checkFormError": "",
|
"checkFormError": "Bitte überprüfen Sie das Formular auf Fehler.",
|
||||||
"diagnosticsPage": {
|
"diagnosticsPage": {
|
||||||
"diagnosticDescription": "",
|
"diagnosticDescription": "Systemdiagnose",
|
||||||
"statsDescription": "",
|
"statsDescription": "Systemstatistiken",
|
||||||
"gauges": {
|
"gauges": {
|
||||||
"heapAllocationTitle": "",
|
"heapAllocationTitle": "Heap-Zuweisung",
|
||||||
"heapAllocationSubtitle": "",
|
"heapAllocationSubtitle": "% des verfügbaren Speichers",
|
||||||
"heapUsageTitle": "",
|
"heapUsageTitle": "Heap-Nutzung",
|
||||||
"heapUsageSubtitle": "",
|
"heapUsageSubtitle": "% des verfügbaren Speichers",
|
||||||
"heapUtilizationTitle": "",
|
"heapUtilizationTitle": "Heap-Auslastung",
|
||||||
"heapUtilizationSubtitle": "",
|
"heapUtilizationSubtitle": "% der zugewiesenen",
|
||||||
"instantCpuUsageTitle": "",
|
"instantCpuUsageTitle": "Sofortige CPU-Auslastung",
|
||||||
"instantCpuUsageSubtitle": ""
|
"instantCpuUsageSubtitle": "% der von der CPU genutzten 1s"
|
||||||
},
|
},
|
||||||
"stats": {
|
"stats": {
|
||||||
"eventLoopDelayTitle": "",
|
"eventLoopDelayTitle": "Ereignisschleifenverzögerung",
|
||||||
"uptimeTitle": "",
|
"uptimeTitle": "Betriebszeit",
|
||||||
"usedHeapSizeTitle": "",
|
"usedHeapSizeTitle": "Verwendete Heap-Größe",
|
||||||
"totalHeapSizeTitle": "",
|
"totalHeapSizeTitle": "Gesamtgröße des Heapspeichers",
|
||||||
"osMemoryLimitTitle": ""
|
"osMemoryLimitTitle": "Betriebssystem-Speicherlimit"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageSpeedLighthouseAPI": "",
|
"pageSpeedLighthouseAPI": "Verwenden Sie die Lighthouse PageSpeed API, um Ihre Website zu überwachen",
|
||||||
"time": {
|
"time": {
|
||||||
"threeMinutes": "",
|
"threeMinutes": "3 Minuten",
|
||||||
"fiveMinutes": "",
|
"fiveMinutes": "5 Minuten",
|
||||||
"tenMinutes": "",
|
"tenMinutes": "10 Minuten",
|
||||||
"twentyMinutes": "",
|
"twentyMinutes": "20 Minuten",
|
||||||
"oneHour": "",
|
"oneHour": "1 Stunde",
|
||||||
"oneDay": "",
|
"oneDay": "1 Tag",
|
||||||
"oneWeek": ""
|
"oneWeek": "1 Woche",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": "Keine {{unit}} gefunden"
|
||||||
},
|
},
|
||||||
"infrastructureMonitor": {
|
"infrastructureMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Verfolgen Sie die Leistung Ihrer Server",
|
||||||
"actionButton": ""
|
"Identifizieren Sie Engpässe und optimieren Sie die Nutzung",
|
||||||
|
"Sorgen Sie für Zuverlässigkeit durch Echtzeitüberwachung"
|
||||||
|
],
|
||||||
|
"title": "Ein Infrastrukturmonitor wird verwendet, um:",
|
||||||
|
"actionButton": "Lassen Sie uns Ihren ersten Infrastrukturmonitor erstellen!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"maintenanceWindow": {
|
"maintenanceWindow": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Markieren Sie Ihre Wartungszeiträume.",
|
||||||
"actionButton": ""
|
"Beseitigen Sie Missverständnisse.",
|
||||||
|
"Beenden Sie das Senden von Warnmeldungen in Wartungsfenstern."
|
||||||
|
],
|
||||||
|
"title": "Ein Wartungsfenster wird verwendet, um:",
|
||||||
|
"actionButton": "Lassen Sie uns Ihr erstes Wartungsfenster erstellen!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageSpeed": {
|
"pageSpeed": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Berichten Sie über die Benutzerfreundlichkeit einer Seite.",
|
||||||
"actionButton": ""
|
"Helfen Sie bei der Analyse der Webseitengeschwindigkeit.",
|
||||||
|
"Geben Sie Verbesserungsvorschläge für die Seite."
|
||||||
|
],
|
||||||
|
"title": "Ein PageSpeed-Monitor wird verwendet, um:",
|
||||||
|
"actionButton": "Lassen Sie uns Ihren ersten PageSpeed-Monitor erstellen!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"uptimeMonitor": {
|
"uptimeMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Prüfen Sie, ob Websites oder Server online und reaktionsfähig sind.",
|
||||||
"actionButton": ""
|
"Benachrichtigen Sie Ihre Teams über Ausfallzeiten oder Leistungsprobleme.",
|
||||||
|
"Überwachen Sie HTTP-Endpunkte, Pings, Container und Ports.",
|
||||||
|
"Verfolgen Sie historische Verfügbarkeits- und Zuverlässigkeitstrends."
|
||||||
|
],
|
||||||
|
"title": "Ein Uptime-Monitor wird verwendet, um:",
|
||||||
|
"actionButton": "Lassen Sie uns Ihren ersten Uptime-Monitor erstellen!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editUserPage": {
|
"editUserPage": {
|
||||||
"form": {
|
"form": {
|
||||||
"email": "",
|
"email": "E-Mail",
|
||||||
"firstName": "",
|
"firstName": "Vorname",
|
||||||
"lastName": "",
|
"lastName": "Nachname",
|
||||||
"role": "",
|
"role": "Rollen",
|
||||||
"save": ""
|
"save": "Speichern"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"actionHeader": "",
|
"actionHeader": "Aktion",
|
||||||
"roleHeader": ""
|
"roleHeader": "Rolle"
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": "Benutzer bearbeiten",
|
||||||
"toast": {
|
"toast": {
|
||||||
"successUserUpdate": "",
|
"successUserUpdate": "Benutzer erfolgreich aktualisiert",
|
||||||
"validationErrors": ""
|
"validationErrors": "Validierungsfehler"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "Monitor-Vorfälle beheben",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "Alle Vorfälle lösen",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+930
-878
File diff suppressed because it is too large.
Load diff
+133
-7
@@ -260,7 +260,6 @@
|
|||||||
"notifyEmails": "",
|
"notifyEmails": "",
|
||||||
"seperateEmails": "",
|
"seperateEmails": "",
|
||||||
"checkFrequency": "",
|
"checkFrequency": "",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "",
|
"matchMethod": "",
|
||||||
"expectedValue": "",
|
"expectedValue": "",
|
||||||
"deleteDialogTitle": "",
|
"deleteDialogTitle": "",
|
||||||
@@ -377,7 +376,52 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"role": "",
|
"role": "",
|
||||||
"created": ""
|
"created": ""
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "",
|
"paused": "",
|
||||||
@@ -569,7 +613,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -595,7 +640,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": ""
|
"success": ""
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
@@ -741,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -847,6 +894,10 @@
|
|||||||
"selectDisabled": "",
|
"selectDisabled": "",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -915,7 +966,12 @@
|
|||||||
"twentyMinutes": "",
|
"twentyMinutes": "",
|
||||||
"oneHour": "",
|
"oneHour": "",
|
||||||
"oneDay": "",
|
"oneDay": "",
|
||||||
"oneWeek": ""
|
"oneWeek": "",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -967,5 +1023,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+133
-7
@@ -260,7 +260,6 @@
|
|||||||
"notifyEmails": "",
|
"notifyEmails": "",
|
||||||
"seperateEmails": "",
|
"seperateEmails": "",
|
||||||
"checkFrequency": "",
|
"checkFrequency": "",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "",
|
"matchMethod": "",
|
||||||
"expectedValue": "",
|
"expectedValue": "",
|
||||||
"deleteDialogTitle": "",
|
"deleteDialogTitle": "",
|
||||||
@@ -377,7 +376,52 @@
|
|||||||
"email": "Sähköposti",
|
"email": "Sähköposti",
|
||||||
"role": "Rooli",
|
"role": "Rooli",
|
||||||
"created": "Luotu"
|
"created": "Luotu"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Tauota",
|
"paused": "Tauota",
|
||||||
@@ -569,7 +613,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -595,7 +640,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": ""
|
"success": ""
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
@@ -741,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -847,6 +894,10 @@
|
|||||||
"selectDisabled": "",
|
"selectDisabled": "",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -915,7 +966,12 @@
|
|||||||
"twentyMinutes": "",
|
"twentyMinutes": "",
|
||||||
"oneHour": "",
|
"oneHour": "",
|
||||||
"oneDay": "",
|
"oneDay": "",
|
||||||
"oneWeek": ""
|
"oneWeek": "",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -967,5 +1023,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+178
-31
@@ -90,7 +90,7 @@
|
|||||||
"Informez les ingénieurs lorsque des incidents se produisent",
|
"Informez les ingénieurs lorsque des incidents se produisent",
|
||||||
"Tenez les administrateurs informés des changements apportés au système"
|
"Tenez les administrateurs informés des changements apportés au système"
|
||||||
],
|
],
|
||||||
"actionButton": ""
|
"actionButton": "Créez votre premier canal de notification !"
|
||||||
},
|
},
|
||||||
"createButton": "Créer un canal de notification",
|
"createButton": "Créer un canal de notification",
|
||||||
"createTitle": "Canal de notification",
|
"createTitle": "Canal de notification",
|
||||||
@@ -264,7 +264,6 @@
|
|||||||
"notifyEmails": "Envoyer également une notification par email à plusieurs adresses (bientôt).",
|
"notifyEmails": "Envoyer également une notification par email à plusieurs adresses (bientôt).",
|
||||||
"seperateEmails": "Vous pouvez ajouter plusieurs adresses emails en les séparant par une virgule",
|
"seperateEmails": "Vous pouvez ajouter plusieurs adresses emails en les séparant par une virgule",
|
||||||
"checkFrequency": "Vérifier la fréquence",
|
"checkFrequency": "Vérifier la fréquence",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "Méthode de rapprochement",
|
"matchMethod": "Méthode de rapprochement",
|
||||||
"expectedValue": "Valeur attendue",
|
"expectedValue": "Valeur attendue",
|
||||||
"deleteDialogTitle": "Voulez-vous vraiment supprimer ce moniteur ?",
|
"deleteDialogTitle": "Voulez-vous vraiment supprimer ce moniteur ?",
|
||||||
@@ -381,7 +380,52 @@
|
|||||||
"email": "Email",
|
"email": "Email",
|
||||||
"role": "Rôle",
|
"role": "Rôle",
|
||||||
"created": "Créée"
|
"created": "Créée"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Pause",
|
"paused": "Pause",
|
||||||
@@ -548,7 +592,7 @@
|
|||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"min": ""
|
"min": "Au moins un rôle est requis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,7 +617,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": "Le mot de passe fourni est erroné"
|
"incorrect": "Le mot de passe fourni est erroné"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": "Bon retour sur Checkmate !"
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -599,7 +644,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "Bienvenue ! Votre compte a été créé avec succès."
|
"success": "Bienvenue ! Votre compte a été créé avec succès."
|
||||||
}
|
},
|
||||||
|
"welcome": "Bienvenue sur Checkmate !"
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "Mot de passe oublié ?",
|
"heading": "Mot de passe oublié ?",
|
||||||
@@ -745,7 +791,8 @@
|
|||||||
"failCountHeader": "Nombre d'échecs",
|
"failCountHeader": "Nombre d'échecs",
|
||||||
"lastRunHeader": "Dernière tentative le",
|
"lastRunHeader": "Dernière tentative le",
|
||||||
"lastFinishedAtHeader": "Dernière finalisation à",
|
"lastFinishedAtHeader": "Dernière finalisation à",
|
||||||
"lastRunTookHeader": "Dernière exécution effectuée"
|
"lastRunTookHeader": "Dernière exécution effectuée",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "Métriques des files",
|
"title": "Métriques des files",
|
||||||
@@ -851,6 +898,10 @@
|
|||||||
"selectDisabled": "Désactivé",
|
"selectDisabled": "Désactivé",
|
||||||
"selectEnabled": "Activé",
|
"selectEnabled": "Activé",
|
||||||
"title": "IP/URL du moniteur sur la page de statut"
|
"title": "IP/URL du moniteur sur la page de statut"
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "Seuils globaux",
|
||||||
|
"description": "Configurez des seuils globaux pour le CPU, la mémoire, le disque et la température. Si une valeur est fournie, elle sera automatiquement activée pour la surveillance."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -876,9 +927,13 @@
|
|||||||
"generalSettings": "Paramètres généraux",
|
"generalSettings": "Paramètres généraux",
|
||||||
"contents": "Contenus",
|
"contents": "Contenus",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Surveillez et affichez l’état de santé de vos services en temps réel",
|
||||||
"actionButton": ""
|
"Suivez plusieurs services et partagez leur statut",
|
||||||
|
"Tenez les utilisateurs informés des pannes et des performances"
|
||||||
|
],
|
||||||
|
"title": "Une page de status est utilisée pour :",
|
||||||
|
"actionButton": "Créer votre première page de status !"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testNotificationsDisabled": "Il n'y aucune notification paramétrée pour ce moniteur. Vous pouvez en ajouter une en cliquant sur le bouton 'Configurer'",
|
"testNotificationsDisabled": "Il n'y aucune notification paramétrée pour ce moniteur. Vous pouvez en ajouter une en cliquant sur le bouton 'Configurer'",
|
||||||
@@ -919,57 +974,149 @@
|
|||||||
"twentyMinutes": "20 minutes",
|
"twentyMinutes": "20 minutes",
|
||||||
"oneHour": "1 heure",
|
"oneHour": "1 heure",
|
||||||
"oneDay": "1 jour",
|
"oneDay": "1 jour",
|
||||||
"oneWeek": "1 semaine"
|
"oneWeek": "1 semaine",
|
||||||
|
"fourMinutes": "4 minutes",
|
||||||
|
"oneMinute": "1 minute",
|
||||||
|
"twoMinutes": "2 minutes",
|
||||||
|
"fifteenSeconds": "15 secondes",
|
||||||
|
"thirtySeconds": "30 secondes"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": "Aucune {{unit}} trouvée"
|
||||||
},
|
},
|
||||||
"infrastructureMonitor": {
|
"infrastructureMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Suivez les performances de vos serveurs",
|
||||||
"actionButton": ""
|
"Identifiez les points de blocage et optimisez l’utilisation",
|
||||||
|
"Assurez la fiabilité grâce à la surveillance en temps réel"
|
||||||
|
],
|
||||||
|
"title": "Une surveillance d'infrastructure est utilisé pour :",
|
||||||
|
"actionButton": "Créer votre premier moniteur d'infrastructure !"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"maintenanceWindow": {
|
"maintenanceWindow": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Marquez vos périodes de maintenance",
|
||||||
"actionButton": ""
|
"Éliminez tout malentendu",
|
||||||
|
"Arrêtez d’envoyer des alertes pendant les fenêtres de maintenance"
|
||||||
|
],
|
||||||
|
"title": "Une fenêtre de maintenance est utilisé pour :",
|
||||||
|
"actionButton": "Créer votre première fenêtre de maintenance !"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageSpeed": {
|
"pageSpeed": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
|
"Rapport sur l’expérience utilisateur d’une page",
|
||||||
|
"Aider à analyser la vitesse de la page web",
|
||||||
|
"Donner des suggestions sur la façon dont la page peut être améliorée"
|
||||||
|
],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"uptimeMonitor": {
|
"uptimeMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
|
"Vérifiez si les sites web ou serveurs sont en ligne et réactifs",
|
||||||
|
"Alertez les équipes en cas de panne ou de problème de performance",
|
||||||
|
"Surveillez les points de terminaison HTTP, les pings, les conteneurs et les ports",
|
||||||
|
"Suivez l’historique de la disponibilité et les tendances de fiabilité"
|
||||||
|
],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editUserPage": {
|
"editUserPage": {
|
||||||
"form": {
|
"form": {
|
||||||
"email": "",
|
"email": "Email",
|
||||||
"firstName": "",
|
"firstName": "Prénom",
|
||||||
"lastName": "",
|
"lastName": "Nom",
|
||||||
"role": "",
|
"role": "Rôles",
|
||||||
"save": ""
|
"save": "Enregistrer"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"actionHeader": "",
|
"actionHeader": "Action",
|
||||||
"roleHeader": ""
|
"roleHeader": "Rôle"
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": "Modifier l'utilisateur",
|
||||||
"toast": {
|
"toast": {
|
||||||
"successUserUpdate": "",
|
"successUserUpdate": "L'utilisateur à bien été modifié",
|
||||||
"validationErrors": ""
|
"validationErrors": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "Résoudres les incidents de surveillance",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "Résoudre tous les incidents",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "Égal",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "Inclure",
|
||||||
|
"includePlaceholder": "ok",
|
||||||
|
"regex": "Regex",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "ID du conteneur",
|
||||||
|
"namePlaceholder": "Mon conteneur",
|
||||||
|
"placeholder": "abcd1234"
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "URL à surveiller",
|
||||||
|
"namePlaceholder": "Google",
|
||||||
|
"placeholder": "google.com"
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "Adresse IP à surveiller",
|
||||||
|
"namePlaceholder": "Google",
|
||||||
|
"placeholder": "1.1.1.1"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "URL à surveiller",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": "localhost"
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": "Chemin JSON"
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+133
-7
@@ -264,7 +264,6 @@
|
|||||||
"notifyEmails": "複数のアドレスにメールでも通知(近日公開)",
|
"notifyEmails": "複数のアドレスにメールでも通知(近日公開)",
|
||||||
"seperateEmails": "複数のメールはカンマで区切ることができます",
|
"seperateEmails": "複数のメールはカンマで区切ることができます",
|
||||||
"checkFrequency": "チェック頻度",
|
"checkFrequency": "チェック頻度",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "マッチ方法",
|
"matchMethod": "マッチ方法",
|
||||||
"expectedValue": "期待値",
|
"expectedValue": "期待値",
|
||||||
"deleteDialogTitle": "本当にこのモニターを削除しますか?",
|
"deleteDialogTitle": "本当にこのモニターを削除しますか?",
|
||||||
@@ -381,7 +380,52 @@
|
|||||||
"email": "メール",
|
"email": "メール",
|
||||||
"role": "役割",
|
"role": "役割",
|
||||||
"created": "作成日"
|
"created": "作成日"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "一時停止",
|
"paused": "一時停止",
|
||||||
@@ -573,7 +617,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": "入力されたパスワードが記録と一致しません"
|
"incorrect": "入力されたパスワードが記録と一致しません"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -599,7 +644,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "ようこそ!アカウントが正常に作成されました。"
|
"success": "ようこそ!アカウントが正常に作成されました。"
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "パスワードを忘れましたか?",
|
"heading": "パスワードを忘れましたか?",
|
||||||
@@ -745,7 +791,8 @@
|
|||||||
"failCountHeader": "失敗回数",
|
"failCountHeader": "失敗回数",
|
||||||
"lastRunHeader": "最終実行日時",
|
"lastRunHeader": "最終実行日時",
|
||||||
"lastFinishedAtHeader": "最終完了日時",
|
"lastFinishedAtHeader": "最終完了日時",
|
||||||
"lastRunTookHeader": "最終実行時間"
|
"lastRunTookHeader": "最終実行時間",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "キューメトリック",
|
"title": "キューメトリック",
|
||||||
@@ -851,6 +898,10 @@
|
|||||||
"selectDisabled": "無効",
|
"selectDisabled": "無効",
|
||||||
"selectEnabled": "有効",
|
"selectEnabled": "有効",
|
||||||
"title": "ステータスページのモニターIP/URL"
|
"title": "ステータスページのモニターIP/URL"
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -919,7 +970,12 @@
|
|||||||
"twentyMinutes": "20分",
|
"twentyMinutes": "20分",
|
||||||
"oneHour": "1時間",
|
"oneHour": "1時間",
|
||||||
"oneDay": "1日",
|
"oneDay": "1日",
|
||||||
"oneWeek": "1週間"
|
"oneWeek": "1週間",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -971,5 +1027,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+447
-296
@@ -84,31 +84,35 @@
|
|||||||
"unsupportedType": "Tipo de notificação não suportado",
|
"unsupportedType": "Tipo de notificação não suportado",
|
||||||
"networkError": "Ocorreu um erro de rede",
|
"networkError": "Ocorreu um erro de rede",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"title": "",
|
"title": "Um canal de notificação é usado para:",
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"actionButton": ""
|
"Alerte as equipes sobre tempo de inatividade ou problemas de desempenho",
|
||||||
|
"Informe os engenheiros sobre incidentes",
|
||||||
|
"Mantenha os administradores informados sobre as mudanças no sistema"
|
||||||
|
],
|
||||||
|
"actionButton": "Vamos criar seu primeiro canal de notificação!"
|
||||||
},
|
},
|
||||||
"createButton": "",
|
"createButton": "Criar canal de notificação",
|
||||||
"createTitle": "",
|
"createTitle": "Canal de notificação",
|
||||||
"create": {
|
"create": {
|
||||||
"success": "",
|
"success": "Notificação criada com sucesso",
|
||||||
"failed": ""
|
"failed": "Falha ao criar notificação"
|
||||||
},
|
},
|
||||||
"fetch": {
|
"fetch": {
|
||||||
"success": "",
|
"success": "Notificações obtidas com sucesso",
|
||||||
"failed": ""
|
"failed": "Falha ao buscar notificações"
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"success": "",
|
"success": "Notificação excluída com sucesso",
|
||||||
"failed": ""
|
"failed": "Falha ao excluir a notificação"
|
||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"success": "",
|
"success": "Notificação atualizada com sucesso",
|
||||||
"failed": ""
|
"failed": "Falha ao atualizar a notificação"
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"success": "",
|
"success": "Notificação de teste enviada com sucesso",
|
||||||
"failed": ""
|
"failed": "Falha ao enviar notificação de teste"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testLocale": "testLocale",
|
"testLocale": "testLocale",
|
||||||
@@ -260,7 +264,6 @@
|
|||||||
"notifyEmails": "Também notificar por e-mail para vários endereços (em breve)",
|
"notifyEmails": "Também notificar por e-mail para vários endereços (em breve)",
|
||||||
"seperateEmails": "Você pode separar vários e-mails com uma vírgula",
|
"seperateEmails": "Você pode separar vários e-mails com uma vírgula",
|
||||||
"checkFrequency": "Verifique a frequência",
|
"checkFrequency": "Verifique a frequência",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "Método de correspondência",
|
"matchMethod": "Método de correspondência",
|
||||||
"expectedValue": "Valor esperado",
|
"expectedValue": "Valor esperado",
|
||||||
"deleteDialogTitle": "Você realmente deseja excluir este monitor?",
|
"deleteDialogTitle": "Você realmente deseja excluir este monitor?",
|
||||||
@@ -333,8 +336,8 @@
|
|||||||
"validationFailed": "Falha na validação",
|
"validationFailed": "Falha na validação",
|
||||||
"noFileSelected": "Nenhum arquivo selecionado",
|
"noFileSelected": "Nenhum arquivo selecionado",
|
||||||
"fallbackPage": "Importe um arquivo para enviar uma lista de servidores em massa",
|
"fallbackPage": "Importe um arquivo para enviar uma lista de servidores em massa",
|
||||||
"invalidFileType": "",
|
"invalidFileType": "Tipo de arquivo inválido",
|
||||||
"uploadFailed": ""
|
"uploadFailed": "Falha no upload"
|
||||||
},
|
},
|
||||||
"DeleteAccountTitle": "Remover conta",
|
"DeleteAccountTitle": "Remover conta",
|
||||||
"DeleteAccountButton": "Remover conta",
|
"DeleteAccountButton": "Remover conta",
|
||||||
@@ -377,7 +380,52 @@
|
|||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"role": "Cargo",
|
"role": "Cargo",
|
||||||
"created": "Criado"
|
"created": "Criado"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Pausado",
|
"paused": "Pausado",
|
||||||
@@ -401,8 +449,8 @@
|
|||||||
"password": "Senha",
|
"password": "Senha",
|
||||||
"team": "Equipe",
|
"team": "Equipe",
|
||||||
"logOut": "Sair",
|
"logOut": "Sair",
|
||||||
"notifications": "",
|
"notifications": "Notificações",
|
||||||
"logs": ""
|
"logs": "Registros"
|
||||||
},
|
},
|
||||||
"settingsEmailUser": "Usuário de e-mail - Nome de usuário para autenticação, substitui o endereço de e-mail, se especificado",
|
"settingsEmailUser": "Usuário de e-mail - Nome de usuário para autenticação, substitui o endereço de e-mail, se especificado",
|
||||||
"state": "Estado",
|
"state": "Estado",
|
||||||
@@ -477,41 +525,41 @@
|
|||||||
},
|
},
|
||||||
"special": {
|
"special": {
|
||||||
"beginning": "Deve conter pelo menos",
|
"beginning": "Deve conter pelo menos",
|
||||||
"highlighted": ""
|
"highlighted": "um caractere especial"
|
||||||
},
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"beginning": "",
|
"beginning": "Deve ter pelo menos",
|
||||||
"highlighted": ""
|
"highlighted": "um número"
|
||||||
},
|
},
|
||||||
"uppercase": {
|
"uppercase": {
|
||||||
"beginning": "",
|
"beginning": "Deve ter pelo menos",
|
||||||
"highlighted": ""
|
"highlighted": "uma letra maiúscula"
|
||||||
},
|
},
|
||||||
"lowercase": {
|
"lowercase": {
|
||||||
"beginning": "",
|
"beginning": "Deve ter pelo menos",
|
||||||
"highlighted": ""
|
"highlighted": "uma letra minúscula"
|
||||||
},
|
},
|
||||||
"match": {
|
"match": {
|
||||||
"beginning": "",
|
"beginning": "Senha e confirmação de senha",
|
||||||
"highlighted": ""
|
"highlighted": "devem combinar"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "Por favor, digite sua senha",
|
"empty": "Por favor, digite sua senha",
|
||||||
"length": "A senha deve ter pelo menos 8 caracteres",
|
"length": "A senha deve ter pelo menos 8 caracteres",
|
||||||
"uppercase": "A senha deve conter pelo menos 1 letra maiúscula",
|
"uppercase": "A senha deve conter pelo menos 1 letra maiúscula",
|
||||||
"lowercase": "",
|
"lowercase": "Senha deve ter pelo menos uma letra minúscula",
|
||||||
"number": "",
|
"number": "Senha deve ter pelo menos um número",
|
||||||
"special": "",
|
"special": "Senha deve ter pelo menos um caractere especial",
|
||||||
"incorrect": ""
|
"incorrect": "A senha que você forneceu não está registrada"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"passwordConfirm": {
|
"passwordConfirm": {
|
||||||
"label": "",
|
"label": "Confirme a senha",
|
||||||
"placeholder": "",
|
"placeholder": "Informe a senha novamente para confirmar",
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "",
|
"empty": "Por favor, informe a senha novamente para confirmação (cuidado com erros de digitação)",
|
||||||
"different": ""
|
"different": "As senhas informadas não combinam, então uma deve estar errada"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"firstName": {
|
"firstName": {
|
||||||
@@ -539,12 +587,12 @@
|
|||||||
"fields": {
|
"fields": {
|
||||||
"password": {
|
"password": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"incorrect": ""
|
"incorrect": "A senha que você forneceu não corresponde aos nossos registros"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"min": ""
|
"min": "Pelo menos uma função é necessária"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -558,8 +606,8 @@
|
|||||||
"links": {
|
"links": {
|
||||||
"forgotPassword": "Esqueceu sua senha?",
|
"forgotPassword": "Esqueceu sua senha?",
|
||||||
"register": "Não tem uma conta?",
|
"register": "Não tem uma conta?",
|
||||||
"forgotPasswordLink": "",
|
"forgotPasswordLink": "Redefinir senha",
|
||||||
"registerLink": ""
|
"registerLink": "Registre-se aqui"
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "Bem-vindo de volta! Você está autenticado.",
|
"success": "Bem-vindo de volta! Você está autenticado.",
|
||||||
@@ -567,9 +615,10 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": "A senha que você forneceu não corresponde aos nossos registros"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -577,42 +626,43 @@
|
|||||||
"user": "Se inscrever"
|
"user": "Se inscrever"
|
||||||
},
|
},
|
||||||
"subheadings": {
|
"subheadings": {
|
||||||
"stepOne": "",
|
"stepOne": "Informe seus dados pessoais",
|
||||||
"stepTwo": "",
|
"stepTwo": "Informe seu email",
|
||||||
"stepThree": ""
|
"stepThree": "Crie sua senha"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"superAdmin": "",
|
"superAdmin": "Crie sua conta de superadministrador para começar",
|
||||||
"user": ""
|
"user": "Cadastre-se como usuário e peça ao superadministrador acesso aos seus monitores"
|
||||||
},
|
},
|
||||||
"gettingStartedButton": {
|
"gettingStartedButton": {
|
||||||
"superAdmin": "",
|
"superAdmin": "Criar conta de superadministrador",
|
||||||
"user": ""
|
"user": "Cadastre-se como usuário normal"
|
||||||
},
|
},
|
||||||
"termsAndPolicies": "",
|
"termsAndPolicies": "Ao criar uma conta, você concorda com nossos <a1>Termos de Serviço</a1> e <a2>Política de Privacidade</a2>.",
|
||||||
"links": {
|
"links": {
|
||||||
"login": ""
|
"login": "Já tem uma conta? <a>Entrar</a>"
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": ""
|
"success": "Bem-vindo! Sua conta foi criada com sucesso."
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "",
|
"heading": "Esqueceu sua senha?",
|
||||||
"subheadings": {
|
"subheadings": {
|
||||||
"stepOne": "",
|
"stepOne": "Não se preocupe, enviaremos instruções de redefinição.",
|
||||||
"stepTwo": "",
|
"stepTwo": "Enviamos um link de redefinição de senha para <email/>",
|
||||||
"stepThree": "",
|
"stepThree": "Sua nova senha deve ser diferente das senhas usadas anteriormente.",
|
||||||
"stepFour": ""
|
"stepFour": "Sua senha foi redefinida com sucesso. Clique abaixo para fazer login magicamente."
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"openEmail": "",
|
"openEmail": "Abra o aplicativo de e-mail",
|
||||||
"resetPassword": ""
|
"resetPassword": "Redefinir senha"
|
||||||
},
|
},
|
||||||
"imageAlts": {
|
"imageAlts": {
|
||||||
"passwordKey": "",
|
"passwordKey": "Ícone de chave de senha",
|
||||||
"email": "",
|
"email": "Ícone de e-mail",
|
||||||
"lock": "",
|
"lock": "Ícone de cadeado",
|
||||||
"passwordConfirm": "Ícone de confirmação de senha"
|
"passwordConfirm": "Ícone de confirmação de senha"
|
||||||
},
|
},
|
||||||
"links": {
|
"links": {
|
||||||
@@ -620,352 +670,453 @@
|
|||||||
"resend": "Não recebeu o email? <a>Clique para reenviar</a>"
|
"resend": "Não recebeu o email? <a>Clique para reenviar</a>"
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"sent": "",
|
"sent": "Instruções enviadas para <email/>.",
|
||||||
"emailNotFound": "",
|
"emailNotFound": "E-mail não encontrado.",
|
||||||
"redirect": "",
|
"redirect": "Redirecionando em <segundos/>...",
|
||||||
"success": "",
|
"success": "Sua senha foi redefinida com sucesso.",
|
||||||
"error": ""
|
"error": "Não foi possível redefinir a senha. Tente novamente mais tarde ou entre em contato com o suporte."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"errorPages": {
|
"errorPages": {
|
||||||
"serverUnreachable": {
|
"serverUnreachable": {
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"reconnected": "",
|
"reconnected": "Reconectado ao servidor com sucesso.",
|
||||||
"stillUnreachable": ""
|
"stillUnreachable": "O servidor ainda está inacessível. Tente novamente mais tarde."
|
||||||
},
|
},
|
||||||
"alertBox": "",
|
"alertBox": "Erro de conexão do servidor",
|
||||||
"description": "",
|
"description": "Não conseguimos conectar ao servidor. Verifique sua conexão com a internet ou sua configuração de implantação se o problema persistir.",
|
||||||
"retryButton": {
|
"retryButton": {
|
||||||
"default": "",
|
"default": "Tentar conectar novamente",
|
||||||
"processing": ""
|
"processing": "Conectando..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"createNotifications": {
|
"createNotifications": {
|
||||||
"title": "",
|
"title": "Criar canal de notificação",
|
||||||
"nameSettings": {
|
"nameSettings": {
|
||||||
"title": "",
|
"title": "Nome",
|
||||||
"description": "",
|
"description": "Um nome descritivo para sua integração.",
|
||||||
"nameLabel": "",
|
"nameLabel": "Nome",
|
||||||
"namePlaceholder": ""
|
"namePlaceholder": "por exemplo, notificações do Slack"
|
||||||
},
|
},
|
||||||
"typeSettings": {
|
"typeSettings": {
|
||||||
"title": "",
|
"title": "Tipo",
|
||||||
"description": "",
|
"description": "Selecione o tipo de canal de notificação que você deseja criar.",
|
||||||
"typeLabel": ""
|
"typeLabel": "Tipo"
|
||||||
},
|
},
|
||||||
"emailSettings": {
|
"emailSettings": {
|
||||||
"title": "",
|
"title": "E-mail",
|
||||||
"description": "",
|
"description": "Endereços de e-mail de destino.",
|
||||||
"emailLabel": "",
|
"emailLabel": "Endereço de email",
|
||||||
"emailPlaceholder": ""
|
"emailPlaceholder": "por exemplo john@example.com"
|
||||||
},
|
},
|
||||||
"slackSettings": {
|
"slackSettings": {
|
||||||
"title": "",
|
"title": "Folga",
|
||||||
"description": "",
|
"description": "Configure seu webhook do Slack aqui",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "URL do webhook do Slack",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": "https://hooks.slack.com/services/..."
|
||||||
},
|
},
|
||||||
"pagerdutySettings": {
|
"pagerdutySettings": {
|
||||||
"title": "",
|
"title": "PagerDuty",
|
||||||
"description": "",
|
"description": "Configure sua integração com o PagerDuty aqui",
|
||||||
"integrationKeyLabel": "",
|
"integrationKeyLabel": "Chave de integração",
|
||||||
"integrationKeyPlaceholder": ""
|
"integrationKeyPlaceholder": "1234567890"
|
||||||
},
|
},
|
||||||
"discordSettings": {
|
"discordSettings": {
|
||||||
"title": "",
|
"title": "Discórdia",
|
||||||
"description": "",
|
"description": "Configure seu webhook do Discord aqui",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "URL do webhook do Discord",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": "https://seu-servidor.com/webhook"
|
||||||
},
|
},
|
||||||
"webhookSettings": {
|
"webhookSettings": {
|
||||||
"title": "",
|
"title": "Webhook",
|
||||||
"description": "",
|
"description": "Configure seu webhook aqui",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "URL do webhook",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": "https://seu-servidor.com/webhook"
|
||||||
},
|
},
|
||||||
"testNotification": "",
|
"testNotification": "Notificação de teste",
|
||||||
"dialogDeleteTitle": "",
|
"dialogDeleteTitle": "Tem certeza de que deseja excluir esta notificação?",
|
||||||
"dialogDeleteConfirm": ""
|
"dialogDeleteConfirm": "Excluir"
|
||||||
},
|
},
|
||||||
"notificationConfig": {
|
"notificationConfig": {
|
||||||
"title": "",
|
"title": "Notificações",
|
||||||
"description": ""
|
"description": "Selecione os canais de notificação que deseja usar"
|
||||||
},
|
},
|
||||||
"monitorStatus": {
|
"monitorStatus": {
|
||||||
"checkingEvery": "",
|
"checkingEvery": "Verificando a cada {{intervalo}}",
|
||||||
"withCaptureAgent": "",
|
"withCaptureAgent": "com agente de captura {{versão}}",
|
||||||
"up": "",
|
"up": "acima",
|
||||||
"down": "",
|
"down": "abaixo",
|
||||||
"paused": ""
|
"paused": "pausado"
|
||||||
},
|
},
|
||||||
"advancedMatching": "",
|
"advancedMatching": "Correspondência avançada",
|
||||||
"sendTestNotifications": "",
|
"sendTestNotifications": "Enviar notificações de teste",
|
||||||
"selectAll": "",
|
"selectAll": "Selecionar tudo",
|
||||||
"showAdminLoginLink": "",
|
"showAdminLoginLink": "Mostrar o link \"Administrador? Efetue login aqui\" na página de status",
|
||||||
"logsPage": {
|
"logsPage": {
|
||||||
"title": "",
|
"title": "Registros",
|
||||||
"description": "",
|
"description": "Logs do sistema - últimas 1000 linhas",
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"queue": "",
|
"queue": "Fila de tarefas",
|
||||||
"logs": "",
|
"logs": "Logs do servidor",
|
||||||
"diagnostics": ""
|
"diagnostics": "Diagnóstico"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"fetchLogsSuccess": ""
|
"fetchLogsSuccess": "Logs obtidos com sucesso"
|
||||||
},
|
},
|
||||||
"logLevelSelect": {
|
"logLevelSelect": {
|
||||||
"title": "",
|
"title": "Nível de log",
|
||||||
"values": {
|
"values": {
|
||||||
"all": "",
|
"all": "Todos",
|
||||||
"info": "",
|
"info": "Informações",
|
||||||
"warn": "",
|
"warn": "Avisar",
|
||||||
"error": "",
|
"error": "Erro",
|
||||||
"debug": ""
|
"debug": "Depurar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"queuePage": {
|
"queuePage": {
|
||||||
"title": "",
|
"title": "Fila",
|
||||||
"refreshButton": "",
|
"refreshButton": "Atualizar",
|
||||||
"flushButton": "",
|
"flushButton": "Fila de descarga",
|
||||||
"jobTable": {
|
"jobTable": {
|
||||||
"title": "",
|
"title": "Empregos atualmente na fila",
|
||||||
"idHeader": "",
|
"idHeader": "ID do monitor",
|
||||||
"urlHeader": "",
|
"urlHeader": "URL",
|
||||||
"typeHeader": "",
|
"typeHeader": "Tipo",
|
||||||
"activeHeader": "",
|
"activeHeader": "Ativo",
|
||||||
"lockedAtHeader": "",
|
"lockedAtHeader": "Trancado em",
|
||||||
"runCountHeader": "",
|
"runCountHeader": "Contagem de corridas",
|
||||||
"failCountHeader": "",
|
"failCountHeader": "Contagem de falhas",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "Última corrida em",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "Última conclusão em",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "A última corrida aconteceu",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "Métricas de fila",
|
||||||
"metricHeader": "",
|
"metricHeader": "Métrica",
|
||||||
"valueHeader": ""
|
"valueHeader": "Valor"
|
||||||
},
|
},
|
||||||
"failedJobTable": {
|
"failedJobTable": {
|
||||||
"title": "",
|
"title": "Trabalhos com falha",
|
||||||
"monitorIdHeader": "",
|
"monitorIdHeader": "ID do monitor",
|
||||||
"monitorUrlHeader": "",
|
"monitorUrlHeader": "URL do monitor",
|
||||||
"failCountHeader": "",
|
"failCountHeader": "Contagem de falhas",
|
||||||
"failedAtHeader": "",
|
"failedAtHeader": "Última falha em",
|
||||||
"failReasonHeader": ""
|
"failReasonHeader": "Motivo da falha"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "",
|
"title": "Monitores de Exportação",
|
||||||
"success": "",
|
"success": "Monitores exportados com sucesso!",
|
||||||
"failed": ""
|
"failed": "Falha ao exportar monitores"
|
||||||
},
|
},
|
||||||
"monitorActions": {
|
"monitorActions": {
|
||||||
"title": "",
|
"title": "Exportação/Importação",
|
||||||
"import": "",
|
"import": "Monitores de importação",
|
||||||
"export": "",
|
"export": "Monitores de Exportação",
|
||||||
"deleteSuccess": "",
|
"deleteSuccess": "Monitor excluído com sucesso",
|
||||||
"deleteFailed": "",
|
"deleteFailed": "Falha ao excluir o monitor",
|
||||||
"details": ""
|
"details": "Detalhes"
|
||||||
},
|
},
|
||||||
"settingsPage": {
|
"settingsPage": {
|
||||||
"aboutSettings": {
|
"aboutSettings": {
|
||||||
"labelDevelopedBy": "",
|
"labelDevelopedBy": "Desenvolvido pela Bluewave Labs",
|
||||||
"labelVersion": "",
|
"labelVersion": "Versão",
|
||||||
"title": ""
|
"title": "Sobre"
|
||||||
},
|
},
|
||||||
"demoMonitorsSettings": {
|
"demoMonitorsSettings": {
|
||||||
"buttonAddMonitors": "",
|
"buttonAddMonitors": "Adicionar monitores de demonstração",
|
||||||
"description": "",
|
"description": "Adicione monitores de amostra para fins de demonstração.",
|
||||||
"title": ""
|
"title": "Monitores de demonstração"
|
||||||
},
|
},
|
||||||
"emailSettings": {
|
"emailSettings": {
|
||||||
"buttonSendTestEmail": "",
|
"buttonSendTestEmail": "Enviar e-mail de teste",
|
||||||
"description": "",
|
"description": "Configure as configurações de e-mail do seu sistema. Elas são usadas para enviar notificações e alertas.",
|
||||||
"descriptionTransport": "",
|
"descriptionTransport": "Isso cria um transporte SMTP para o NodeMailer",
|
||||||
"labelAddress": "",
|
"labelAddress": "Endereço de e-mail - Usado para autenticação",
|
||||||
"labelConnectionHost": "",
|
"labelConnectionHost": "Host de conexão de e-mail - Nome do host a ser usado na saudação HELO/EHLO",
|
||||||
"labelHost": "",
|
"labelHost": "Host de e-mail - Nome do host ou endereço IP para conectar",
|
||||||
"labelIgnoreTLS": "",
|
"labelIgnoreTLS": "Desabilitar STARTTLS: Não use TLS mesmo que o servidor suporte",
|
||||||
"labelPassword": "",
|
"labelPassword": "Senha de e-mail - Senha para autenticação",
|
||||||
"labelPasswordSet": "",
|
"labelPasswordSet": "A senha foi definida. Clique em Redefinir para alterá-la.",
|
||||||
"labelPool": "",
|
"labelPool": "Habilitar pool de conexões: Reutilize conexões existentes para melhorar o desempenho",
|
||||||
"labelPort": "",
|
"labelPort": "Porta de e-mail - Porta para conectar",
|
||||||
"labelRejectUnauthorized": "",
|
"labelRejectUnauthorized": "Rejeitar certificados inválidos: rejeitar conexões com certificados autoassinados ou não confiáveis",
|
||||||
"labelRequireTLS": "",
|
"labelRequireTLS": "Forçar STARTTLS: requer atualização de TLS, falha se não for suportado",
|
||||||
"labelSecure": "",
|
"labelSecure": "Usar SSL (recomendado): criptografar a conexão usando SSL/TLS",
|
||||||
"labelTLSServername": "",
|
"labelTLSServername": "Nome do servidor TLS - Nome do host opcional para validação TLS quando o host é um IP",
|
||||||
"labelUser": "",
|
"labelUser": "Usuário de e-mail - Nome de usuário para autenticação, substitui o endereço de e-mail, se especificado",
|
||||||
"linkTransport": "",
|
"linkTransport": "Veja as especificações aqui",
|
||||||
"placeholderUser": "",
|
"placeholderUser": "Deixe em branco se não for necessário",
|
||||||
"title": "",
|
"title": "E-mail",
|
||||||
"toastEmailRequiredFieldsError": ""
|
"toastEmailRequiredFieldsError": "Endereço de e-mail, host, porta e senha são obrigatórios"
|
||||||
},
|
},
|
||||||
"pageSpeedSettings": {
|
"pageSpeedSettings": {
|
||||||
"description": "",
|
"description": "Insira sua chave da API do Google PageSpeed para ativar o monitoramento do Google PageSpeed. Clique em Redefinir para atualizar a chave.",
|
||||||
"labelApiKeySet": "",
|
"labelApiKeySet": "A chave de API está definida. Clique em Redefinir para alterá-la.",
|
||||||
"labelApiKey": "",
|
"labelApiKey": "Chave da API do PageSpeed",
|
||||||
"title": ""
|
"title": "Chave da API do Google PageSpeed"
|
||||||
},
|
},
|
||||||
"saveButtonLabel": "",
|
"saveButtonLabel": "Salvar",
|
||||||
"statsSettings": {
|
"statsSettings": {
|
||||||
"clearAllStatsButton": "",
|
"clearAllStatsButton": "Limpar todas as estatísticas",
|
||||||
"clearAllStatsDescription": "",
|
"clearAllStatsDescription": "Limpe todas as estatísticas. Isso é irreversível.",
|
||||||
"clearAllStatsDialogConfirm": "",
|
"clearAllStatsDialogConfirm": "Sim, limpar todas as estatísticas",
|
||||||
"clearAllStatsDialogDescription": "",
|
"clearAllStatsDialogDescription": "Uma vez removido, o histórico de monitoramento e as estatísticas não podem ser recuperados.",
|
||||||
"clearAllStatsDialogTitle": "",
|
"clearAllStatsDialogTitle": "Você quer limpar todas as estatísticas?",
|
||||||
"description": "",
|
"description": "Defina por quanto tempo você deseja manter os dados históricos. Você também pode limpar todos os dados existentes.",
|
||||||
"labelTTL": "",
|
"labelTTL": "Os dias em que você deseja continuar monitorando o histórico.",
|
||||||
"labelTTLOptional": "",
|
"labelTTLOptional": "0 para infinito",
|
||||||
"title": ""
|
"title": "Histórico do monitor"
|
||||||
},
|
},
|
||||||
"systemResetSettings": {
|
"systemResetSettings": {
|
||||||
"buttonRemoveAllMonitors": "",
|
"buttonRemoveAllMonitors": "Remover todos os monitores",
|
||||||
"description": "",
|
"description": "Remova todos os monitores do seu sistema.",
|
||||||
"dialogConfirm": "",
|
"dialogConfirm": "Sim, remova todos os monitores",
|
||||||
"dialogDescription": "",
|
"dialogDescription": "Uma vez removidos, os monitores não podem ser recuperados.",
|
||||||
"dialogTitle": "",
|
"dialogTitle": "Você deseja remover todos os monitores?",
|
||||||
"title": ""
|
"title": "Reinicialização do sistema"
|
||||||
},
|
},
|
||||||
"timezoneSettings": {
|
"timezoneSettings": {
|
||||||
"description": "",
|
"description": "Selecione o fuso horário usado para exibir datas e horas em todo o aplicativo.",
|
||||||
"label": "",
|
"label": "Exibir fuso horário",
|
||||||
"title": ""
|
"title": "Exibir fuso horário"
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": "Configurações",
|
||||||
"uiSettings": {
|
"uiSettings": {
|
||||||
"description": "",
|
"description": "Alterne entre o modo claro e escuro ou altere o idioma da interface do usuário.",
|
||||||
"labelLanguage": "",
|
"labelLanguage": "Linguagem",
|
||||||
"labelTheme": "",
|
"labelTheme": "Modo de tema",
|
||||||
"title": ""
|
"title": "Aparência"
|
||||||
},
|
},
|
||||||
"urlSettings": {
|
"urlSettings": {
|
||||||
"description": "",
|
"description": "Exiba o endereço IP ou URL do monitor na página de status pública. Se estiver desabilitado, apenas o nome do monitor será exibido para proteger informações confidenciais.",
|
||||||
"label": "",
|
"label": "Exibir IP/URL na página de status",
|
||||||
"selectDisabled": "",
|
"selectDisabled": "Desabilitado",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "Habilitado",
|
||||||
"title": ""
|
"title": "Monitorar IP/URL na página de status"
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "Limites Globais",
|
||||||
|
"description": "Configurar limites globais da CPU, Memória, Disco e Temperatura. Se um valor for fornecido, o monitoramento será ativado automaticamente"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
"buttonSave": ""
|
"buttonSave": "Salvar"
|
||||||
},
|
},
|
||||||
"incidentsOptionsHeaderFilterResolved": "",
|
"incidentsOptionsHeaderFilterResolved": "Resolvido",
|
||||||
"settingsSave": "",
|
"settingsSave": "Salvar",
|
||||||
"statusPageCreateAppearanceTitle": "",
|
"statusPageCreateAppearanceTitle": "Aparência",
|
||||||
"confirmPassword": "",
|
"confirmPassword": "Confirme sua senha",
|
||||||
"monitorHooks": {
|
"monitorHooks": {
|
||||||
"failureAddDemoMonitors": "",
|
"failureAddDemoMonitors": "Falha ao adicionar monitores de demonstração",
|
||||||
"successAddDemoMonitors": ""
|
"successAddDemoMonitors": "Monitores de demonstração adicionados com sucesso"
|
||||||
},
|
},
|
||||||
"settingsAppearance": "",
|
"settingsAppearance": "Aparência",
|
||||||
"settingsDisplayTimezone": "",
|
"settingsDisplayTimezone": "Exibir fuso horário",
|
||||||
"settingsGeneralSettings": "",
|
"settingsGeneralSettings": "Configurações gerais",
|
||||||
"incidentsOptionsHeaderTotalIncidents": "",
|
"incidentsOptionsHeaderTotalIncidents": "Total de incidentes",
|
||||||
"statusPage": {
|
"statusPage": {
|
||||||
"deleteSuccess": "",
|
"deleteSuccess": "Página de status excluída com sucesso",
|
||||||
"deleteFailed": "",
|
"deleteFailed": "Falha ao excluir a página de status",
|
||||||
"createSuccess": "",
|
"createSuccess": "Página de status criada com sucesso",
|
||||||
"updateSuccess": "",
|
"updateSuccess": "Página de status atualizada com sucesso",
|
||||||
"generalSettings": "",
|
"generalSettings": "Configurações gerais",
|
||||||
"contents": "",
|
"contents": "Conteúdo",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Monitore e exiba a integridade dos seus serviços em tempo real",
|
||||||
"actionButton": ""
|
"Acompanhe vários serviços e compartilhe seus status",
|
||||||
|
"Mantenha os usuários informados sobre interrupções e desempenho"
|
||||||
|
],
|
||||||
|
"title": "Uma página de status é usada para:",
|
||||||
|
"actionButton": "Vamos criar sua primeira página de status!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testNotificationsDisabled": "",
|
"testNotificationsDisabled": "Não há notificações configuradas para este monitor. Você precisa adicionar uma clicando no botão \"Configurar\".",
|
||||||
"incidentsTableResolvedAt": "",
|
"incidentsTableResolvedAt": "Resolvido em",
|
||||||
"incidentsTableActionResolve": "",
|
"incidentsTableActionResolve": "Resolver",
|
||||||
"checkHooks": {
|
"checkHooks": {
|
||||||
"failureResolveOne": "",
|
"failureResolveOne": "Falha ao resolver o incidente.",
|
||||||
"failureResolveAll": "",
|
"failureResolveAll": "Falha ao resolver todos os incidentes.",
|
||||||
"failureResolveMonitor": ""
|
"failureResolveMonitor": "Falha ao resolver incidentes do monitor."
|
||||||
},
|
},
|
||||||
"checkFormError": "",
|
"checkFormError": "Verifique se há erros no formulário.",
|
||||||
"diagnosticsPage": {
|
"diagnosticsPage": {
|
||||||
"diagnosticDescription": "",
|
"diagnosticDescription": "Diagnóstico do sistema",
|
||||||
"statsDescription": "",
|
"statsDescription": "Estatísticas do sistema",
|
||||||
"gauges": {
|
"gauges": {
|
||||||
"heapAllocationTitle": "",
|
"heapAllocationTitle": "Alocação de heap",
|
||||||
"heapAllocationSubtitle": "",
|
"heapAllocationSubtitle": "% de memória disponível",
|
||||||
"heapUsageTitle": "",
|
"heapUsageTitle": "Uso de heap",
|
||||||
"heapUsageSubtitle": "",
|
"heapUsageSubtitle": "% de memória disponível",
|
||||||
"heapUtilizationTitle": "",
|
"heapUtilizationTitle": "Utilização de heap",
|
||||||
"heapUtilizationSubtitle": "",
|
"heapUtilizationSubtitle": "% do alocado",
|
||||||
"instantCpuUsageTitle": "",
|
"instantCpuUsageTitle": "Uso instantâneo da CPU",
|
||||||
"instantCpuUsageSubtitle": ""
|
"instantCpuUsageSubtitle": "% de 1s usados pela CPU"
|
||||||
},
|
},
|
||||||
"stats": {
|
"stats": {
|
||||||
"eventLoopDelayTitle": "",
|
"eventLoopDelayTitle": "Atraso do loop de eventos",
|
||||||
"uptimeTitle": "",
|
"uptimeTitle": "Tempo de atividade",
|
||||||
"usedHeapSizeTitle": "",
|
"usedHeapSizeTitle": "Tamanho de heap usado",
|
||||||
"totalHeapSizeTitle": "",
|
"totalHeapSizeTitle": "Tamanho total do heap",
|
||||||
"osMemoryLimitTitle": ""
|
"osMemoryLimitTitle": "Limite de memória do sistema operacional"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageSpeedLighthouseAPI": "",
|
"pageSpeedLighthouseAPI": "Use a API Lighthouse PageSpeed para monitorar seu site",
|
||||||
"time": {
|
"time": {
|
||||||
"threeMinutes": "",
|
"threeMinutes": "3 minutos",
|
||||||
"fiveMinutes": "",
|
"fiveMinutes": "5 minutos",
|
||||||
"tenMinutes": "",
|
"tenMinutes": "10 minutos",
|
||||||
"twentyMinutes": "",
|
"twentyMinutes": "20 minutos",
|
||||||
"oneHour": "",
|
"oneHour": "1 hora",
|
||||||
"oneDay": "",
|
"oneDay": "1 dia",
|
||||||
"oneWeek": ""
|
"oneWeek": "1 semana",
|
||||||
|
"fourMinutes": "4 minutos",
|
||||||
|
"oneMinute": "1 minuto",
|
||||||
|
"twoMinutes": "2 minutos",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": "Nenhuma {{unidade}} encontrada"
|
||||||
},
|
},
|
||||||
"infrastructureMonitor": {
|
"infrastructureMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Acompanhe o desempenho dos seus servidores",
|
||||||
"actionButton": ""
|
"Identifique gargalos e otimize o uso",
|
||||||
|
"Garanta a confiabilidade com monitoramento em tempo real"
|
||||||
|
],
|
||||||
|
"title": "Um monitor de infraestrutura é usado para:",
|
||||||
|
"actionButton": "Vamos criar seu primeiro monitor de infraestrutura!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"maintenanceWindow": {
|
"maintenanceWindow": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Marque seus períodos de manutenção",
|
||||||
"actionButton": ""
|
"Elimine qualquer mal-entendido",
|
||||||
|
"Pare de enviar alertas em janelas de manutenção"
|
||||||
|
],
|
||||||
|
"title": "Uma janela de manutenção é usada para:",
|
||||||
|
"actionButton": "Vamos criar sua primeira janela de manutenção!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageSpeed": {
|
"pageSpeed": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Relatar a experiência do usuário em uma página",
|
||||||
"actionButton": ""
|
"Ajudar a analisar a velocidade da página",
|
||||||
|
"Dar sugestões sobre como a página pode ser melhorada"
|
||||||
|
],
|
||||||
|
"title": "Um monitor PageSpeed é usado para:",
|
||||||
|
"actionButton": "Vamos criar seu primeiro monitor PageSpeed!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"uptimeMonitor": {
|
"uptimeMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"title": "",
|
"Verifique se sites ou servidores estão online e responsivos",
|
||||||
"actionButton": ""
|
"Alerte as equipes sobre tempo de inatividade ou problemas de desempenho",
|
||||||
|
"Monitore endpoints HTTP, pings, contêineres e portas",
|
||||||
|
"Acompanhe o histórico de tempo de atividade e tendências de confiabilidade"
|
||||||
|
],
|
||||||
|
"title": "Um monitor de tempo de atividade é usado para:",
|
||||||
|
"actionButton": "Vamos criar seu primeiro monitor de tempo de atividade!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editUserPage": {
|
"editUserPage": {
|
||||||
"form": {
|
"form": {
|
||||||
"email": "",
|
"email": "E-mail",
|
||||||
"firstName": "",
|
"firstName": "Primeiro nome",
|
||||||
"lastName": "",
|
"lastName": "Sobrenome",
|
||||||
"role": "",
|
"role": "Funções",
|
||||||
"save": ""
|
"save": "Salvar"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"actionHeader": "",
|
"actionHeader": "Ação",
|
||||||
"roleHeader": ""
|
"roleHeader": "Papel"
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": "Editar usuário",
|
||||||
"toast": {
|
"toast": {
|
||||||
"successUserUpdate": "",
|
"successUserUpdate": "Usuário atualizado com sucesso",
|
||||||
"validationErrors": ""
|
"validationErrors": "Erros de validação"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "Resolver incidentes de monitoramento",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "Resolver todos os incidentes",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "Regex",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "Meu Contêiner",
|
||||||
|
"placeholder": "abcd1234"
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "URL para monitorar",
|
||||||
|
"namePlaceholder": "Google",
|
||||||
|
"placeholder": "google.com"
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "Endereço IP para monitorar",
|
||||||
|
"namePlaceholder": "Google",
|
||||||
|
"placeholder": "1.1.1.1"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "URL para monitorar",
|
||||||
|
"namePlaceholder": "Localhost:5173",
|
||||||
|
"placeholder": "localhost"
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
+211
-85
@@ -260,7 +260,6 @@
|
|||||||
"notifyEmails": "Также уведомлять по электронной почте на несколько адресов (скоро)",
|
"notifyEmails": "Также уведомлять по электронной почте на несколько адресов (скоро)",
|
||||||
"seperateEmails": "Вы можете разделить несколько адресов электронной почты запятой.",
|
"seperateEmails": "Вы можете разделить несколько адресов электронной почты запятой.",
|
||||||
"checkFrequency": "Проверить частоту",
|
"checkFrequency": "Проверить частоту",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "Метод сопоставления",
|
"matchMethod": "Метод сопоставления",
|
||||||
"expectedValue": "Ожидаемое значение",
|
"expectedValue": "Ожидаемое значение",
|
||||||
"deleteDialogTitle": "Вы действительно хотите удалить этот монитор?",
|
"deleteDialogTitle": "Вы действительно хотите удалить этот монитор?",
|
||||||
@@ -377,7 +376,52 @@
|
|||||||
"email": "Email",
|
"email": "Email",
|
||||||
"role": "Роль",
|
"role": "Роль",
|
||||||
"created": "Создано"
|
"created": "Создано"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Остановлено",
|
"paused": "Остановлено",
|
||||||
@@ -422,23 +466,23 @@
|
|||||||
"passwordRequirements": "Новый пароль должен содержать не менее 8 символов и содержать как минимум одну заглавную букву, одну строчную букву, одну цифру и один специальный символ.",
|
"passwordRequirements": "Новый пароль должен содержать не менее 8 символов и содержать как минимум одну заглавную букву, одну строчную букву, одну цифру и один специальный символ.",
|
||||||
"saving": "Сохранение..."
|
"saving": "Сохранение..."
|
||||||
},
|
},
|
||||||
"emailSent": "",
|
"emailSent": "Письмо успешно отправлено",
|
||||||
"failedToSendEmail": "",
|
"failedToSendEmail": "Не удалось отправить письмо",
|
||||||
"settingsTestEmailSuccess": "",
|
"settingsTestEmailSuccess": "Тестовое письмо успешно отправлено",
|
||||||
"settingsTestEmailFailed": "",
|
"settingsTestEmailFailed": "Не удалось отправить тестовое письмо",
|
||||||
"settingsTestEmailFailedWithReason": "",
|
"settingsTestEmailFailedWithReason": "Не удалось отправить тестовое письмо: {{reason}}",
|
||||||
"settingsTestEmailUnknownError": "",
|
"settingsTestEmailUnknownError": "Неизвестная ошибка",
|
||||||
"statusMsg": {
|
"statusMsg": {
|
||||||
"paused": "",
|
"paused": "Мониторинг приостановлен",
|
||||||
"up": "",
|
"up": "",
|
||||||
"down": "",
|
"down": "",
|
||||||
"pending": ""
|
"pending": "Ожидание..."
|
||||||
},
|
},
|
||||||
"uptimeGeneralInstructions": {
|
"uptimeGeneralInstructions": {
|
||||||
"http": "",
|
"http": "Введите URL-адрес или IP-адрес для мониторинга (например, https://example.com/ или 192.168.1.100) и добавьте понятное имя, которое будет отображаться на панели инструментов.",
|
||||||
"ping": "",
|
"ping": "Ведите IP-адрес или имя хоста для пинга (например, 192.168.1.100 или example.com) и добавьте понятное имя, которое будет отображаться на панели инструментов.",
|
||||||
"docker": "",
|
"docker": "Введите Docker ID вашего контейнера. Docker ID должен быть полным 64-символьным Docker ID. Вы можете запустить docker inspect <short_id>, чтобы получить полный ID контейнера.",
|
||||||
"port": "",
|
"port": "Введите URL-адрес или IP-адрес сервера, номер порта и понятное имя, которое будет отображаться на панели инструментов.",
|
||||||
"game": ""
|
"game": ""
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
@@ -448,93 +492,93 @@
|
|||||||
"toggleTheme": ""
|
"toggleTheme": ""
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"networkError": "",
|
"networkError": "Ошибка сети",
|
||||||
"checkConnection": "",
|
"checkConnection": "Пожалуйста, проверьте свое сетевое соединение",
|
||||||
"unknownError": ""
|
"unknownError": "Неизвестная ошибка"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"common": {
|
"common": {
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"continue": "",
|
"continue": "Продолжить",
|
||||||
"back": ""
|
"back": "Назад"
|
||||||
},
|
},
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"email": {
|
"email": {
|
||||||
"label": "",
|
"label": "Электронная почта",
|
||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "",
|
"empty": "Для продолжения введите свой адрес электронной почты",
|
||||||
"invalid": ""
|
"invalid": "Пожалуйста, проверьте правильность введённого адреса электронной почты"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "",
|
"label": "Пароль",
|
||||||
"rules": {
|
"rules": {
|
||||||
"length": {
|
"length": {
|
||||||
"beginning": "",
|
"beginning": "Должен быть как минимум",
|
||||||
"highlighted": ""
|
"highlighted": "8 символов в длину"
|
||||||
},
|
},
|
||||||
"special": {
|
"special": {
|
||||||
"beginning": "",
|
"beginning": "Должен содержать как минимум",
|
||||||
"highlighted": ""
|
"highlighted": "один спецсимвол"
|
||||||
},
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"beginning": "",
|
"beginning": "Должен содержать как минимум",
|
||||||
"highlighted": ""
|
"highlighted": "одно число"
|
||||||
},
|
},
|
||||||
"uppercase": {
|
"uppercase": {
|
||||||
"beginning": "",
|
"beginning": "Должен содержать как минимум",
|
||||||
"highlighted": ""
|
"highlighted": "одну заглавную букву"
|
||||||
},
|
},
|
||||||
"lowercase": {
|
"lowercase": {
|
||||||
"beginning": "",
|
"beginning": "Должен содержать как минимум",
|
||||||
"highlighted": ""
|
"highlighted": "одну прописную букву"
|
||||||
},
|
},
|
||||||
"match": {
|
"match": {
|
||||||
"beginning": "",
|
"beginning": "Пароли",
|
||||||
"highlighted": ""
|
"highlighted": "должны совпадать"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "",
|
"empty": "Пожалуйста, введите пароль",
|
||||||
"length": "",
|
"length": "Пароль должен быть длиной не менее 8 символов",
|
||||||
"uppercase": "",
|
"uppercase": "Пароль должен содержать минимум 1 прописную букву",
|
||||||
"lowercase": "",
|
"lowercase": "Пароль должен содержать минимум 1 строчную букву",
|
||||||
"number": "",
|
"number": "Пароль должен содержать минимум 1 цифру",
|
||||||
"special": "",
|
"special": "Пароль должен содержать минимум 1 спецсимвол",
|
||||||
"incorrect": ""
|
"incorrect": "Предоставленный вами пароль не соответствует нашим записям"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"passwordConfirm": {
|
"passwordConfirm": {
|
||||||
"label": "",
|
"label": "Подтвердите пароль",
|
||||||
"placeholder": "",
|
"placeholder": "Введите пароль еще раз для подтверждения",
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "",
|
"empty": "Пожалуйста, введите свой пароль еще раз для подтверждения (помогает избежать опечаток)",
|
||||||
"different": ""
|
"different": "Введённые пароли не совпадают, вероятно, один из них напечатан с ошибкой"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"firstName": {
|
"firstName": {
|
||||||
"label": "",
|
"label": "Имя",
|
||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "",
|
"empty": "Пожалуйста, введите свое имя",
|
||||||
"length": "",
|
"length": "Имя должно быть короче 50 символов",
|
||||||
"pattern": ""
|
"pattern": "Имя должно содержать только буквы, пробелы, апострофы или дефисы"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lastName": {
|
"lastName": {
|
||||||
"label": "",
|
"label": "Фамилия",
|
||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"errors": {
|
"errors": {
|
||||||
"empty": "",
|
"empty": "Пожалуйста, введите свою фамилию",
|
||||||
"length": "",
|
"length": "Фамилия должна быть короче 50 символов",
|
||||||
"pattern": ""
|
"pattern": "Фамилия должна содержать только буквы, пробелы, апострофы или дефисы"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"validation": ""
|
"validation": "Ошибка при проверке данных."
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"password": {
|
"password": {
|
||||||
@@ -550,64 +594,66 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"heading": "",
|
"heading": "Войдите, чтобы продолжить",
|
||||||
"subheadings": {
|
"subheadings": {
|
||||||
"stepOne": "",
|
"stepOne": "Введите свою электронную почту",
|
||||||
"stepTwo": ""
|
"stepTwo": "Введите свой пароль"
|
||||||
},
|
},
|
||||||
"links": {
|
"links": {
|
||||||
"forgotPassword": "",
|
"forgotPassword": "Забыли пароль?",
|
||||||
"register": "",
|
"register": "У вас нет учетной записи?",
|
||||||
"forgotPasswordLink": "",
|
"forgotPasswordLink": "",
|
||||||
"registerLink": ""
|
"registerLink": ""
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "",
|
"success": "С возвращением! Вы успешно вошли в систему.",
|
||||||
"incorrectPassword": ""
|
"incorrectPassword": "Неверный пароль"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
"superAdmin": "",
|
"superAdmin": "Создать супер-администратора",
|
||||||
"user": ""
|
"user": "Зарегистрироваться"
|
||||||
},
|
},
|
||||||
"subheadings": {
|
"subheadings": {
|
||||||
"stepOne": "",
|
"stepOne": "Введите свои личные данные",
|
||||||
"stepTwo": "",
|
"stepTwo": "Введите вашу электронную почту",
|
||||||
"stepThree": ""
|
"stepThree": "Создайте свой пароль"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"superAdmin": "",
|
"superAdmin": "Создайте свой аккаунт супер-администратора, чтобы начать",
|
||||||
"user": ""
|
"user": "Зарегистрируйтесь как пользователь и обратитесь к супер-администратору для доступа к вашим мониторам"
|
||||||
},
|
},
|
||||||
"gettingStartedButton": {
|
"gettingStartedButton": {
|
||||||
"superAdmin": "",
|
"superAdmin": "Создать учетную запись супер-администратора",
|
||||||
"user": ""
|
"user": "Зарегистрироваться как обычный пользователь"
|
||||||
},
|
},
|
||||||
"termsAndPolicies": "",
|
"termsAndPolicies": "Создавая учетную запись, вы соглашаетесь с нашими <a1>Условиями предоставления услуг</a1> и <a2>Политикой конфиденциальности</a2>.",
|
||||||
"links": {
|
"links": {
|
||||||
"login": ""
|
"login": "Уже есть учетная запись? <a>Войти</a>"
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": ""
|
"success": "Добро пожаловать! Ваша учетная запись была создана успешно."
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "",
|
"heading": "Забыли пароль?",
|
||||||
"subheadings": {
|
"subheadings": {
|
||||||
"stepOne": "",
|
"stepOne": "Не волнуйтесь, мы вышлем вам инструкции для сброса.",
|
||||||
"stepTwo": "",
|
"stepTwo": "Мы выслали ссылку для сброса пароля на <email/>",
|
||||||
"stepThree": "",
|
"stepThree": "Ваш новый пароль должен отличаться от ваших предыдущих пароей.",
|
||||||
"stepFour": ""
|
"stepFour": "Ваш пароль был успешно сброшен. Нажмите ниже, чтобы волшебным образом войти в систему."
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"openEmail": "",
|
"openEmail": "",
|
||||||
"resetPassword": ""
|
"resetPassword": "Сбросить пароль"
|
||||||
},
|
},
|
||||||
"imageAlts": {
|
"imageAlts": {
|
||||||
"passwordKey": "",
|
"passwordKey": "",
|
||||||
@@ -741,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -847,6 +894,10 @@
|
|||||||
"selectDisabled": "",
|
"selectDisabled": "",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -915,7 +966,12 @@
|
|||||||
"twentyMinutes": "",
|
"twentyMinutes": "",
|
||||||
"oneHour": "",
|
"oneHour": "",
|
||||||
"oneDay": "",
|
"oneDay": "",
|
||||||
"oneWeek": ""
|
"oneWeek": "",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -967,5 +1023,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
+133
-7
@@ -260,7 +260,6 @@
|
|||||||
"notifyEmails": "Ayrıca birden fazla eposta adresine bildirim gönderebilirsiniz (yakında geliyor)",
|
"notifyEmails": "Ayrıca birden fazla eposta adresine bildirim gönderebilirsiniz (yakında geliyor)",
|
||||||
"seperateEmails": "Birden fazla epostayı virgülle ayırabilirsiniz",
|
"seperateEmails": "Birden fazla epostayı virgülle ayırabilirsiniz",
|
||||||
"checkFrequency": "Frekansı denetle",
|
"checkFrequency": "Frekansı denetle",
|
||||||
"chooseGame": "Oyun seç",
|
|
||||||
"matchMethod": "Eşleşme yöntemi",
|
"matchMethod": "Eşleşme yöntemi",
|
||||||
"expectedValue": "Beklenen değer",
|
"expectedValue": "Beklenen değer",
|
||||||
"deleteDialogTitle": "Gerçekten bu monitörü silmek istiyor musunuz?",
|
"deleteDialogTitle": "Gerçekten bu monitörü silmek istiyor musunuz?",
|
||||||
@@ -377,7 +376,52 @@
|
|||||||
"email": "Eposta",
|
"email": "Eposta",
|
||||||
"role": "Rol",
|
"role": "Rol",
|
||||||
"created": "Oluşturulma"
|
"created": "Oluşturulma"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Durduruldu",
|
"paused": "Durduruldu",
|
||||||
@@ -569,7 +613,8 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"incorrect": "Giriş yaptığınız parola sistemdekiyle uyuşmuyor"
|
"incorrect": "Giriş yaptığınız parola sistemdekiyle uyuşmuyor"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -595,7 +640,8 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "Hoşgeldiniz! Hesabınız başarıyla oluşturuldu."
|
"success": "Hoşgeldiniz! Hesabınız başarıyla oluşturuldu."
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "Parolanızı mı kaybettiniz?",
|
"heading": "Parolanızı mı kaybettiniz?",
|
||||||
@@ -741,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "Son tamamlama",
|
"lastFinishedAtHeader": "Son tamamlama",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -847,6 +894,10 @@
|
|||||||
"selectDisabled": "Kapalı",
|
"selectDisabled": "Kapalı",
|
||||||
"selectEnabled": "Etkin",
|
"selectEnabled": "Etkin",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
@@ -915,7 +966,12 @@
|
|||||||
"twentyMinutes": "",
|
"twentyMinutes": "",
|
||||||
"oneHour": "1 saat",
|
"oneHour": "1 saat",
|
||||||
"oneDay": "1 gün",
|
"oneDay": "1 gün",
|
||||||
"oneWeek": "1 hafta"
|
"oneWeek": "1 hafta",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
@@ -967,5 +1023,75 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large.
Load diff
+332
-202
@@ -3,81 +3,81 @@
|
|||||||
"title": "名稱",
|
"title": "名稱",
|
||||||
"distributedStatusHeaderText": "實時、真實設備覆蓋",
|
"distributedStatusHeaderText": "實時、真實設備覆蓋",
|
||||||
"distributedStatusSubHeaderText": "由全球數百萬個設備提供支持,您可以按全球區域、國家或城市查看系統效能",
|
"distributedStatusSubHeaderText": "由全球數百萬個設備提供支持,您可以按全球區域、國家或城市查看系統效能",
|
||||||
"settingsDisabled": "",
|
"settingsDisabled": "已停用",
|
||||||
"settingsSuccessSaved": "",
|
"settingsSuccessSaved": "設定已成功儲存",
|
||||||
"settingsFailedToSave": "",
|
"settingsFailedToSave": "無法儲存設定",
|
||||||
"settingsStatsCleared": "",
|
"settingsStatsCleared": "統計數據已成功清除",
|
||||||
"settingsFailedToClearStats": "",
|
"settingsFailedToClearStats": "無法清除統計數據",
|
||||||
"settingsMonitorsDeleted": "",
|
"settingsMonitorsDeleted": "已成功刪除所有監視器",
|
||||||
"settingsFailedToDeleteMonitors": "",
|
"settingsFailedToDeleteMonitors": "無法刪除所有監視器",
|
||||||
"starPromptTitle": "",
|
"starPromptTitle": "星標Checkmate",
|
||||||
"starPromptDescription": "",
|
"starPromptDescription": "查看最新版本發布及在 GitHub 上幫助社區成長",
|
||||||
"https": "",
|
"https": "HTTPS",
|
||||||
"http": "",
|
"http": "HTTP",
|
||||||
"monitor": "",
|
"monitor": "監控",
|
||||||
"aboutus": "",
|
"aboutus": "關於我們",
|
||||||
"now": "",
|
"now": "現在",
|
||||||
"delete": "",
|
"delete": "刪除",
|
||||||
"configure": "",
|
"configure": "設定",
|
||||||
"responseTime": "",
|
"responseTime": "回應時間",
|
||||||
"ms": "",
|
"ms": "毫秒",
|
||||||
"bar": "",
|
"bar": "條",
|
||||||
"area": "",
|
"area": "區域",
|
||||||
"country": "",
|
"country": "國家",
|
||||||
"city": "",
|
"city": "城市",
|
||||||
"response": "",
|
"response": "回應",
|
||||||
"monitorStatusUp": "",
|
"monitorStatusUp": "",
|
||||||
"monitorStatusDown": "",
|
"monitorStatusDown": "",
|
||||||
"webhookSendSuccess": "",
|
"webhookSendSuccess": "Webhook 通知發送成功",
|
||||||
"webhookSendError": "",
|
"webhookSendError": "",
|
||||||
"webhookUnsupportedPlatform": "",
|
"webhookUnsupportedPlatform": "不支援的平台: {platform}",
|
||||||
"distributedRightCategoryTitle": "",
|
"distributedRightCategoryTitle": "監控",
|
||||||
"distributedStatusServerMonitors": "",
|
"distributedStatusServerMonitors": "伺服器監控",
|
||||||
"distributedStatusServerMonitorsDescription": "",
|
"distributedStatusServerMonitorsDescription": "監控相關伺服器狀態",
|
||||||
"distributedUptimeCreateSelectURL": "",
|
"distributedUptimeCreateSelectURL": "你可以在這裡選擇主機的 URL,同時選擇監視器類型。",
|
||||||
"distributedUptimeCreateChecks": "",
|
"distributedUptimeCreateChecks": "要執行的檢查項目",
|
||||||
"distributedUptimeCreateChecksDescription": "",
|
"distributedUptimeCreateChecksDescription": "你可以在新增網站後,隨時新增或移除檢查項目。",
|
||||||
"distributedUptimeCreateIncidentNotification": "",
|
"distributedUptimeCreateIncidentNotification": "事故通知",
|
||||||
"distributedUptimeCreateIncidentDescription": "",
|
"distributedUptimeCreateIncidentDescription": "事故發生時,向用戶發送通知。",
|
||||||
"distributedUptimeCreateAdvancedSettings": "",
|
"distributedUptimeCreateAdvancedSettings": "進階設定",
|
||||||
"distributedUptimeDetailsNoMonitorHistory": "",
|
"distributedUptimeDetailsNoMonitorHistory": "此監控尚無檢查記錄。",
|
||||||
"distributedUptimeDetailsStatusHeaderUptime": "",
|
"distributedUptimeDetailsStatusHeaderUptime": "正常運行時間:",
|
||||||
"distributedUptimeDetailsStatusHeaderLastUpdate": "",
|
"distributedUptimeDetailsStatusHeaderLastUpdate": "最後更新",
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"enableNotifications": "",
|
"enableNotifications": "",
|
||||||
"testNotification": "",
|
"testNotification": "測試通知",
|
||||||
"addOrEditNotifications": "",
|
"addOrEditNotifications": "新增或編輯通知",
|
||||||
"slack": {
|
"slack": {
|
||||||
"label": "",
|
"label": "Slack",
|
||||||
"description": "",
|
"description": "要啟用 Slack 通知,請建立一個 Slack 應用程式並啟用傳入 Webhook。完成後,請在此提供 Webhook URL 即可。",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "Webhook URL",
|
||||||
"webhookPlaceholder": "",
|
"webhookPlaceholder": "https://hooks.slack.com/services/...",
|
||||||
"webhookRequired": ""
|
"webhookRequired": "Slack webhook URL is required"
|
||||||
},
|
},
|
||||||
"discord": {
|
"discord": {
|
||||||
"label": "",
|
"label": "Discord",
|
||||||
"description": "",
|
"description": "",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "Discord Webhook URL",
|
||||||
"webhookPlaceholder": "",
|
"webhookPlaceholder": "https://discord.com/api/webhooks/...",
|
||||||
"webhookRequired": ""
|
"webhookRequired": ""
|
||||||
},
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"label": "",
|
"label": "Telegram",
|
||||||
"description": "",
|
"description": "要啟用 Telegram 通知,請使用 BotFather 用於創建和管理 Telegram 的官方機器來建立一個 Telegram 機器人。接著,取得 API 金鑰和聊天室 ID,並在此處填寫。",
|
||||||
"tokenLabel": "",
|
"tokenLabel": "你的機器人金鑰",
|
||||||
"tokenPlaceholder": "",
|
"tokenPlaceholder": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
|
||||||
"chatIdLabel": "",
|
"chatIdLabel": "你的聊天 ID",
|
||||||
"chatIdPlaceholder": "",
|
"chatIdPlaceholder": "-1001234567890",
|
||||||
"fieldsRequired": ""
|
"fieldsRequired": ""
|
||||||
},
|
},
|
||||||
"webhook": {
|
"webhook": {
|
||||||
"label": "",
|
"label": "Webhooks",
|
||||||
"description": "",
|
"description": "你可以設定自訂 webhook,在事件發生時接收通知。",
|
||||||
"urlLabel": "",
|
"urlLabel": "Webhook URL",
|
||||||
"urlPlaceholder": "",
|
"urlPlaceholder": "https://your-server.com/webhook",
|
||||||
"urlRequired": ""
|
"urlRequired": ""
|
||||||
},
|
},
|
||||||
"testNotificationDevelop": "",
|
"testNotificationDevelop": "測試通知 2",
|
||||||
"integrationButton": "",
|
"integrationButton": "",
|
||||||
"testSuccess": "",
|
"testSuccess": "",
|
||||||
"testFailed": "",
|
"testFailed": "",
|
||||||
@@ -85,8 +85,12 @@
|
|||||||
"networkError": "",
|
"networkError": "",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"title": "",
|
"title": "",
|
||||||
"checks": [""],
|
"checks": [
|
||||||
"actionButton": ""
|
"提醒團隊有關停機或性能問題",
|
||||||
|
"讓工程師知道事件發生時的情況",
|
||||||
|
"讓管理員了解系統變更情況"
|
||||||
|
],
|
||||||
|
"actionButton": "讓我們建立您的第一個通知頻道!"
|
||||||
},
|
},
|
||||||
"createButton": "",
|
"createButton": "",
|
||||||
"createTitle": "",
|
"createTitle": "",
|
||||||
@@ -111,35 +115,35 @@
|
|||||||
"failed": ""
|
"failed": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testLocale": "",
|
"testLocale": "測試語言環境",
|
||||||
"add": "",
|
"add": "新增",
|
||||||
"monitors": "",
|
"monitors": "",
|
||||||
"distributedUptimeStatusCreateStatusPage": "",
|
"distributedUptimeStatusCreateStatusPage": "",
|
||||||
"distributedUptimeStatusCreateStatusPageAccess": "",
|
"distributedUptimeStatusCreateStatusPageAccess": "",
|
||||||
"distributedUptimeStatusCreateStatusPageReady": "",
|
"distributedUptimeStatusCreateStatusPageReady": "",
|
||||||
"distributedUptimeStatusBasicInfoHeader": "",
|
"distributedUptimeStatusBasicInfoHeader": "基本資料",
|
||||||
"distributedUptimeStatusBasicInfoDescription": "",
|
"distributedUptimeStatusBasicInfoDescription": "",
|
||||||
"distributedUptimeStatusLogoHeader": "",
|
"distributedUptimeStatusLogoHeader": "標誌",
|
||||||
"distributedUptimeStatusLogoDescription": "",
|
"distributedUptimeStatusLogoDescription": "",
|
||||||
"distributedUptimeStatusLogoUploadButton": "",
|
"distributedUptimeStatusLogoUploadButton": "上傳標誌",
|
||||||
"distributedUptimeStatusStandardMonitorsHeader": "",
|
"distributedUptimeStatusStandardMonitorsHeader": "",
|
||||||
"distributedUptimeStatusStandardMonitorsDescription": "",
|
"distributedUptimeStatusStandardMonitorsDescription": "",
|
||||||
"distributedUptimeStatusCreateYour": "",
|
"distributedUptimeStatusCreateYour": "",
|
||||||
"distributedUptimeStatusEditYour": "",
|
"distributedUptimeStatusEditYour": "",
|
||||||
"distributedUptimeStatusPublishedLabel": "",
|
"distributedUptimeStatusPublishedLabel": "",
|
||||||
"distributedUptimeStatusCompanyNameLabel": "",
|
"distributedUptimeStatusCompanyNameLabel": "公司名稱",
|
||||||
"distributedUptimeStatusPageAddressLabel": "",
|
"distributedUptimeStatusPageAddressLabel": "",
|
||||||
"distributedUptimeStatus30Days": "",
|
"distributedUptimeStatus30Days": "30日",
|
||||||
"distributedUptimeStatus60Days": "",
|
"distributedUptimeStatus60Days": "60日",
|
||||||
"distributedUptimeStatus90Days": "",
|
"distributedUptimeStatus90Days": "90日",
|
||||||
"distributedUptimeStatusPageNotSetUp": "",
|
"distributedUptimeStatusPageNotSetUp": "",
|
||||||
"distributedUptimeStatusContactAdmin": "",
|
"distributedUptimeStatusContactAdmin": "",
|
||||||
"distributedUptimeStatusPageNotPublic": "",
|
"distributedUptimeStatusPageNotPublic": "",
|
||||||
"distributedUptimeStatusPageDeleteDialog": "",
|
"distributedUptimeStatusPageDeleteDialog": "",
|
||||||
"distributedUptimeStatusPageDeleteConfirm": "",
|
"distributedUptimeStatusPageDeleteConfirm": "",
|
||||||
"distributedUptimeStatusPageDeleteDescription": "",
|
"distributedUptimeStatusPageDeleteDescription": "",
|
||||||
"distributedUptimeStatusDevices": "",
|
"distributedUptimeStatusDevices": "設備",
|
||||||
"distributedUptimeStatusUpt": "",
|
"distributedUptimeStatusUpt": "UPT",
|
||||||
"distributedUptimeStatusUptBurned": "",
|
"distributedUptimeStatusUptBurned": "",
|
||||||
"distributedUptimeStatusUptLogo": "",
|
"distributedUptimeStatusUptLogo": "",
|
||||||
"incidentsTableNoIncidents": "",
|
"incidentsTableNoIncidents": "",
|
||||||
@@ -169,53 +173,53 @@
|
|||||||
"infrastructureServerUrlLabel": "",
|
"infrastructureServerUrlLabel": "",
|
||||||
"infrastructureDisplayNameLabel": "",
|
"infrastructureDisplayNameLabel": "",
|
||||||
"infrastructureAuthorizationSecretLabel": "",
|
"infrastructureAuthorizationSecretLabel": "",
|
||||||
"gb": "",
|
"gb": "GB",
|
||||||
"mb": "",
|
"mb": "MB",
|
||||||
"mem": "",
|
"mem": "Mem",
|
||||||
"memoryUsage": "",
|
"memoryUsage": "",
|
||||||
"cpu": "",
|
"cpu": "CPU",
|
||||||
"cpuUsage": "",
|
"cpuUsage": "CPU 使用量",
|
||||||
"cpuTemperature": "",
|
"cpuTemperature": "CPU 溫度",
|
||||||
"diskUsage": "",
|
"diskUsage": "",
|
||||||
"used": "",
|
"used": "",
|
||||||
"total": "",
|
"total": "",
|
||||||
"cores": "",
|
"cores": "核",
|
||||||
"frequency": "",
|
"frequency": "",
|
||||||
"status": "",
|
"status": "",
|
||||||
"cpuPhysical": "",
|
"cpuPhysical": "CPU (實體核心)",
|
||||||
"cpuLogical": "",
|
"cpuLogical": "CPU (邏輯核心)",
|
||||||
"cpuFrequency": "",
|
"cpuFrequency": "CPU 頻率",
|
||||||
"avgCpuTemperature": "",
|
"avgCpuTemperature": "平均 CPU 溫度",
|
||||||
"memory": "",
|
"memory": "",
|
||||||
"disk": "",
|
"disk": "",
|
||||||
"uptime": "",
|
"uptime": "",
|
||||||
"os": "",
|
"os": "OS",
|
||||||
"host": "",
|
"host": "",
|
||||||
"actions": "",
|
"actions": "行動",
|
||||||
"integrations": "",
|
"integrations": "",
|
||||||
"integrationsPrism": "",
|
"integrationsPrism": "",
|
||||||
"integrationsSlack": "",
|
"integrationsSlack": "Slack",
|
||||||
"integrationsSlackInfo": "",
|
"integrationsSlackInfo": "",
|
||||||
"integrationsDiscord": "",
|
"integrationsDiscord": "",
|
||||||
"integrationsDiscordInfo": "",
|
"integrationsDiscordInfo": "",
|
||||||
"integrationsZapier": "",
|
"integrationsZapier": "",
|
||||||
"integrationsZapierInfo": "",
|
"integrationsZapierInfo": "",
|
||||||
"commonSave": "",
|
"commonSave": "儲存",
|
||||||
"createYour": "",
|
"createYour": "",
|
||||||
"createMonitor": "",
|
"createMonitor": "",
|
||||||
"pause": "",
|
"pause": "",
|
||||||
"resume": "",
|
"resume": "",
|
||||||
"editing": "",
|
"editing": "",
|
||||||
"url": "",
|
"url": "UR:",
|
||||||
"access": "",
|
"access": "存取",
|
||||||
"timezone": "",
|
"timezone": "時區",
|
||||||
"features": "",
|
"features": "",
|
||||||
"administrator": "",
|
"administrator": "系統管理員?",
|
||||||
"loginHere": "",
|
"loginHere": "",
|
||||||
"displayName": "",
|
"displayName": "",
|
||||||
"urlMonitor": "",
|
"urlMonitor": "",
|
||||||
"portToMonitor": "",
|
"portToMonitor": "",
|
||||||
"websiteMonitoring": "",
|
"websiteMonitoring": "網站監控",
|
||||||
"websiteMonitoringDescription": "",
|
"websiteMonitoringDescription": "",
|
||||||
"pingMonitoring": "",
|
"pingMonitoring": "",
|
||||||
"pingMonitoringDescription": "",
|
"pingMonitoringDescription": "",
|
||||||
@@ -232,15 +236,15 @@
|
|||||||
"maintenanceRepeat": "",
|
"maintenanceRepeat": "",
|
||||||
"maintenance": "",
|
"maintenance": "",
|
||||||
"duration": "",
|
"duration": "",
|
||||||
"addMonitors": "",
|
"addMonitors": "新增監視器",
|
||||||
"window": "",
|
"window": "",
|
||||||
"cancel": "",
|
"cancel": "取消",
|
||||||
"message": "",
|
"message": "",
|
||||||
"low": "",
|
"low": "低",
|
||||||
"high": "",
|
"high": "高",
|
||||||
"statusCode": "",
|
"statusCode": "",
|
||||||
"date&Time": "",
|
"date&Time": "日期與時間",
|
||||||
"type": "",
|
"type": "類型",
|
||||||
"statusPageName": "",
|
"statusPageName": "",
|
||||||
"publicURL": "",
|
"publicURL": "",
|
||||||
"repeat": "",
|
"repeat": "",
|
||||||
@@ -259,21 +263,20 @@
|
|||||||
"notifySMS": "",
|
"notifySMS": "",
|
||||||
"notifyEmails": "",
|
"notifyEmails": "",
|
||||||
"seperateEmails": "",
|
"seperateEmails": "",
|
||||||
"checkFrequency": "",
|
"checkFrequency": "檢查頻率",
|
||||||
"chooseGame": "",
|
|
||||||
"matchMethod": "",
|
"matchMethod": "",
|
||||||
"expectedValue": "",
|
"expectedValue": "",
|
||||||
"deleteDialogTitle": "",
|
"deleteDialogTitle": "您確定要刪除此監視器嗎?",
|
||||||
"deleteDialogDescription": "",
|
"deleteDialogDescription": "一旦刪除,該監視器無法恢復。",
|
||||||
"pageSpeedMonitor": "",
|
"pageSpeedMonitor": "",
|
||||||
"shown": "",
|
"shown": "",
|
||||||
"ago": "",
|
"ago": "",
|
||||||
"companyName": "",
|
"companyName": "公司名稱",
|
||||||
"pageSpeedDetailsPerformanceReport": "",
|
"pageSpeedDetailsPerformanceReport": "",
|
||||||
"pageSpeedDetailsPerformanceReportCalculator": "",
|
"pageSpeedDetailsPerformanceReportCalculator": "",
|
||||||
"checkingEvery": "",
|
"checkingEvery": "",
|
||||||
"statusPageCreateSettings": "",
|
"statusPageCreateSettings": "",
|
||||||
"basicInformation": "",
|
"basicInformation": "基本資料",
|
||||||
"statusPageCreateBasicInfoDescription": "",
|
"statusPageCreateBasicInfoDescription": "",
|
||||||
"statusPageCreateSelectTimeZoneDescription": "",
|
"statusPageCreateSelectTimeZoneDescription": "",
|
||||||
"statusPageCreateAppearanceDescription": "",
|
"statusPageCreateAppearanceDescription": "",
|
||||||
@@ -307,24 +310,24 @@
|
|||||||
"pageSpeedWarning": "",
|
"pageSpeedWarning": "",
|
||||||
"pageSpeedLearnMoreLink": "",
|
"pageSpeedLearnMoreLink": "",
|
||||||
"pageSpeedAddApiKey": "",
|
"pageSpeedAddApiKey": "",
|
||||||
"update": "",
|
"update": "更新",
|
||||||
"invalidFileFormat": "",
|
"invalidFileFormat": "",
|
||||||
"invalidFileSize": "",
|
"invalidFileSize": "",
|
||||||
"ClickUpload": "",
|
"ClickUpload": "點擊上傳",
|
||||||
"DragandDrop": "",
|
"DragandDrop": "",
|
||||||
"MaxSize": "",
|
"MaxSize": "",
|
||||||
"SupportedFormats": "",
|
"SupportedFormats": "",
|
||||||
"FirstName": "",
|
"FirstName": "",
|
||||||
"LastName": "",
|
"LastName": "",
|
||||||
"EmailDescriptionText": "",
|
"EmailDescriptionText": "",
|
||||||
"YourPhoto": "",
|
"YourPhoto": "頭像",
|
||||||
"PhotoDescriptionText": "",
|
"PhotoDescriptionText": "",
|
||||||
"save": "",
|
"save": "",
|
||||||
"DeleteDescriptionText": "",
|
"DeleteDescriptionText": "這將刪除帳號以及所有相關的伺服器資料,此操作不可逆轉。",
|
||||||
"DeleteAccountWarning": "",
|
"DeleteAccountWarning": "刪除您的帳號表示您將無法再次登入,且所有資料都會被移除。此操作不可逆轉。",
|
||||||
"DeleteWarningTitle": "",
|
"DeleteWarningTitle": "",
|
||||||
"bulkImport": {
|
"bulkImport": {
|
||||||
"title": "",
|
"title": "批量匯入",
|
||||||
"selectFileTips": "",
|
"selectFileTips": "",
|
||||||
"selectFileDescription": "",
|
"selectFileDescription": "",
|
||||||
"selectFile": "",
|
"selectFile": "",
|
||||||
@@ -336,8 +339,8 @@
|
|||||||
"invalidFileType": "",
|
"invalidFileType": "",
|
||||||
"uploadFailed": ""
|
"uploadFailed": ""
|
||||||
},
|
},
|
||||||
"DeleteAccountTitle": "",
|
"DeleteAccountTitle": "刪除帳戶",
|
||||||
"DeleteAccountButton": "",
|
"DeleteAccountButton": "刪除帳戶",
|
||||||
"publicLink": "",
|
"publicLink": "",
|
||||||
"maskedPageSpeedKeyPlaceholder": "",
|
"maskedPageSpeedKeyPlaceholder": "",
|
||||||
"reset": "",
|
"reset": "",
|
||||||
@@ -352,14 +355,14 @@
|
|||||||
},
|
},
|
||||||
"roles": {
|
"roles": {
|
||||||
"superAdmin": "",
|
"superAdmin": "",
|
||||||
"admin": "",
|
"admin": "管理員",
|
||||||
"teamMember": "",
|
"teamMember": "",
|
||||||
"demoUser": ""
|
"demoUser": "示範用戶"
|
||||||
},
|
},
|
||||||
"teamPanel": {
|
"teamPanel": {
|
||||||
"teamMembers": "",
|
"teamMembers": "",
|
||||||
"filter": {
|
"filter": {
|
||||||
"all": "",
|
"all": "全部",
|
||||||
"member": ""
|
"member": ""
|
||||||
},
|
},
|
||||||
"inviteTeamMember": "",
|
"inviteTeamMember": "",
|
||||||
@@ -368,7 +371,7 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"selectRole": "",
|
"selectRole": "",
|
||||||
"inviteLink": "",
|
"inviteLink": "",
|
||||||
"cancel": "",
|
"cancel": "取消",
|
||||||
"noMembers": "",
|
"noMembers": "",
|
||||||
"getToken": "",
|
"getToken": "",
|
||||||
"emailToken": "",
|
"emailToken": "",
|
||||||
@@ -377,12 +380,57 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"role": "",
|
"role": "",
|
||||||
"created": ""
|
"created": ""
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "",
|
||||||
|
"title": "",
|
||||||
|
"description": "",
|
||||||
|
"addButton": ""
|
||||||
|
},
|
||||||
|
"register": "",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "",
|
||||||
|
"dbUserExists": "",
|
||||||
|
"unknownError": ""
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "",
|
||||||
|
"invalid": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": ""
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "",
|
"paused": "",
|
||||||
"resumed": "",
|
"resumed": "",
|
||||||
"active": ""
|
"active": "啟用中"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"uptime": "",
|
"uptime": "",
|
||||||
@@ -396,7 +444,7 @@
|
|||||||
"support": "",
|
"support": "",
|
||||||
"discussions": "",
|
"discussions": "",
|
||||||
"docs": "",
|
"docs": "",
|
||||||
"changelog": "",
|
"changelog": "版本變更記錄",
|
||||||
"profile": "",
|
"profile": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"team": "",
|
"team": "",
|
||||||
@@ -408,17 +456,17 @@
|
|||||||
"state": "",
|
"state": "",
|
||||||
"statusBreadCrumbsStatusPages": "",
|
"statusBreadCrumbsStatusPages": "",
|
||||||
"statusBreadCrumbsDetails": "",
|
"statusBreadCrumbsDetails": "",
|
||||||
"commonSaving": "",
|
"commonSaving": "儲存中...",
|
||||||
"navControls": "",
|
"navControls": "",
|
||||||
"incidentsPageTitle": "",
|
"incidentsPageTitle": "",
|
||||||
"passwordPanel": {
|
"passwordPanel": {
|
||||||
"passwordChangedSuccess": "",
|
"passwordChangedSuccess": "",
|
||||||
"passwordInputIncorrect": "",
|
"passwordInputIncorrect": "",
|
||||||
"currentPassword": "",
|
"currentPassword": "當前密碼",
|
||||||
"enterCurrentPassword": "",
|
"enterCurrentPassword": "",
|
||||||
"newPassword": "",
|
"newPassword": "",
|
||||||
"enterNewPassword": "",
|
"enterNewPassword": "",
|
||||||
"confirmNewPassword": "",
|
"confirmNewPassword": "確認新密碼",
|
||||||
"passwordRequirements": "",
|
"passwordRequirements": "",
|
||||||
"saving": ""
|
"saving": ""
|
||||||
},
|
},
|
||||||
@@ -442,22 +490,22 @@
|
|||||||
"game": ""
|
"game": ""
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"appName": "",
|
"appName": "Checkmate",
|
||||||
"monitoringAgentName": "",
|
"monitoringAgentName": "",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"toggleTheme": ""
|
"toggleTheme": ""
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"networkError": "",
|
"networkError": "",
|
||||||
"checkConnection": "",
|
"checkConnection": "請檢查您的連線",
|
||||||
"unknownError": ""
|
"unknownError": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"common": {
|
"common": {
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"continue": "",
|
"continue": "繼續",
|
||||||
"back": ""
|
"back": "返回"
|
||||||
},
|
},
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"email": {
|
"email": {
|
||||||
@@ -472,23 +520,23 @@
|
|||||||
"label": "",
|
"label": "",
|
||||||
"rules": {
|
"rules": {
|
||||||
"length": {
|
"length": {
|
||||||
"beginning": "",
|
"beginning": "必須至少",
|
||||||
"highlighted": ""
|
"highlighted": ""
|
||||||
},
|
},
|
||||||
"special": {
|
"special": {
|
||||||
"beginning": "",
|
"beginning": "必須至少包含",
|
||||||
"highlighted": ""
|
"highlighted": ""
|
||||||
},
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"beginning": "",
|
"beginning": "必須至少包含",
|
||||||
"highlighted": ""
|
"highlighted": ""
|
||||||
},
|
},
|
||||||
"uppercase": {
|
"uppercase": {
|
||||||
"beginning": "",
|
"beginning": "必須至少包含",
|
||||||
"highlighted": ""
|
"highlighted": ""
|
||||||
},
|
},
|
||||||
"lowercase": {
|
"lowercase": {
|
||||||
"beginning": "",
|
"beginning": "必須至少包含",
|
||||||
"highlighted": ""
|
"highlighted": ""
|
||||||
},
|
},
|
||||||
"match": {
|
"match": {
|
||||||
@@ -562,14 +610,15 @@
|
|||||||
"registerLink": ""
|
"registerLink": ""
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": "",
|
"success": "歡迎回來!您已成功登入。",
|
||||||
"incorrectPassword": ""
|
"incorrectPassword": ""
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"password": {
|
"password": {
|
||||||
"incorrect": ""
|
"incorrect": ""
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"registration": {
|
"registration": {
|
||||||
"heading": {
|
"heading": {
|
||||||
@@ -594,8 +643,9 @@
|
|||||||
"login": ""
|
"login": ""
|
||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"success": ""
|
"success": "歡迎!您的帳號已成功建立。"
|
||||||
}
|
},
|
||||||
|
"welcome": ""
|
||||||
},
|
},
|
||||||
"forgotPassword": {
|
"forgotPassword": {
|
||||||
"heading": "",
|
"heading": "",
|
||||||
@@ -623,7 +673,7 @@
|
|||||||
"sent": "",
|
"sent": "",
|
||||||
"emailNotFound": "",
|
"emailNotFound": "",
|
||||||
"redirect": "",
|
"redirect": "",
|
||||||
"success": "",
|
"success": "您的密碼已成功重設。",
|
||||||
"error": ""
|
"error": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -634,10 +684,10 @@
|
|||||||
"reconnected": "",
|
"reconnected": "",
|
||||||
"stillUnreachable": ""
|
"stillUnreachable": ""
|
||||||
},
|
},
|
||||||
"alertBox": "",
|
"alertBox": "伺服器連線錯誤",
|
||||||
"description": "",
|
"description": "我們無法連接到伺服器。請檢查您的網路連線,若問題持續,請確認您的部署設定是否正確。",
|
||||||
"retryButton": {
|
"retryButton": {
|
||||||
"default": "",
|
"default": "重新嘗試連線",
|
||||||
"processing": ""
|
"processing": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -645,42 +695,42 @@
|
|||||||
"createNotifications": {
|
"createNotifications": {
|
||||||
"title": "",
|
"title": "",
|
||||||
"nameSettings": {
|
"nameSettings": {
|
||||||
"title": "",
|
"title": "姓名",
|
||||||
"description": "",
|
"description": "為您的整合設定描述名稱。",
|
||||||
"nameLabel": "",
|
"nameLabel": "",
|
||||||
"namePlaceholder": ""
|
"namePlaceholder": ""
|
||||||
},
|
},
|
||||||
"typeSettings": {
|
"typeSettings": {
|
||||||
"title": "",
|
"title": "類型",
|
||||||
"description": "",
|
"description": "請選擇您想要建立的通知頻道類型。",
|
||||||
"typeLabel": ""
|
"typeLabel": "類型"
|
||||||
},
|
},
|
||||||
"emailSettings": {
|
"emailSettings": {
|
||||||
"title": "",
|
"title": "電郵",
|
||||||
"description": "",
|
"description": "目的地電子郵件位址。",
|
||||||
"emailLabel": "",
|
"emailLabel": "",
|
||||||
"emailPlaceholder": ""
|
"emailPlaceholder": ""
|
||||||
},
|
},
|
||||||
"slackSettings": {
|
"slackSettings": {
|
||||||
"title": "",
|
"title": "Slack",
|
||||||
"description": "",
|
"description": "在此配置您的 Slack webhook",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": ""
|
||||||
},
|
},
|
||||||
"pagerdutySettings": {
|
"pagerdutySettings": {
|
||||||
"title": "",
|
"title": "PagerDuty",
|
||||||
"description": "",
|
"description": "在此配置您的 PagerDuty 整合",
|
||||||
"integrationKeyLabel": "",
|
"integrationKeyLabel": "",
|
||||||
"integrationKeyPlaceholder": ""
|
"integrationKeyPlaceholder": ""
|
||||||
},
|
},
|
||||||
"discordSettings": {
|
"discordSettings": {
|
||||||
"title": "",
|
"title": "Discord",
|
||||||
"description": "",
|
"description": "在此配置您的 Discord webhook",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": ""
|
||||||
},
|
},
|
||||||
"webhookSettings": {
|
"webhookSettings": {
|
||||||
"title": "",
|
"title": "Webhook",
|
||||||
"description": "",
|
"description": "",
|
||||||
"webhookLabel": "",
|
"webhookLabel": "",
|
||||||
"webhookPlaceholder": ""
|
"webhookPlaceholder": ""
|
||||||
@@ -690,8 +740,8 @@
|
|||||||
"dialogDeleteConfirm": ""
|
"dialogDeleteConfirm": ""
|
||||||
},
|
},
|
||||||
"notificationConfig": {
|
"notificationConfig": {
|
||||||
"title": "",
|
"title": "通知",
|
||||||
"description": ""
|
"description": "請選擇您想要使用的通知頻道"
|
||||||
},
|
},
|
||||||
"monitorStatus": {
|
"monitorStatus": {
|
||||||
"checkingEvery": "",
|
"checkingEvery": "",
|
||||||
@@ -700,7 +750,7 @@
|
|||||||
"down": "",
|
"down": "",
|
||||||
"paused": ""
|
"paused": ""
|
||||||
},
|
},
|
||||||
"advancedMatching": "",
|
"advancedMatching": "進階匹配",
|
||||||
"sendTestNotifications": "",
|
"sendTestNotifications": "",
|
||||||
"selectAll": "",
|
"selectAll": "",
|
||||||
"showAdminLoginLink": "",
|
"showAdminLoginLink": "",
|
||||||
@@ -718,11 +768,11 @@
|
|||||||
"logLevelSelect": {
|
"logLevelSelect": {
|
||||||
"title": "",
|
"title": "",
|
||||||
"values": {
|
"values": {
|
||||||
"all": "",
|
"all": "全部",
|
||||||
"info": "",
|
"info": "",
|
||||||
"warn": "",
|
"warn": "",
|
||||||
"error": "",
|
"error": "",
|
||||||
"debug": ""
|
"debug": "除錯"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -734,14 +784,15 @@
|
|||||||
"title": "",
|
"title": "",
|
||||||
"idHeader": "",
|
"idHeader": "",
|
||||||
"urlHeader": "",
|
"urlHeader": "",
|
||||||
"typeHeader": "",
|
"typeHeader": "類型",
|
||||||
"activeHeader": "",
|
"activeHeader": "啟用中",
|
||||||
"lockedAtHeader": "",
|
"lockedAtHeader": "",
|
||||||
"runCountHeader": "",
|
"runCountHeader": "",
|
||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
@@ -774,7 +825,7 @@
|
|||||||
"aboutSettings": {
|
"aboutSettings": {
|
||||||
"labelDevelopedBy": "",
|
"labelDevelopedBy": "",
|
||||||
"labelVersion": "",
|
"labelVersion": "",
|
||||||
"title": ""
|
"title": "關於"
|
||||||
},
|
},
|
||||||
"demoMonitorsSettings": {
|
"demoMonitorsSettings": {
|
||||||
"buttonAddMonitors": "",
|
"buttonAddMonitors": "",
|
||||||
@@ -782,7 +833,7 @@
|
|||||||
"title": ""
|
"title": ""
|
||||||
},
|
},
|
||||||
"emailSettings": {
|
"emailSettings": {
|
||||||
"buttonSendTestEmail": "",
|
"buttonSendTestEmail": "發送測試電子郵件",
|
||||||
"description": "",
|
"description": "",
|
||||||
"descriptionTransport": "",
|
"descriptionTransport": "",
|
||||||
"labelAddress": "",
|
"labelAddress": "",
|
||||||
@@ -800,25 +851,25 @@
|
|||||||
"labelUser": "",
|
"labelUser": "",
|
||||||
"linkTransport": "",
|
"linkTransport": "",
|
||||||
"placeholderUser": "",
|
"placeholderUser": "",
|
||||||
"title": "",
|
"title": "電郵",
|
||||||
"toastEmailRequiredFieldsError": ""
|
"toastEmailRequiredFieldsError": ""
|
||||||
},
|
},
|
||||||
"pageSpeedSettings": {
|
"pageSpeedSettings": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"labelApiKeySet": "",
|
"labelApiKeySet": "",
|
||||||
"labelApiKey": "",
|
"labelApiKey": "",
|
||||||
"title": ""
|
"title": "Google PageSpeed API 金鑰"
|
||||||
},
|
},
|
||||||
"saveButtonLabel": "",
|
"saveButtonLabel": "",
|
||||||
"statsSettings": {
|
"statsSettings": {
|
||||||
"clearAllStatsButton": "",
|
"clearAllStatsButton": "清除所有統計數據",
|
||||||
"clearAllStatsDescription": "",
|
"clearAllStatsDescription": "清除所有統計數據,此操作不可逆轉。",
|
||||||
"clearAllStatsDialogConfirm": "",
|
"clearAllStatsDialogConfirm": "是,請清除所有統計數據",
|
||||||
"clearAllStatsDialogDescription": "",
|
"clearAllStatsDialogDescription": "一旦刪除,監控歷史和統計數據將無法復原。",
|
||||||
"clearAllStatsDialogTitle": "",
|
"clearAllStatsDialogTitle": "您是否要清除所有統計數據?",
|
||||||
"description": "",
|
"description": "",
|
||||||
"labelTTL": "",
|
"labelTTL": "",
|
||||||
"labelTTLOptional": "",
|
"labelTTLOptional": "0 表示無限",
|
||||||
"title": ""
|
"title": ""
|
||||||
},
|
},
|
||||||
"systemResetSettings": {
|
"systemResetSettings": {
|
||||||
@@ -827,19 +878,19 @@
|
|||||||
"dialogConfirm": "",
|
"dialogConfirm": "",
|
||||||
"dialogDescription": "",
|
"dialogDescription": "",
|
||||||
"dialogTitle": "",
|
"dialogTitle": "",
|
||||||
"title": ""
|
"title": "系統重設"
|
||||||
},
|
},
|
||||||
"timezoneSettings": {
|
"timezoneSettings": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"label": "",
|
"label": "",
|
||||||
"title": ""
|
"title": "顯示時區"
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": "設定",
|
||||||
"uiSettings": {
|
"uiSettings": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"labelLanguage": "",
|
"labelLanguage": "",
|
||||||
"labelTheme": "",
|
"labelTheme": "",
|
||||||
"title": ""
|
"title": "外觀"
|
||||||
},
|
},
|
||||||
"urlSettings": {
|
"urlSettings": {
|
||||||
"description": "",
|
"description": "",
|
||||||
@@ -847,15 +898,19 @@
|
|||||||
"selectDisabled": "",
|
"selectDisabled": "",
|
||||||
"selectEnabled": "",
|
"selectEnabled": "",
|
||||||
"title": ""
|
"title": ""
|
||||||
|
},
|
||||||
|
"globalThresholds": {
|
||||||
|
"title": "",
|
||||||
|
"description": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusPageCreate": {
|
"statusPageCreate": {
|
||||||
"buttonSave": ""
|
"buttonSave": "儲存"
|
||||||
},
|
},
|
||||||
"incidentsOptionsHeaderFilterResolved": "",
|
"incidentsOptionsHeaderFilterResolved": "",
|
||||||
"settingsSave": "",
|
"settingsSave": "",
|
||||||
"statusPageCreateAppearanceTitle": "",
|
"statusPageCreateAppearanceTitle": "",
|
||||||
"confirmPassword": "",
|
"confirmPassword": "確認密碼",
|
||||||
"monitorHooks": {
|
"monitorHooks": {
|
||||||
"failureAddDemoMonitors": "",
|
"failureAddDemoMonitors": "",
|
||||||
"successAddDemoMonitors": ""
|
"successAddDemoMonitors": ""
|
||||||
@@ -866,15 +921,15 @@
|
|||||||
"incidentsOptionsHeaderTotalIncidents": "",
|
"incidentsOptionsHeaderTotalIncidents": "",
|
||||||
"statusPage": {
|
"statusPage": {
|
||||||
"deleteSuccess": "",
|
"deleteSuccess": "",
|
||||||
"deleteFailed": "",
|
"deleteFailed": "刪除狀態頁面失敗",
|
||||||
"createSuccess": "",
|
"createSuccess": "",
|
||||||
"updateSuccess": "",
|
"updateSuccess": "",
|
||||||
"generalSettings": "",
|
"generalSettings": "",
|
||||||
"contents": "",
|
"contents": "內容",
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [""],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": "讓我們建立您的第一個狀態頁面!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"testNotificationsDisabled": "",
|
"testNotificationsDisabled": "",
|
||||||
@@ -909,63 +964,138 @@
|
|||||||
},
|
},
|
||||||
"pageSpeedLighthouseAPI": "",
|
"pageSpeedLighthouseAPI": "",
|
||||||
"time": {
|
"time": {
|
||||||
"threeMinutes": "",
|
"threeMinutes": "3分鐘",
|
||||||
"fiveMinutes": "",
|
"fiveMinutes": "5分鐘",
|
||||||
"tenMinutes": "",
|
"tenMinutes": "10分鐘",
|
||||||
"twentyMinutes": "",
|
"twentyMinutes": "20分鐘",
|
||||||
"oneHour": "",
|
"oneHour": "1小時",
|
||||||
"oneDay": "",
|
"oneDay": "1日",
|
||||||
"oneWeek": ""
|
"oneWeek": "1星期",
|
||||||
|
"fourMinutes": "",
|
||||||
|
"oneMinute": "",
|
||||||
|
"twoMinutes": "",
|
||||||
|
"fifteenSeconds": "",
|
||||||
|
"thirtySeconds": ""
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"noOptionsFound": ""
|
"noOptionsFound": ""
|
||||||
},
|
},
|
||||||
"infrastructureMonitor": {
|
"infrastructureMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": ["追蹤伺服器的效能", "識別瓶頸並優化資源使用", "透過即時監控確保可靠性"],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": "讓我們建立您的第一個基礎設施監視器!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"maintenanceWindow": {
|
"maintenanceWindow": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": ["標記您的維護期間", "消除任何誤解", "在維護時段停止發送警報"],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": "讓我們建立您的第一個維護時段!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageSpeed": {
|
"pageSpeed": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [""],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": "讓我們建立您的第一個 PageSpeed 監視器!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"uptimeMonitor": {
|
"uptimeMonitor": {
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"checks": [""],
|
"checks": [""],
|
||||||
"title": "",
|
"title": "",
|
||||||
"actionButton": ""
|
"actionButton": "讓我們建立您的第一個正常運行時間監視器!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editUserPage": {
|
"editUserPage": {
|
||||||
"form": {
|
"form": {
|
||||||
"email": "",
|
"email": "電郵",
|
||||||
"firstName": "",
|
"firstName": "名",
|
||||||
"lastName": "",
|
"lastName": "姓",
|
||||||
"role": "",
|
"role": "角色",
|
||||||
"save": ""
|
"save": "儲存"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"actionHeader": "",
|
"actionHeader": "行動",
|
||||||
"roleHeader": ""
|
"roleHeader": "角色"
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": "編輯用戶",
|
||||||
"toast": {
|
"toast": {
|
||||||
"successUserUpdate": "",
|
"successUserUpdate": "",
|
||||||
"validationErrors": ""
|
"validationErrors": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"incidentsPageActionResolveMonitor": "",
|
"incidentsPageActionResolveMonitor": "解決監視器事故",
|
||||||
"incidentsPageActionResolveAll": ""
|
"incidentsPageActionResolveAll": "解決所有事故",
|
||||||
|
"matchMethodOptions": {
|
||||||
|
"equal": "",
|
||||||
|
"equalPlaceholder": "",
|
||||||
|
"include": "",
|
||||||
|
"includePlaceholder": "",
|
||||||
|
"regex": "",
|
||||||
|
"regexPlaceholder": "",
|
||||||
|
"text": ""
|
||||||
|
},
|
||||||
|
"monitorType": {
|
||||||
|
"docker": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"game": {
|
||||||
|
"label": "",
|
||||||
|
"namePlaceholder": "",
|
||||||
|
"placeholder": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uptimeAdvancedMatching": {
|
||||||
|
"jsonPath": ""
|
||||||
|
},
|
||||||
|
"bytesPerSecond": "",
|
||||||
|
"bytesReceived": "",
|
||||||
|
"bytesSent": "",
|
||||||
|
"chooseGame": "",
|
||||||
|
"createMonitorPage": {
|
||||||
|
"incidentConfigDescription": "",
|
||||||
|
"incidentConfigStatusWindowLabel": "",
|
||||||
|
"incidentConfigStatusWindowThresholdLabel": "",
|
||||||
|
"incidentConfigTitle": ""
|
||||||
|
},
|
||||||
|
"dataRate": "",
|
||||||
|
"dataReceived": "",
|
||||||
|
"dataSent": "",
|
||||||
|
"details": "",
|
||||||
|
"drops": "",
|
||||||
|
"errors": "",
|
||||||
|
"errorsIn": "",
|
||||||
|
"errorsOut": "",
|
||||||
|
"gameServerMonitoring": "",
|
||||||
|
"gameServerMonitoringDescription": "",
|
||||||
|
"network": "",
|
||||||
|
"networkDrops": "",
|
||||||
|
"networkErrors": "",
|
||||||
|
"networkInterface": "",
|
||||||
|
"noNetworkStatsAvailable": "",
|
||||||
|
"packetsPerSecond": "",
|
||||||
|
"packetsReceived": "",
|
||||||
|
"packetsReceivedRate": "",
|
||||||
|
"packetsSent": "",
|
||||||
|
"rate": "",
|
||||||
|
"selectInterface": ""
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ import { execSync } from "child_process";
|
|||||||
|
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
const env = loadEnv(mode, process.cwd(), "");
|
const env = loadEnv(mode, process.cwd(), "");
|
||||||
let version = "3.0-beta";
|
let version = "3.2.0";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
base: "/",
|
base: "/",
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
FROM node:20-alpine AS build
|
FROM node:20-slim AS build
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
python3 \
|
|
||||||
make g++ \
|
|
||||||
gcc \
|
|
||||||
libc-dev \
|
|
||||||
linux-headers \
|
|
||||||
libusb-dev \
|
|
||||||
eudev-dev
|
|
||||||
|
|
||||||
COPY ./client/package*.json ./
|
COPY ./client/package*.json ./
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
FROM node:20-alpine AS build
|
FROM node:20-slim AS build
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
python3 \
|
|
||||||
make g++ \
|
|
||||||
gcc \
|
|
||||||
libc-dev \
|
|
||||||
linux-headers \
|
|
||||||
libusb-dev \
|
|
||||||
eudev-dev
|
|
||||||
|
|
||||||
|
|
||||||
COPY ./client/package*.json ./
|
COPY ./client/package*.json ./
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ services:
|
|||||||
server:
|
server:
|
||||||
image: ghcr.io/bluewave-labs/checkmate-backend-mono-multiarch:latest
|
image: ghcr.io/bluewave-labs/checkmate-backend-mono-multiarch:latest
|
||||||
restart: always
|
restart: always
|
||||||
|
pull_policy: always
|
||||||
ports:
|
ports:
|
||||||
- "52345:52345"
|
- "52345:52345"
|
||||||
environment:
|
environment:
|
||||||
@@ -15,9 +16,8 @@ services:
|
|||||||
- mongodb
|
- mongodb
|
||||||
mongodb:
|
mongodb:
|
||||||
image: mongo:4.4.18
|
image: mongo:4.4.18
|
||||||
container_name: checkmate-mongodb
|
|
||||||
restart: always
|
restart: always
|
||||||
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
|
command: ["mongod", "--quiet", "--bind_ip_all"]
|
||||||
ports:
|
ports:
|
||||||
- "27017:27017"
|
- "27017:27017"
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -1,25 +1,44 @@
|
|||||||
FROM node:20-alpine AS frontend-build
|
# ---------------------
|
||||||
|
# Frontend build stage
|
||||||
|
# ---------------------
|
||||||
|
FROM node:24-slim AS frontend-build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /app/client
|
WORKDIR /app/client
|
||||||
|
|
||||||
COPY client/package*.json ./
|
COPY client/package.json ./
|
||||||
RUN npm ci
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
RUN npm install esbuild@0.25.5 --build-from-source
|
||||||
|
|
||||||
COPY client ./
|
COPY client ./
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM node:20-alpine AS backend
|
# ---------------------
|
||||||
|
# Backend stage
|
||||||
|
# ---------------------
|
||||||
|
FROM node:24-slim AS backend
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app/server
|
WORKDIR /app/server
|
||||||
|
|
||||||
|
COPY server/package.json ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
COPY server ./
|
COPY server ./
|
||||||
|
|
||||||
COPY --from=frontend-build /app/client/dist ./public
|
COPY --from=frontend-build /app/client/dist ./public
|
||||||
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
RUN chmod +x ./scripts/inject-vars.sh
|
RUN chmod +x ./scripts/inject-vars.sh
|
||||||
|
|
||||||
EXPOSE 52345
|
EXPOSE 52345
|
||||||
|
|
||||||
CMD ./scripts/inject-vars.sh && node ./src/index.js
|
CMD ["sh", "-c", "./scripts/inject-vars.sh && node ./src/index.js"]
|
||||||
@@ -5,7 +5,7 @@ cd "$(dirname "$0")"
|
|||||||
cd ../..
|
cd ../..
|
||||||
|
|
||||||
# Define service names and their corresponding Dockerfiles in parallel arrays
|
# Define service names and their corresponding Dockerfiles in parallel arrays
|
||||||
services=("mono_mongo" "mono_redis" "mono_server")
|
services=("mono_mongo" "mono_server")
|
||||||
dockerfiles=(
|
dockerfiles=(
|
||||||
"./docker/dist-mono/mongoDB.Dockerfile"
|
"./docker/dist-mono/mongoDB.Dockerfile"
|
||||||
"./docker/dist-mono/server.Dockerfile"
|
"./docker/dist-mono/server.Dockerfile"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
server:
|
server:
|
||||||
image: ghcr.io/bluewave-labs/checkmate-backend-mono:latest
|
image: ghcr.io/bluewave-labs/checkmate-backend-mono:latest
|
||||||
|
pull_policy: always
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "52345:52345"
|
- "52345:52345"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:20-alpine AS frontend-build
|
FROM node:20-slim AS frontend-build
|
||||||
|
|
||||||
WORKDIR /app/client
|
WORKDIR /app/client
|
||||||
|
|
||||||
@@ -8,7 +8,12 @@ RUN npm install
|
|||||||
COPY client ./
|
COPY client ./
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM node:20-alpine AS app
|
FROM node:20-slim AS app
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app/server
|
WORKDIR /app/server
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-10
@@ -1,18 +1,9 @@
|
|||||||
FROM node:20-alpine AS build
|
FROM node:20-slim AS build
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
python3 \
|
|
||||||
make g++ \
|
|
||||||
gcc \
|
|
||||||
libc-dev \
|
|
||||||
linux-headers \
|
|
||||||
libusb-dev \
|
|
||||||
eudev-dev
|
|
||||||
|
|
||||||
COPY ./client/package*.json ./
|
COPY ./client/package*.json ./
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|||||||
Vendored
+6
-1
@@ -1,4 +1,9 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
FROM node:20-alpine AS build
|
FROM node:20-slim AS build
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
python3 \
|
|
||||||
make g++ \
|
|
||||||
gcc \
|
|
||||||
libc-dev \
|
|
||||||
linux-headers \
|
|
||||||
libusb-dev \
|
|
||||||
eudev-dev
|
|
||||||
|
|
||||||
COPY ./client/package*.json ./
|
COPY ./client/package*.json ./
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=2048"
|
ENV NODE_OPTIONS="--max-old-space-size=2048"
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
FROM node:20-alpine AS build
|
FROM node:20-slim AS build
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
python3 \
|
|
||||||
make g++ \
|
|
||||||
gcc \
|
|
||||||
libc-dev \
|
|
||||||
linux-headers \
|
|
||||||
libusb-dev \
|
|
||||||
eudev-dev
|
|
||||||
|
|
||||||
|
|
||||||
COPY ./client/package*.json ./
|
COPY ./client/package*.json ./
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install ping
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y iputils-ping \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=2048"
|
ENV NODE_OPTIONS="--max-old-space-size=2048"
|
||||||
|
|
||||||
|
|||||||
Generated
+416
-292
File diff suppressed because it is too large.
Load diff
+2
-1
@@ -28,6 +28,7 @@
|
|||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"express-rate-limit": "8.0.1",
|
"express-rate-limit": "8.0.1",
|
||||||
"gamedig": "^5.3.1",
|
"gamedig": "^5.3.1",
|
||||||
|
"got": "14.4.7",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"helmet": "^8.0.0",
|
"helmet": "^8.0.0",
|
||||||
"ioredis": "^5.4.2",
|
"ioredis": "^5.4.2",
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
"ping": "0.4.4",
|
"ping": "0.4.4",
|
||||||
"sharp": "0.33.5",
|
"sharp": "0.33.5",
|
||||||
"ssl-checker": "2.0.10",
|
"ssl-checker": "2.0.10",
|
||||||
"super-simple-scheduler": "1.3.0",
|
"super-simple-scheduler": "1.4.1",
|
||||||
"swagger-ui-express": "5.0.1",
|
"swagger-ui-express": "5.0.1",
|
||||||
"winston": "^3.13.0"
|
"winston": "^3.13.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import MaintenanceWindowService from "../service/business/maintenanceWindowServi
|
|||||||
import MonitorService from "../service/business/monitorService.js";
|
import MonitorService from "../service/business/monitorService.js";
|
||||||
import papaparse from "papaparse";
|
import papaparse from "papaparse";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import got from "got";
|
||||||
import ping from "ping";
|
import ping from "ping";
|
||||||
import http from "http";
|
import http from "http";
|
||||||
|
import https from "https";
|
||||||
import Docker from "dockerode";
|
import Docker from "dockerode";
|
||||||
import net from "net";
|
import net from "net";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@@ -32,6 +34,8 @@ import mjml2html from "mjml";
|
|||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
import { games } from "gamedig";
|
import { games } from "gamedig";
|
||||||
|
import jmespath from "jmespath";
|
||||||
|
import { GameDig } from "gamedig";
|
||||||
|
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
@@ -43,8 +47,6 @@ import { ParseBoolean } from "../utils/utils.js";
|
|||||||
|
|
||||||
// Models
|
// Models
|
||||||
import Check from "../db/models/Check.js";
|
import Check from "../db/models/Check.js";
|
||||||
import HardwareCheck from "../db/models/HardwareCheck.js";
|
|
||||||
import PageSpeedCheck from "../db/models/PageSpeedCheck.js";
|
|
||||||
import Monitor from "../db/models/Monitor.js";
|
import Monitor from "../db/models/Monitor.js";
|
||||||
import User from "../db/models/User.js";
|
import User from "../db/models/User.js";
|
||||||
import InviteToken from "../db/models/InviteToken.js";
|
import InviteToken from "../db/models/InviteToken.js";
|
||||||
@@ -52,7 +54,6 @@ import StatusPage from "../db/models/StatusPage.js";
|
|||||||
import Team from "../db/models/Team.js";
|
import Team from "../db/models/Team.js";
|
||||||
import MaintenanceWindow from "../db/models/MaintenanceWindow.js";
|
import MaintenanceWindow from "../db/models/MaintenanceWindow.js";
|
||||||
import MonitorStats from "../db/models/MonitorStats.js";
|
import MonitorStats from "../db/models/MonitorStats.js";
|
||||||
import NetworkCheck from "../db/models/NetworkCheck.js";
|
|
||||||
import Notification from "../db/models/Notification.js";
|
import Notification from "../db/models/Notification.js";
|
||||||
import RecoveryToken from "../db/models/RecoveryToken.js";
|
import RecoveryToken from "../db/models/RecoveryToken.js";
|
||||||
import AppSettings from "../db/models/AppSettings.js";
|
import AppSettings from "../db/models/AppSettings.js";
|
||||||
@@ -61,12 +62,9 @@ import InviteModule from "../db/mongo/modules/inviteModule.js";
|
|||||||
import CheckModule from "../db/mongo/modules/checkModule.js";
|
import CheckModule from "../db/mongo/modules/checkModule.js";
|
||||||
import StatusPageModule from "../db/mongo/modules/statusPageModule.js";
|
import StatusPageModule from "../db/mongo/modules/statusPageModule.js";
|
||||||
import UserModule from "../db/mongo/modules/userModule.js";
|
import UserModule from "../db/mongo/modules/userModule.js";
|
||||||
import HardwareCheckModule from "../db/mongo/modules/hardwareCheckModule.js";
|
|
||||||
import MaintenanceWindowModule from "../db/mongo/modules/maintenanceWindowModule.js";
|
import MaintenanceWindowModule from "../db/mongo/modules/maintenanceWindowModule.js";
|
||||||
import MonitorModule from "../db/mongo/modules/monitorModule.js";
|
import MonitorModule from "../db/mongo/modules/monitorModule.js";
|
||||||
import NetworkCheckModule from "../db/mongo/modules/networkCheckModule.js";
|
|
||||||
import NotificationModule from "../db/mongo/modules/notificationModule.js";
|
import NotificationModule from "../db/mongo/modules/notificationModule.js";
|
||||||
import PageSpeedCheckModule from "../db/mongo/modules/pageSpeedCheckModule.js";
|
|
||||||
import RecoveryModule from "../db/mongo/modules/recoveryModule.js";
|
import RecoveryModule from "../db/mongo/modules/recoveryModule.js";
|
||||||
import SettingsModule from "../db/mongo/modules/settingsModule.js";
|
import SettingsModule from "../db/mongo/modules/settingsModule.js";
|
||||||
|
|
||||||
@@ -80,18 +78,15 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
|||||||
const stringService = new StringService(translationService);
|
const stringService = new StringService(translationService);
|
||||||
|
|
||||||
// Create DB
|
// Create DB
|
||||||
const checkModule = new CheckModule({ logger, Check, HardwareCheck, PageSpeedCheck, Monitor, User });
|
const checkModule = new CheckModule({ logger, Check, Monitor, User });
|
||||||
const inviteModule = new InviteModule({ InviteToken, crypto, stringService });
|
const inviteModule = new InviteModule({ InviteToken, crypto, stringService });
|
||||||
const statusPageModule = new StatusPageModule({ StatusPage, NormalizeData, stringService });
|
const statusPageModule = new StatusPageModule({ StatusPage, NormalizeData, stringService });
|
||||||
const userModule = new UserModule({ User, Team, GenerateAvatarImage, ParseBoolean, stringService });
|
const userModule = new UserModule({ User, Team, GenerateAvatarImage, ParseBoolean, stringService });
|
||||||
const hardwareCheckModule = new HardwareCheckModule({ HardwareCheck, Monitor, logger });
|
|
||||||
const maintenanceWindowModule = new MaintenanceWindowModule({ MaintenanceWindow });
|
const maintenanceWindowModule = new MaintenanceWindowModule({ MaintenanceWindow });
|
||||||
const monitorModule = new MonitorModule({
|
const monitorModule = new MonitorModule({
|
||||||
Monitor,
|
Monitor,
|
||||||
MonitorStats,
|
MonitorStats,
|
||||||
Check,
|
Check,
|
||||||
PageSpeedCheck,
|
|
||||||
HardwareCheck,
|
|
||||||
stringService,
|
stringService,
|
||||||
fs,
|
fs,
|
||||||
path,
|
path,
|
||||||
@@ -100,9 +95,7 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
|||||||
NormalizeData,
|
NormalizeData,
|
||||||
NormalizeDataUptimeDetails,
|
NormalizeDataUptimeDetails,
|
||||||
});
|
});
|
||||||
const networkCheckModule = new NetworkCheckModule({ NetworkCheck });
|
|
||||||
const notificationModule = new NotificationModule({ Notification, Monitor });
|
const notificationModule = new NotificationModule({ Notification, Monitor });
|
||||||
const pageSpeedCheckModule = new PageSpeedCheckModule({ PageSpeedCheck });
|
|
||||||
const recoveryModule = new RecoveryModule({ User, RecoveryToken, crypto, stringService });
|
const recoveryModule = new RecoveryModule({ User, RecoveryToken, crypto, stringService });
|
||||||
const settingsModule = new SettingsModule({ AppSettings });
|
const settingsModule = new SettingsModule({ AppSettings });
|
||||||
|
|
||||||
@@ -113,19 +106,29 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
|||||||
inviteModule,
|
inviteModule,
|
||||||
statusPageModule,
|
statusPageModule,
|
||||||
userModule,
|
userModule,
|
||||||
hardwareCheckModule,
|
|
||||||
maintenanceWindowModule,
|
maintenanceWindowModule,
|
||||||
monitorModule,
|
monitorModule,
|
||||||
networkCheckModule,
|
|
||||||
notificationModule,
|
notificationModule,
|
||||||
pageSpeedCheckModule,
|
|
||||||
recoveryModule,
|
recoveryModule,
|
||||||
settingsModule,
|
settingsModule,
|
||||||
});
|
});
|
||||||
|
|
||||||
await db.connect();
|
await db.connect();
|
||||||
|
|
||||||
const networkService = new NetworkService(axios, ping, logger, http, Docker, net, stringService, settingsService);
|
const networkService = new NetworkService({
|
||||||
|
axios,
|
||||||
|
got,
|
||||||
|
https,
|
||||||
|
jmespath,
|
||||||
|
GameDig,
|
||||||
|
ping,
|
||||||
|
logger,
|
||||||
|
http,
|
||||||
|
Docker,
|
||||||
|
net,
|
||||||
|
stringService,
|
||||||
|
settingsService,
|
||||||
|
});
|
||||||
const emailService = new EmailService(settingsService, fs, path, compile, mjml2html, nodemailer, logger);
|
const emailService = new EmailService(settingsService, fs, path, compile, mjml2html, nodemailer, logger);
|
||||||
const bufferService = new BufferService({ db, logger, envSettings });
|
const bufferService = new BufferService({ db, logger, envSettings });
|
||||||
const statusService = new StatusService({ db, logger, buffer: bufferService });
|
const statusService = new StatusService({ db, logger, buffer: bufferService });
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ class StatusPageController extends BaseController {
|
|||||||
|
|
||||||
deleteStatusPage = this.asyncHandler(
|
deleteStatusPage = this.asyncHandler(
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
await this.db.deleteStatusPage(req.params.url);
|
await this.db.statusPageModule.deleteStatusPage(req.params.url);
|
||||||
return res.success({
|
return res.success({
|
||||||
msg: this.stringService.statusPageDelete,
|
msg: this.stringService.statusPageDelete,
|
||||||
});
|
});
|
||||||
|
|||||||
+166
-89
@@ -1,99 +1,176 @@
|
|||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
|
|
||||||
const BaseCheckSchema = mongoose.Schema({
|
const cpuSchema = mongoose.Schema({
|
||||||
/**
|
physical_core: { type: Number, default: 0 },
|
||||||
* Reference to the associated Monitor document.
|
logical_core: { type: Number, default: 0 },
|
||||||
*
|
frequency: { type: Number, default: 0 },
|
||||||
* @type {mongoose.Schema.Types.ObjectId}
|
temperature: { type: [Number], default: [] },
|
||||||
*/
|
free_percent: { type: Number, default: 0 },
|
||||||
monitorId: {
|
usage_percent: { type: Number, default: 0 },
|
||||||
type: mongoose.Schema.Types.ObjectId,
|
|
||||||
ref: "Monitor",
|
|
||||||
immutable: true,
|
|
||||||
index: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
teamId: {
|
|
||||||
type: mongoose.Schema.Types.ObjectId,
|
|
||||||
ref: "Team",
|
|
||||||
immutable: true,
|
|
||||||
index: true,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Status of the check (true for up, false for down).
|
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
status: {
|
|
||||||
type: Boolean,
|
|
||||||
index: true,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Response time of the check in milliseconds.
|
|
||||||
*
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
responseTime: {
|
|
||||||
type: Number,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* HTTP status code received during the check.
|
|
||||||
*
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
statusCode: {
|
|
||||||
type: Number,
|
|
||||||
index: true,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Message or description of the check result.
|
|
||||||
*
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
message: {
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Expiry date of the check, auto-calculated to expire after 30 days.
|
|
||||||
*
|
|
||||||
* @type {Date}
|
|
||||||
*/
|
|
||||||
|
|
||||||
expiry: {
|
|
||||||
type: Date,
|
|
||||||
default: Date.now,
|
|
||||||
expires: 60 * 60 * 24 * 30, // 30 days
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Acknowledgment of the check.
|
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
ack: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Resolution date of the check (when the check was resolved).
|
|
||||||
*
|
|
||||||
* @type {Date}
|
|
||||||
*/
|
|
||||||
ackAt: {
|
|
||||||
type: Date,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
const memorySchema = mongoose.Schema({
|
||||||
* Check Schema for MongoDB collection.
|
total_bytes: { type: Number, default: 0 },
|
||||||
*
|
available_bytes: { type: Number, default: 0 },
|
||||||
* Represents a check associated with a monitor, storing information
|
used_bytes: { type: Number, default: 0 },
|
||||||
* about the status and response of a particular check event.
|
usage_percent: { type: Number, default: 0 },
|
||||||
*/
|
});
|
||||||
const CheckSchema = mongoose.Schema({ ...BaseCheckSchema.obj }, { timestamps: true });
|
|
||||||
|
const diskSchema = mongoose.Schema({
|
||||||
|
read_speed_bytes: { type: Number, default: 0 },
|
||||||
|
write_speed_bytes: { type: Number, default: 0 },
|
||||||
|
total_bytes: { type: Number, default: 0 },
|
||||||
|
free_bytes: { type: Number, default: 0 },
|
||||||
|
usage_percent: { type: Number, default: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const hostSchema = mongoose.Schema({
|
||||||
|
os: { type: String, default: "" },
|
||||||
|
platform: { type: String, default: "" },
|
||||||
|
kernel_version: { type: String, default: "" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const errorSchema = mongoose.Schema({
|
||||||
|
metric: { type: [String], default: [] },
|
||||||
|
err: { type: String, default: "" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const captureSchema = mongoose.Schema({
|
||||||
|
version: { type: String, default: "" },
|
||||||
|
mode: { type: String, default: "" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const networkInterfaceSchema = mongoose.Schema({
|
||||||
|
name: { type: String },
|
||||||
|
bytes_sent: { type: Number, default: 0 },
|
||||||
|
bytes_recv: { type: Number, default: 0 },
|
||||||
|
packets_sent: { type: Number, default: 0 },
|
||||||
|
packets_recv: { type: Number, default: 0 },
|
||||||
|
err_in: { type: Number, default: 0 },
|
||||||
|
err_out: { type: Number, default: 0 },
|
||||||
|
drop_in: { type: Number, default: 0 },
|
||||||
|
drop_out: { type: Number, default: 0 },
|
||||||
|
fifo_in: { type: Number, default: 0 },
|
||||||
|
fifo_out: { type: Number, default: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const CheckSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
// Common fields
|
||||||
|
monitorId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "Monitor",
|
||||||
|
immutable: true,
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
teamId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "Team",
|
||||||
|
immutable: true,
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"],
|
||||||
|
required: true,
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
status: {
|
||||||
|
type: Boolean,
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
responseTime: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
|
||||||
|
timings: {
|
||||||
|
type: Object,
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
statusCode: {
|
||||||
|
type: Number,
|
||||||
|
index: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
message: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
expiry: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now,
|
||||||
|
expires: 60 * 60 * 24 * 30, // 30 days
|
||||||
|
},
|
||||||
|
|
||||||
|
ack: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
ackAt: {
|
||||||
|
type: Date,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Hardware fields
|
||||||
|
cpu: {
|
||||||
|
type: cpuSchema,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
memory: {
|
||||||
|
type: memorySchema,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
disk: {
|
||||||
|
type: [diskSchema],
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
host: {
|
||||||
|
type: hostSchema,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
type: [errorSchema],
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
|
||||||
|
capture: {
|
||||||
|
type: captureSchema,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
|
||||||
|
net: {
|
||||||
|
type: [networkInterfaceSchema],
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
|
||||||
|
// PageSpeed fields
|
||||||
|
accessibility: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
bestPractices: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
seo: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
performance: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
audits: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
CheckSchema.index({ updatedAt: 1 });
|
CheckSchema.index({ updatedAt: 1 });
|
||||||
CheckSchema.index({ monitorId: 1, updatedAt: 1 });
|
CheckSchema.index({ monitorId: 1, updatedAt: 1 });
|
||||||
CheckSchema.index({ monitorId: 1, updatedAt: -1 });
|
CheckSchema.index({ monitorId: 1, updatedAt: -1 });
|
||||||
CheckSchema.index({ teamId: 1, updatedAt: -1 });
|
CheckSchema.index({ teamId: 1, updatedAt: -1 });
|
||||||
|
|
||||||
export default mongoose.model("Check", CheckSchema);
|
export default mongoose.model("Check", CheckSchema);
|
||||||
export { BaseCheckSchema };
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
import mongoose from "mongoose";
|
|
||||||
import { BaseCheckSchema } from "./Check.js";
|
|
||||||
const cpuSchema = mongoose.Schema({
|
|
||||||
physical_core: { type: Number, default: 0 },
|
|
||||||
logical_core: { type: Number, default: 0 },
|
|
||||||
frequency: { type: Number, default: 0 },
|
|
||||||
temperature: { type: [Number], default: [] },
|
|
||||||
free_percent: { type: Number, default: 0 },
|
|
||||||
usage_percent: { type: Number, default: 0 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const memorySchema = mongoose.Schema({
|
|
||||||
total_bytes: { type: Number, default: 0 },
|
|
||||||
available_bytes: { type: Number, default: 0 },
|
|
||||||
used_bytes: { type: Number, default: 0 },
|
|
||||||
usage_percent: { type: Number, default: 0 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const diskSchema = mongoose.Schema({
|
|
||||||
read_speed_bytes: { type: Number, default: 0 },
|
|
||||||
write_speed_bytes: { type: Number, default: 0 },
|
|
||||||
total_bytes: { type: Number, default: 0 },
|
|
||||||
free_bytes: { type: Number, default: 0 },
|
|
||||||
usage_percent: { type: Number, default: 0 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const hostSchema = mongoose.Schema({
|
|
||||||
os: { type: String, default: "" },
|
|
||||||
platform: { type: String, default: "" },
|
|
||||||
kernel_version: { type: String, default: "" },
|
|
||||||
});
|
|
||||||
|
|
||||||
const errorSchema = mongoose.Schema({
|
|
||||||
metric: { type: [String], default: [] },
|
|
||||||
err: { type: String, default: "" },
|
|
||||||
});
|
|
||||||
|
|
||||||
const captureSchema = mongoose.Schema({
|
|
||||||
version: { type: String, default: "" },
|
|
||||||
mode: { type: String, default: "" },
|
|
||||||
});
|
|
||||||
|
|
||||||
const networkInterfaceSchema = mongoose.Schema({
|
|
||||||
name: { type: String },
|
|
||||||
bytes_sent: { type: Number, default: 0 },
|
|
||||||
bytes_recv: { type: Number, default: 0 },
|
|
||||||
packets_sent: { type: Number, default: 0 },
|
|
||||||
packets_recv: { type: Number, default: 0 },
|
|
||||||
err_in: { type: Number, default: 0 },
|
|
||||||
err_out: { type: Number, default: 0 },
|
|
||||||
drop_in: { type: Number, default: 0 },
|
|
||||||
drop_out: { type: Number, default: 0 },
|
|
||||||
fifo_in: { type: Number, default: 0 },
|
|
||||||
fifo_out: { type: Number, default: 0 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const HardwareCheckSchema = mongoose.Schema(
|
|
||||||
{
|
|
||||||
...BaseCheckSchema.obj,
|
|
||||||
cpu: {
|
|
||||||
type: cpuSchema,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
memory: {
|
|
||||||
type: memorySchema,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
disk: {
|
|
||||||
type: [diskSchema],
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
host: {
|
|
||||||
type: hostSchema,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
type: [errorSchema],
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
|
|
||||||
capture: {
|
|
||||||
type: captureSchema,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
net: {
|
|
||||||
type: [networkInterfaceSchema],
|
|
||||||
default: () => [],
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ timestamps: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
HardwareCheckSchema.index({ createdAt: 1 });
|
|
||||||
HardwareCheckSchema.index({ monitorId: 1, createdAt: 1 });
|
|
||||||
HardwareCheckSchema.index({ monitorId: 1, createdAt: -1 });
|
|
||||||
|
|
||||||
export default mongoose.model("HardwareCheck", HardwareCheckSchema);
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
import HardwareCheck from "./HardwareCheck.js";
|
|
||||||
import PageSpeedCheck from "./PageSpeedCheck.js";
|
|
||||||
import Check from "./Check.js";
|
import Check from "./Check.js";
|
||||||
import MonitorStats from "./MonitorStats.js";
|
import MonitorStats from "./MonitorStats.js";
|
||||||
import StatusPage from "./StatusPage.js";
|
import StatusPage from "./StatusPage.js";
|
||||||
@@ -30,6 +28,18 @@ const MonitorSchema = mongoose.Schema(
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
},
|
},
|
||||||
|
statusWindow: {
|
||||||
|
type: [Boolean],
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
statusWindowSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 5,
|
||||||
|
},
|
||||||
|
statusWindowThreshold: {
|
||||||
|
type: Number,
|
||||||
|
default: 60,
|
||||||
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -133,13 +143,7 @@ MonitorSchema.pre("findOneAndDelete", async function (next) {
|
|||||||
throw new Error("Monitor not found");
|
throw new Error("Monitor not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc?.type === "pagespeed") {
|
await Check.deleteMany({ monitorId: doc._id });
|
||||||
await PageSpeedCheck.deleteMany({ monitorId: doc._id });
|
|
||||||
} else if (doc?.type === "hardware") {
|
|
||||||
await HardwareCheck.deleteMany({ monitorId: doc._id });
|
|
||||||
} else {
|
|
||||||
await Check.deleteMany({ monitorId: doc._id });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with status pages
|
// Deal with status pages
|
||||||
await StatusPage.updateMany({ monitors: doc?._id }, { $pull: { monitors: doc?._id } });
|
await StatusPage.updateMany({ monitors: doc?._id }, { $pull: { monitors: doc?._id } });
|
||||||
@@ -156,13 +160,7 @@ MonitorSchema.pre("deleteMany", async function (next) {
|
|||||||
const monitors = await this.model.find(filter).select(["_id", "type"]).lean();
|
const monitors = await this.model.find(filter).select(["_id", "type"]).lean();
|
||||||
|
|
||||||
for (const monitor of monitors) {
|
for (const monitor of monitors) {
|
||||||
if (monitor.type === "pagespeed") {
|
await Check.deleteMany({ monitorId: monitor._id });
|
||||||
await PageSpeedCheck.deleteMany({ monitorId: monitor._id });
|
|
||||||
} else if (monitor.type === "hardware") {
|
|
||||||
await HardwareCheck.deleteMany({ monitorId: monitor._id });
|
|
||||||
} else {
|
|
||||||
await Check.deleteMany({ monitorId: monitor._id });
|
|
||||||
}
|
|
||||||
await StatusPage.updateMany({ monitors: monitor._id }, { $pull: { monitors: monitor._id } });
|
await StatusPage.updateMany({ monitors: monitor._id }, { $pull: { monitors: monitor._id } });
|
||||||
await MonitorStats.deleteMany({ monitorId: monitor._id.toString() });
|
await MonitorStats.deleteMany({ monitorId: monitor._id.toString() });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ const MonitorStatsSchema = new mongoose.Schema(
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
uptBurnt: {
|
|
||||||
type: mongoose.Schema.Types.Decimal128,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
import mongoose from "mongoose";
|
|
||||||
import { BaseCheckSchema } from "./Check.js";
|
|
||||||
|
|
||||||
const networkInterfaceSchema = mongoose.Schema({
|
|
||||||
name: { type: String, required: true },
|
|
||||||
bytes_sent: { type: Number, default: 0 },
|
|
||||||
bytes_recv: { type: Number, default: 0 },
|
|
||||||
packets_sent: { type: Number, default: 0 },
|
|
||||||
packets_recv: { type: Number, default: 0 },
|
|
||||||
err_in: { type: Number, default: 0 },
|
|
||||||
err_out: { type: Number, default: 0 },
|
|
||||||
drop_in: { type: Number, default: 0 },
|
|
||||||
drop_out: { type: Number, default: 0 },
|
|
||||||
fifo_in: { type: Number, default: 0 },
|
|
||||||
fifo_out: { type: Number, default: 0 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const captureSchema = mongoose.Schema({
|
|
||||||
version: { type: String, default: "" },
|
|
||||||
mode: { type: String, default: "" },
|
|
||||||
});
|
|
||||||
|
|
||||||
const NetworkCheckSchema = mongoose.Schema(
|
|
||||||
{
|
|
||||||
...BaseCheckSchema.obj,
|
|
||||||
data: {
|
|
||||||
type: [networkInterfaceSchema],
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
capture: {
|
|
||||||
type: captureSchema,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
errors: {
|
|
||||||
type: mongoose.Schema.Types.Mixed,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ timestamps: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
NetworkCheckSchema.index({ createdAt: 1 });
|
|
||||||
NetworkCheckSchema.index({ monitorId: 1, createdAt: 1 });
|
|
||||||
NetworkCheckSchema.index({ monitorId: 1, createdAt: -1 });
|
|
||||||
|
|
||||||
export default mongoose.model("NetworkCheck", NetworkCheckSchema);
|
|
||||||
Loaded 100 of 124 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user