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 |
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,
|
||||||
|
|||||||
@@ -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 };
|
||||||
@@ -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;
|
||||||
@@ -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({
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useState, useCallback } from "react";
|
||||||
const useInfrastructureMonitorForm = () => {
|
const useInfrastructureMonitorForm = () => {
|
||||||
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
|
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
|
||||||
url: "",
|
url: "",
|
||||||
@@ -6,6 +6,8 @@ const useInfrastructureMonitorForm = () => {
|
|||||||
notifications: [],
|
notifications: [],
|
||||||
notify_email: false,
|
notify_email: false,
|
||||||
interval: 0.25,
|
interval: 0.25,
|
||||||
|
statusWindowSize: 5,
|
||||||
|
statusWindowThreshold: 60,
|
||||||
cpu: false,
|
cpu: false,
|
||||||
usage_cpu: "",
|
usage_cpu: "",
|
||||||
memory: false,
|
memory: false,
|
||||||
@@ -29,9 +31,10 @@ const useInfrastructureMonitorForm = () => {
|
|||||||
[event.target.name]: event.target.checked,
|
[event.target.name]: event.target.checked,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const initializeInfrastructureMonitorForCreate = (globalSettings) => {
|
const initializeInfrastructureMonitorForCreate = useCallback((globalSettings) => {
|
||||||
const gt = globalSettings?.data?.settings?.globalThresholds || {};
|
const gt = globalSettings?.data?.settings?.globalThresholds || {};
|
||||||
setInfrastructureMonitor({
|
setInfrastructureMonitor((prev) => ({
|
||||||
|
...prev,
|
||||||
url: "",
|
url: "",
|
||||||
name: "",
|
name: "",
|
||||||
notifications: [],
|
notifications: [],
|
||||||
@@ -45,17 +48,20 @@ const useInfrastructureMonitorForm = () => {
|
|||||||
temperature: gt.temperature !== undefined,
|
temperature: gt.temperature !== undefined,
|
||||||
usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "",
|
usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "",
|
||||||
secret: "",
|
secret: "",
|
||||||
});
|
}));
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const initializeInfrastructureMonitorForUpdate = (monitor) => {
|
const initializeInfrastructureMonitorForUpdate = useCallback((monitor) => {
|
||||||
const MS_PER_MINUTE = 60000;
|
const MS_PER_MINUTE = 60000;
|
||||||
const { thresholds = {} } = monitor;
|
const { thresholds = {} } = monitor;
|
||||||
setInfrastructureMonitor({
|
setInfrastructureMonitor((prev) => ({
|
||||||
|
...prev,
|
||||||
url: monitor.url.replace(/^https?:\/\//, ""),
|
url: monitor.url.replace(/^https?:\/\//, ""),
|
||||||
name: monitor.name || "",
|
name: monitor.name || "",
|
||||||
notifications: monitor.notifications || [],
|
notifications: monitor.notifications || [],
|
||||||
interval: monitor.interval / MS_PER_MINUTE,
|
interval: monitor.interval / MS_PER_MINUTE,
|
||||||
|
statusWindowSize: monitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: monitor.statusWindowThreshold,
|
||||||
cpu: thresholds.usage_cpu !== undefined,
|
cpu: thresholds.usage_cpu !== undefined,
|
||||||
usage_cpu:
|
usage_cpu:
|
||||||
thresholds.usage_cpu !== undefined ? (thresholds.usage_cpu * 100).toString() : "",
|
thresholds.usage_cpu !== undefined ? (thresholds.usage_cpu * 100).toString() : "",
|
||||||
@@ -75,8 +81,8 @@ const useInfrastructureMonitorForm = () => {
|
|||||||
? (thresholds.usage_temperature * 100).toString()
|
? (thresholds.usage_temperature * 100).toString()
|
||||||
: "",
|
: "",
|
||||||
secret: monitor.secret || "",
|
secret: monitor.secret || "",
|
||||||
});
|
}));
|
||||||
};
|
}, []);
|
||||||
return {
|
return {
|
||||||
infrastructureMonitor,
|
infrastructureMonitor,
|
||||||
setInfrastructureMonitor,
|
setInfrastructureMonitor,
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ const useInfrastructureSubmit = () => {
|
|||||||
? infrastructureMonitor.url
|
? infrastructureMonitor.url
|
||||||
: infrastructureMonitor.name,
|
: infrastructureMonitor.name,
|
||||||
interval: infrastructureMonitor.interval * MS_PER_MINUTE,
|
interval: infrastructureMonitor.interval * MS_PER_MINUTE,
|
||||||
|
statusWindowSize: infrastructureMonitor.statusWindowSize,
|
||||||
|
statusWindowThreshold: infrastructureMonitor.statusWindowThreshold,
|
||||||
cpu: infrastructureMonitor.cpu,
|
cpu: infrastructureMonitor.cpu,
|
||||||
...(infrastructureMonitor.cpu
|
...(infrastructureMonitor.cpu
|
||||||
? { usage_cpu: infrastructureMonitor.usage_cpu }
|
? { usage_cpu: infrastructureMonitor.usage_cpu }
|
||||||
|
|||||||
@@ -86,7 +86,14 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
setHttps(monitor.url.startsWith("https"));
|
setHttps(monitor.url.startsWith("https"));
|
||||||
initializeInfrastructureMonitorForUpdate(monitor);
|
initializeInfrastructureMonitorForUpdate(monitor);
|
||||||
}
|
}
|
||||||
}, [isCreate, monitor, globalSettings, globalSettingsLoading]);
|
}, [
|
||||||
|
isCreate,
|
||||||
|
monitor,
|
||||||
|
globalSettings,
|
||||||
|
globalSettingsLoading,
|
||||||
|
initializeInfrastructureMonitorForCreate,
|
||||||
|
initializeInfrastructureMonitorForUpdate,
|
||||||
|
]);
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
const onSubmit = async (event) => {
|
const onSubmit = async (event) => {
|
||||||
@@ -281,6 +288,39 @@ const CreateInfrastructureMonitor = () => {
|
|||||||
setNotifications={infrastructureMonitor.notifications}
|
setNotifications={infrastructureMonitor.notifications}
|
||||||
/>
|
/>
|
||||||
</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={infrastructureMonitor.statusWindowSize}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors["statusWindowSize"] ? true : false}
|
||||||
|
helperText={errors["statusWindowSize"]}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
name="statusWindowThreshold"
|
||||||
|
label={t("createMonitorPage.incidentConfigStatusWindowThresholdLabel")}
|
||||||
|
type="number"
|
||||||
|
value={infrastructureMonitor.statusWindowThreshold}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors["statusWindowThreshold"] ? true : false}
|
||||||
|
helperText={errors["statusWindowThreshold"]}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</ConfigBox>
|
||||||
<CustomAlertsSection
|
<CustomAlertsSection
|
||||||
errors={errors}
|
errors={errors}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -130,10 +130,12 @@ const monitorValidation = joi.object({
|
|||||||
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()
|
||||||
@@ -435,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()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -376,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": "",
|
||||||
@@ -742,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
@@ -376,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": "",
|
||||||
@@ -742,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
@@ -380,7 +380,52 @@
|
|||||||
"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",
|
||||||
@@ -746,7 +791,8 @@
|
|||||||
"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": "Warteschlangenmetriken",
|
"title": "Warteschlangenmetriken",
|
||||||
|
|||||||
@@ -251,7 +251,7 @@
|
|||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"createA": "Create a",
|
"createA": "Create a",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"maintenanceWindowDescription": "Your pings won't be sent during this time frame",
|
"maintenanceWindowDescription": "During maintenance windows, all monitoring is suspended for selected monitors. No network checks will be performed, preventing any status updates or notifications from being triggered. Your monitors will appear frozen at their last known status, and status pages will display a maintenance indicator. Once the maintenance window ends, monitoring automatically resumes, and alerts will trigger if issues are detected. Maintenance periods do not count against uptime calculations.",
|
||||||
"startTime": "Start time",
|
"startTime": "Start time",
|
||||||
"timeZoneInfo": "All dates and times are in GMT+0 time zone.",
|
"timeZoneInfo": "All dates and times are in GMT+0 time zone.",
|
||||||
"monitorsToApply": "Monitors to apply maintenance window to",
|
"monitorsToApply": "Monitors to apply maintenance window to",
|
||||||
@@ -380,7 +380,52 @@
|
|||||||
"email": "Email",
|
"email": "Email",
|
||||||
"role": "Role",
|
"role": "Role",
|
||||||
"created": "Created"
|
"created": "Created"
|
||||||
}
|
},
|
||||||
|
"addTeamMember": {
|
||||||
|
"addMemberMenu": "Add Team Member",
|
||||||
|
"title": "Register new team member",
|
||||||
|
"description": "Create a new user and share the credentials with them. This method gives the member immediate access to all monitors.",
|
||||||
|
"addButton": "Add Member"
|
||||||
|
},
|
||||||
|
"register": "Register a team member",
|
||||||
|
"registerToast": {
|
||||||
|
"success": "User created, share credentials with the member securely.",
|
||||||
|
"dbUserExists": "User already exists.",
|
||||||
|
"unknownError": "Unknown error occurred."
|
||||||
|
},
|
||||||
|
"registerTeamMember": {
|
||||||
|
"title": "Register team member",
|
||||||
|
"auth": {
|
||||||
|
"common": {
|
||||||
|
"inputs": {
|
||||||
|
"firstName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "Please enter a name",
|
||||||
|
"pattern": "Name must contain only letters, spaces, apostrophes, or hyphens"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "Please enter a surname",
|
||||||
|
"pattern": "Surname must contain only letters, spaces, apostrophes, or hyphens"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "To continue, please enter an email address",
|
||||||
|
"invalid": "Please recheck validity of entered email address"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"errors": {
|
||||||
|
"empty": "Role is required"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"role": "Role"
|
||||||
},
|
},
|
||||||
"monitorState": {
|
"monitorState": {
|
||||||
"paused": "Paused",
|
"paused": "Paused",
|
||||||
@@ -440,7 +485,7 @@
|
|||||||
"uptimeGeneralInstructions": {
|
"uptimeGeneralInstructions": {
|
||||||
"http": "Enter the URL or IP to monitor (e.g., https://example.com/ or 192.168.1.100) and add a clear display name that appears on the dashboard.",
|
"http": "Enter the URL or IP to monitor (e.g., https://example.com/ or 192.168.1.100) and add a clear display name that appears on the dashboard.",
|
||||||
"ping": "Enter the IP address or hostname to ping (e.g., 192.168.1.100 or example.com) and add a clear display name that appears on the dashboard.",
|
"ping": "Enter the IP address or hostname to ping (e.g., 192.168.1.100 or example.com) and add a clear display name that appears on the dashboard.",
|
||||||
"docker": "Enter the Docker ID of your container. Docker IDs must be the full 64 char Docker ID. You can run docker inspect <short_id> to get the full container ID.",
|
"docker": "Enter the Docker container name or ID. You can use either the container name (e.g., my-app) or the container ID (full 64-char ID or short ID).",
|
||||||
"port": "Enter the URL or IP of the server, the port number and a clear display name that appears on the dashboard.",
|
"port": "Enter the URL or IP of the server, the port number and a clear display name that appears on the dashboard.",
|
||||||
"game": "Enter the IP address or hostname and the port number to ping (e.g., 192.168.1.100 or example.com) and choose game type."
|
"game": "Enter the IP address or hostname and the port number to ping (e.g., 192.168.1.100 or example.com) and choose game type."
|
||||||
},
|
},
|
||||||
@@ -746,7 +791,8 @@
|
|||||||
"failCountHeader": "Fail count",
|
"failCountHeader": "Fail count",
|
||||||
"lastRunHeader": "Last run at",
|
"lastRunHeader": "Last run at",
|
||||||
"lastFinishedAtHeader": "Last finished at",
|
"lastFinishedAtHeader": "Last finished at",
|
||||||
"lastRunTookHeader": "Last run took"
|
"lastRunTookHeader": "Last run took",
|
||||||
|
"intervalHeader": "Interval"
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "Queue metrics",
|
"title": "Queue metrics",
|
||||||
@@ -1014,9 +1060,9 @@
|
|||||||
},
|
},
|
||||||
"monitorType": {
|
"monitorType": {
|
||||||
"docker": {
|
"docker": {
|
||||||
"label": "Container ID",
|
"label": "Container Name/ID",
|
||||||
"namePlaceholder": "My Container",
|
"namePlaceholder": "My Container",
|
||||||
"placeholder": "abcd1234"
|
"placeholder": "my-app or abcd1234"
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"label": "URL to monitor",
|
"label": "URL to monitor",
|
||||||
|
|||||||
@@ -376,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": "",
|
||||||
@@ -742,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
@@ -376,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",
|
||||||
@@ -742,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
@@ -380,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",
|
||||||
@@ -746,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",
|
||||||
|
|||||||
@@ -380,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": "一時停止",
|
||||||
@@ -746,7 +791,8 @@
|
|||||||
"failCountHeader": "失敗回数",
|
"failCountHeader": "失敗回数",
|
||||||
"lastRunHeader": "最終実行日時",
|
"lastRunHeader": "最終実行日時",
|
||||||
"lastFinishedAtHeader": "最終完了日時",
|
"lastFinishedAtHeader": "最終完了日時",
|
||||||
"lastRunTookHeader": "最終実行時間"
|
"lastRunTookHeader": "最終実行時間",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "キューメトリック",
|
"title": "キューメトリック",
|
||||||
|
|||||||
@@ -380,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",
|
||||||
@@ -746,7 +791,8 @@
|
|||||||
"failCountHeader": "Contagem de falhas",
|
"failCountHeader": "Contagem de falhas",
|
||||||
"lastRunHeader": "Última corrida em",
|
"lastRunHeader": "Última corrida em",
|
||||||
"lastFinishedAtHeader": "Última conclusão em",
|
"lastFinishedAtHeader": "Última conclusão em",
|
||||||
"lastRunTookHeader": "A última corrida aconteceu"
|
"lastRunTookHeader": "A última corrida aconteceu",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "Métricas de fila",
|
"title": "Métricas de fila",
|
||||||
|
|||||||
+111
-65
@@ -376,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": "Остановлено",
|
||||||
@@ -421,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": {
|
||||||
@@ -447,24 +492,24 @@
|
|||||||
"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": {
|
||||||
@@ -491,49 +536,49 @@
|
|||||||
"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": {
|
||||||
@@ -549,20 +594,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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": {
|
||||||
@@ -573,42 +618,42 @@
|
|||||||
},
|
},
|
||||||
"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": ""
|
"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": "",
|
||||||
@@ -742,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -376,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",
|
||||||
@@ -742,7 +787,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "Son tamamlama",
|
"lastFinishedAtHeader": "Son tamamlama",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -380,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": "",
|
||||||
@@ -746,7 +791,8 @@
|
|||||||
"failCountHeader": "",
|
"failCountHeader": "",
|
||||||
"lastRunHeader": "",
|
"lastRunHeader": "",
|
||||||
"lastFinishedAtHeader": "",
|
"lastFinishedAtHeader": "",
|
||||||
"lastRunTookHeader": ""
|
"lastRunTookHeader": "",
|
||||||
|
"intervalHeader": ""
|
||||||
},
|
},
|
||||||
"metricsTable": {
|
"metricsTable": {
|
||||||
"title": "",
|
"title": "",
|
||||||
|
|||||||
@@ -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.1.2";
|
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:
|
||||||
@@ -16,7 +17,7 @@ services:
|
|||||||
mongodb:
|
mongodb:
|
||||||
image: mongo:4.4.18
|
image: mongo:4.4.18
|
||||||
restart: always
|
restart: always
|
||||||
command: ["mongod", "--quiet", --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"]
|
||||||
@@ -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
+285
-281
@@ -39,7 +39,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"
|
||||||
},
|
},
|
||||||
@@ -94,9 +94,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.27.6",
|
"version": "7.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz",
|
||||||
"integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
|
"integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -128,9 +128,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/color-helpers": {
|
"node_modules/@csstools/color-helpers": {
|
||||||
"version": "5.0.2",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
|
||||||
"integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==",
|
"integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -170,9 +170,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/css-color-parser": {
|
"node_modules/@csstools/css-color-parser": {
|
||||||
"version": "3.0.10",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
|
||||||
"integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==",
|
"integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/color-helpers": "^5.0.2",
|
"@csstools/color-helpers": "^5.1.0",
|
||||||
"@csstools/css-calc": "^2.1.4"
|
"@csstools/css-calc": "^2.1.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -249,9 +249,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emnapi/runtime": {
|
"node_modules/@emnapi/runtime": {
|
||||||
"version": "1.4.5",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
|
||||||
"integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==",
|
"integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -259,9 +259,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.7.0",
|
"version": "4.8.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.8.0.tgz",
|
||||||
"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
|
"integrity": "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -316,9 +316,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-helpers": {
|
"node_modules/@eslint/config-helpers": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
|
||||||
"integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
|
"integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -326,9 +326,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/core": {
|
"node_modules/@eslint/core": {
|
||||||
"version": "0.15.1",
|
"version": "0.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
|
||||||
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
|
"integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -376,9 +376,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.31.0",
|
"version": "9.34.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz",
|
||||||
"integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==",
|
"integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -399,13 +399,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/plugin-kit": {
|
"node_modules/@eslint/plugin-kit": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
|
||||||
"integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
|
"integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/core": "^0.15.1",
|
"@eslint/core": "^0.15.2",
|
||||||
"levn": "^0.4.1"
|
"levn": "^0.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -469,33 +469,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanfs/node": {
|
"node_modules/@humanfs/node": {
|
||||||
"version": "0.16.6",
|
"version": "0.16.7",
|
||||||
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
|
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
|
||||||
"integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
|
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanfs/core": "^0.19.1",
|
"@humanfs/core": "^0.19.1",
|
||||||
"@humanwhocodes/retry": "^0.3.0"
|
"@humanwhocodes/retry": "^0.4.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.18.0"
|
"node": ">=18.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
|
|
||||||
"version": "0.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
|
|
||||||
"integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18.18"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/nzakas"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@humanwhocodes/module-importer": {
|
"node_modules/@humanwhocodes/module-importer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||||
@@ -886,9 +872,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ioredis/commands": {
|
"node_modules/@ioredis/commands": {
|
||||||
"version": "1.2.0",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.1.tgz",
|
||||||
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==",
|
"integrity": "sha512-bYtU8avhGIcje3IhvF9aSjsa5URMZBHnwKtOvXsT4sfYy9gppW11gLPT/9oNqlJZD47yPKveQFTAFWpHjKvUoQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@isaacs/cliui": {
|
"node_modules/@isaacs/cliui": {
|
||||||
@@ -929,16 +915,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.5.4",
|
"version": "1.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||||
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
|
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.29",
|
"version": "0.3.30",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
|
||||||
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
|
"integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1198,14 +1184,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sinonjs/samsam": {
|
"node_modules/@sinonjs/samsam": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz",
|
||||||
"integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==",
|
"integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sinonjs/commons": "^3.0.1",
|
"@sinonjs/commons": "^3.0.1",
|
||||||
"lodash.get": "^4.4.2",
|
|
||||||
"type-detect": "^4.1.0"
|
"type-detect": "^4.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1238,6 +1223,17 @@
|
|||||||
"node": ">=14.16"
|
"node": ">=14.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@trysound/sax": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
@@ -1266,14 +1262,20 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "24.1.0",
|
"version": "24.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
|
||||||
"integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==",
|
"integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.8.0"
|
"undici-types": "~7.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/relateurl": {
|
||||||
|
"version": "0.2.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.33.tgz",
|
||||||
|
"integrity": "sha512-bTQCKsVbIdzLqZhLkF5fcJQreE4y1ro4DIyVrlDNSCJRRwHhB8Z+4zXXa8jN6eDvc2HbRsEYgbvrnGvi54EpSw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/triple-beam": {
|
"node_modules/@types/triple-beam": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
|
||||||
@@ -1383,9 +1385,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "6.1.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz",
|
||||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
"integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
@@ -1503,12 +1505,6 @@
|
|||||||
"readable-stream": "~1.0.2"
|
"readable-stream": "~1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/barse/node_modules/isarray": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
|
||||||
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/barse/node_modules/readable-stream": {
|
"node_modules/barse/node_modules/readable-stream": {
|
||||||
"version": "1.0.34",
|
"version": "1.0.34",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||||
@@ -1664,9 +1660,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/browserslist": {
|
"node_modules/browserslist": {
|
||||||
"version": "4.25.1",
|
"version": "4.25.4",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz",
|
||||||
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
|
"integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -1683,8 +1679,8 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001726",
|
"caniuse-lite": "^1.0.30001737",
|
||||||
"electron-to-chromium": "^1.5.173",
|
"electron-to-chromium": "^1.5.211",
|
||||||
"node-releases": "^2.0.19",
|
"node-releases": "^2.0.19",
|
||||||
"update-browserslist-db": "^1.1.3"
|
"update-browserslist-db": "^1.1.3"
|
||||||
},
|
},
|
||||||
@@ -1909,9 +1905,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001727",
|
"version": "1.0.30001739",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz",
|
||||||
"integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
|
"integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -2303,6 +2299,12 @@
|
|||||||
"typedarray": "^0.0.6"
|
"typedarray": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/concat-stream/node_modules/isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/concat-stream/node_modules/readable-stream": {
|
"node_modules/concat-stream/node_modules/readable-stream": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
@@ -2362,9 +2364,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/cookie": {
|
"node_modules/cookie": {
|
||||||
"version": "0.7.1",
|
"version": "0.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||||
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
|
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
@@ -2383,15 +2385,6 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cookie-parser/node_modules/cookie": {
|
|
||||||
"version": "0.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
|
||||||
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cookie-signature": {
|
"node_modules/cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
@@ -2511,6 +2504,21 @@
|
|||||||
"url": "https://github.com/sponsors/fb55"
|
"url": "https://github.com/sponsors/fb55"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-tree": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"mdn-data": "2.0.30",
|
||||||
|
"source-map-js": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/css-what": {
|
"node_modules/css-what": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
|
||||||
@@ -2536,12 +2544,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cssnano": {
|
"node_modules/cssnano": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.1.1.tgz",
|
||||||
"integrity": "sha512-Pu3rlKkd0ZtlCUzBrKL1Z4YmhKppjC1H9jo7u1o4qaKqyhvixFgu5qLyNIAOjSTg9DjVPtUqdROq2EfpVMEe+w==",
|
"integrity": "sha512-fm4D8ti0dQmFPeF8DXSAA//btEmqCOgAc/9Oa3C1LW94h5usNrJEfrON7b4FkPZgnDEn6OUs5NdxiJZmAtGOpQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssnano-preset-default": "^7.0.8",
|
"cssnano-preset-default": "^7.0.9",
|
||||||
"lilconfig": "^3.1.3"
|
"lilconfig": "^3.1.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2556,9 +2564,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cssnano-preset-default": {
|
"node_modules/cssnano-preset-default": {
|
||||||
"version": "7.0.8",
|
"version": "7.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.9.tgz",
|
||||||
"integrity": "sha512-d+3R2qwrUV3g4LEMOjnndognKirBZISylDZAF/TPeCWVjEwlXS2e4eN4ICkoobRe7pD3H6lltinKVyS1AJhdjQ==",
|
"integrity": "sha512-tCD6AAFgYBOVpMBX41KjbvRh9c2uUjLXRyV7KHSIrwHiq5Z9o0TFfUCoM3TwVrRsRteN3sVXGNvjVNxYzkpTsA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.25.1",
|
"browserslist": "^4.25.1",
|
||||||
@@ -2566,7 +2574,7 @@
|
|||||||
"cssnano-utils": "^5.0.1",
|
"cssnano-utils": "^5.0.1",
|
||||||
"postcss-calc": "^10.1.1",
|
"postcss-calc": "^10.1.1",
|
||||||
"postcss-colormin": "^7.0.4",
|
"postcss-colormin": "^7.0.4",
|
||||||
"postcss-convert-values": "^7.0.6",
|
"postcss-convert-values": "^7.0.7",
|
||||||
"postcss-discard-comments": "^7.0.4",
|
"postcss-discard-comments": "^7.0.4",
|
||||||
"postcss-discard-duplicates": "^7.0.2",
|
"postcss-discard-duplicates": "^7.0.2",
|
||||||
"postcss-discard-empty": "^7.0.1",
|
"postcss-discard-empty": "^7.0.1",
|
||||||
@@ -3012,9 +3020,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.190",
|
"version": "1.5.213",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.190.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.213.tgz",
|
||||||
"integrity": "sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==",
|
"integrity": "sha512-xr9eRzSLNa4neDO0xVFrkXu3vyIzG4Ay08dApecw42Z1NbmCt+keEpXdvlYGVe0wtvY5dhW0Ay0lY0IOfsCg0Q==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/emitter-component": {
|
"node_modules/emitter-component": {
|
||||||
@@ -3196,20 +3204,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.31.0",
|
"version": "9.34.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz",
|
||||||
"integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==",
|
"integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
"@eslint/config-array": "^0.21.0",
|
"@eslint/config-array": "^0.21.0",
|
||||||
"@eslint/config-helpers": "^0.3.0",
|
"@eslint/config-helpers": "^0.3.1",
|
||||||
"@eslint/core": "^0.15.0",
|
"@eslint/core": "^0.15.2",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@eslint/js": "9.31.0",
|
"@eslint/js": "9.34.0",
|
||||||
"@eslint/plugin-kit": "^0.3.1",
|
"@eslint/plugin-kit": "^0.3.5",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.4.2",
|
"@humanwhocodes/retry": "^0.4.2",
|
||||||
@@ -3290,6 +3298,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-mocha/node_modules/type-fest": {
|
||||||
|
"version": "0.20.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
|
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-scope": {
|
"node_modules/eslint-scope": {
|
||||||
"version": "8.4.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||||
@@ -3503,6 +3524,15 @@
|
|||||||
"express": ">= 4.11"
|
"express": ">= 4.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/express/node_modules/cookie": {
|
||||||
|
"version": "0.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
|
||||||
|
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/express/node_modules/debug": {
|
"node_modules/express/node_modules/debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
@@ -3705,9 +3735,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.9",
|
"version": "1.15.11",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -3960,6 +3990,18 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/gaxios/node_modules/is-stream": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gbxremote": {
|
"node_modules/gbxremote": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/gbxremote/-/gbxremote-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/gbxremote/-/gbxremote-0.2.1.tgz",
|
||||||
@@ -4037,18 +4079,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-stream/node_modules/is-stream": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "10.4.5",
|
"version": "10.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||||
@@ -4156,18 +4186,6 @@
|
|||||||
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/got/node_modules/type-fest": {
|
|
||||||
"version": "4.41.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
|
|
||||||
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
|
|
||||||
"license": "(MIT OR CC0-1.0)",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/handlebars": {
|
"node_modules/handlebars": {
|
||||||
"version": "4.7.8",
|
"version": "4.7.8",
|
||||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||||
@@ -4277,11 +4295,12 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/htmlnano": {
|
"node_modules/htmlnano": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.1.3.tgz",
|
||||||
"integrity": "sha512-8Fst+0bhAfU362S6oHVb4wtJj/UYEFr0qiCLAEi8zioqmp1JYBQx5crZAADlFVX0Ly/6s/IQz6G7PL9/hgoJaQ==",
|
"integrity": "sha512-mzTUHhxdfDw80X36rv5qFvjvor7r0uCwXI5mzo8CW61tImbe5Jpvl3JzPAetVh54wUYVuoa8x3qw8LFn8B3gHQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/relateurl": "^0.2.33",
|
||||||
"cosmiconfig": "^9.0.0",
|
"cosmiconfig": "^9.0.0",
|
||||||
"posthtml": "^0.16.5"
|
"posthtml": "^0.16.5"
|
||||||
},
|
},
|
||||||
@@ -4493,12 +4512,12 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/ioredis": {
|
"node_modules/ioredis": {
|
||||||
"version": "5.6.1",
|
"version": "5.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.7.0.tgz",
|
||||||
"integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==",
|
"integrity": "sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ioredis/commands": "^1.1.1",
|
"@ioredis/commands": "^1.3.0",
|
||||||
"cluster-key-slot": "^1.1.0",
|
"cluster-key-slot": "^1.1.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"denque": "^2.1.0",
|
"denque": "^2.1.0",
|
||||||
@@ -4614,12 +4633,12 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/is-stream": {
|
"node_modules/is-stream": {
|
||||||
"version": "2.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
|
||||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
"integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
@@ -4639,9 +4658,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/isarray": {
|
"node_modules/isarray": {
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
@@ -4717,9 +4736,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/istanbul-reports": {
|
"node_modules/istanbul-reports": {
|
||||||
"version": "3.1.7",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
|
||||||
"integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
|
"integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -5066,14 +5085,6 @@
|
|||||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash.get": {
|
|
||||||
"version": "4.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
|
||||||
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
|
||||||
"deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/lodash.includes": {
|
"node_modules/lodash.includes": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
@@ -5182,9 +5193,9 @@
|
|||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/loupe": {
|
"node_modules/loupe": {
|
||||||
"version": "3.1.4",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
|
||||||
"integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==",
|
"integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -5251,6 +5262,14 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdn-data": {
|
||||||
|
"version": "2.0.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/media-typer": {
|
"node_modules/media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
@@ -5919,9 +5938,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongodb": {
|
"node_modules/mongodb": {
|
||||||
"version": "6.18.0",
|
"version": "6.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.19.0.tgz",
|
||||||
"integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==",
|
"integrity": "sha512-H3GtYujOJdeKIMLKBT9PwlDhGrQfplABNF1G904w6r5ZXKWyv77aB0X9B+rhmaAwjtllHzaEkvi9mkGVZxs2Bw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mongodb-js/saslprep": "^1.1.9",
|
"@mongodb-js/saslprep": "^1.1.9",
|
||||||
@@ -5937,7 +5956,7 @@
|
|||||||
"gcp-metadata": "^5.2.0",
|
"gcp-metadata": "^5.2.0",
|
||||||
"kerberos": "^2.0.1",
|
"kerberos": "^2.0.1",
|
||||||
"mongodb-client-encryption": ">=6.0.0 <7",
|
"mongodb-client-encryption": ">=6.0.0 <7",
|
||||||
"snappy": "^7.2.2",
|
"snappy": "^7.3.2",
|
||||||
"socks": "^2.7.1"
|
"socks": "^2.7.1"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
@@ -5975,14 +5994,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose": {
|
"node_modules/mongoose": {
|
||||||
"version": "8.16.4",
|
"version": "8.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.16.4.tgz",
|
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.18.0.tgz",
|
||||||
"integrity": "sha512-jslgdQ8pY2vcNSKPv3Dbi5ogo/NT8zcvf6kPDyD8Sdsjsa1at3AFAF0F5PT+jySPGSPbvlNaQ49nT9h+Kx2UDA==",
|
"integrity": "sha512-3TixPihQKBdyaYDeJqRjzgb86KbilEH07JmzV8SoSjgoskNTpa6oTBmDxeoF9p8YnWQoz7shnCyPkSV/48y3yw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bson": "^6.10.4",
|
"bson": "^6.10.4",
|
||||||
"kareem": "2.6.3",
|
"kareem": "2.6.3",
|
||||||
"mongodb": "~6.17.0",
|
"mongodb": "~6.18.0",
|
||||||
"mpath": "0.9.0",
|
"mpath": "0.9.0",
|
||||||
"mquery": "5.0.0",
|
"mquery": "5.0.0",
|
||||||
"ms": "2.1.3",
|
"ms": "2.1.3",
|
||||||
@@ -5997,9 +6016,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose/node_modules/mongodb": {
|
"node_modules/mongoose/node_modules/mongodb": {
|
||||||
"version": "6.17.0",
|
"version": "6.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz",
|
||||||
"integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==",
|
"integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mongodb-js/saslprep": "^1.1.9",
|
"@mongodb-js/saslprep": "^1.1.9",
|
||||||
@@ -6187,13 +6206,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nise/node_modules/path-to-regexp": {
|
"node_modules/nise/node_modules/path-to-regexp": {
|
||||||
"version": "8.2.0",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
|
||||||
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
|
"integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"funding": {
|
||||||
"node": ">=16"
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-abort-controller": {
|
"node_modules/node-abort-controller": {
|
||||||
@@ -6751,9 +6771,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-convert-values": {
|
"node_modules/postcss-convert-values": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.7.tgz",
|
||||||
"integrity": "sha512-MD/eb39Mr60hvgrqpXsgbiqluawYg/8K4nKsqRsuDX9f+xN1j6awZCUv/5tLH8ak3vYp/EMXwdcnXvfZYiejCQ==",
|
"integrity": "sha512-HR9DZLN04Xbe6xugRH6lS4ZQH2zm/bFh/ZyRkpedZozhvh+awAfbA0P36InO4fZfDhvYfNJeNvlTf1sjwGbw/A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.25.1",
|
"browserslist": "^4.25.1",
|
||||||
@@ -7351,9 +7371,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/protobufjs": {
|
"node_modules/protobufjs": {
|
||||||
"version": "7.5.3",
|
"version": "7.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
|
||||||
"integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==",
|
"integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -7995,9 +8015,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/ssh2": {
|
"node_modules/ssh2": {
|
||||||
"version": "1.16.0",
|
"version": "1.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz",
|
||||||
"integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==",
|
"integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asn1": "^0.2.6",
|
"asn1": "^0.2.6",
|
||||||
@@ -8008,7 +8028,7 @@
|
|||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"cpu-features": "~0.0.10",
|
"cpu-features": "~0.0.10",
|
||||||
"nan": "^2.20.0"
|
"nan": "^2.23.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ssl-checker": {
|
"node_modules/ssl-checker": {
|
||||||
@@ -8077,6 +8097,12 @@
|
|||||||
"readable-stream": "^2.1.0"
|
"readable-stream": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string-to-stream/node_modules/isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/string-to-stream/node_modules/readable-stream": {
|
"node_modules/string-to-stream/node_modules/readable-stream": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
@@ -8245,86 +8271,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/super-simple-scheduler": {
|
"node_modules/super-simple-scheduler": {
|
||||||
"version": "1.3.0",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/super-simple-scheduler/-/super-simple-scheduler-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/super-simple-scheduler/-/super-simple-scheduler-1.4.1.tgz",
|
||||||
"integrity": "sha512-iEGZ+a9Xv7pIaA+XhVuHSGaasQg2T6/afTRlQhosQiiU/7ykpZBsiZB/L2Hqfem5YUrbr3Q8tzrjjXCXKMg81A==",
|
"integrity": "sha512-jKVwxdRBXOHrUstA2pvO4jBZIA3CUinKiQ6k5C2Wn5tscoV3srppPxW0zG3VNKTCaGxo3yPn6Zaf3IDVBcAwRA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"human-interval": "2.0.1",
|
|
||||||
"ioredis": "5.6.1",
|
|
||||||
"mongoose": "8.16.1",
|
|
||||||
"uuid": "11.1.0",
|
"uuid": "11.1.0",
|
||||||
"winston": "3.17.0"
|
"winston": "3.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/super-simple-scheduler/node_modules/mongodb": {
|
|
||||||
"version": "6.17.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz",
|
|
||||||
"integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@mongodb-js/saslprep": "^1.1.9",
|
|
||||||
"bson": "^6.10.4",
|
|
||||||
"mongodb-connection-string-url": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.20.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@aws-sdk/credential-providers": "^3.188.0",
|
|
||||||
"@mongodb-js/zstd": "^1.1.0 || ^2.0.0",
|
|
||||||
"gcp-metadata": "^5.2.0",
|
|
||||||
"kerberos": "^2.0.1",
|
|
||||||
"mongodb-client-encryption": ">=6.0.0 <7",
|
|
||||||
"snappy": "^7.2.2",
|
|
||||||
"socks": "^2.7.1"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@aws-sdk/credential-providers": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@mongodb-js/zstd": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"gcp-metadata": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"kerberos": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"mongodb-client-encryption": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"snappy": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"socks": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/super-simple-scheduler/node_modules/mongoose": {
|
|
||||||
"version": "8.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.16.1.tgz",
|
|
||||||
"integrity": "sha512-Q+0TC+KLdY4SYE+u9gk9pdW1tWu/pl0jusyEkMGTgBoAbvwQdfy4f9IM8dmvCwb/blSfp7IfLkob7v76x6ZGpQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"bson": "^6.10.4",
|
|
||||||
"kareem": "2.6.3",
|
|
||||||
"mongodb": "~6.17.0",
|
|
||||||
"mpath": "0.9.0",
|
|
||||||
"mquery": "5.0.0",
|
|
||||||
"ms": "2.1.3",
|
|
||||||
"sift": "17.1.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.20.1"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/mongoose"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/super-simple-scheduler/node_modules/uuid": {
|
"node_modules/super-simple-scheduler/node_modules/uuid": {
|
||||||
"version": "11.1.0",
|
"version": "11.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
||||||
@@ -8351,10 +8306,48 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svgo": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@trysound/sax": "0.2.0",
|
||||||
|
"commander": "^7.2.0",
|
||||||
|
"css-select": "^5.1.0",
|
||||||
|
"css-tree": "^2.3.1",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"csso": "^5.0.5",
|
||||||
|
"picocolors": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"svgo": "bin/svgo"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/svgo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svgo/node_modules/commander": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/swagger-ui-dist": {
|
"node_modules/swagger-ui-dist": {
|
||||||
"version": "5.27.0",
|
"version": "5.28.1",
|
||||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.28.1.tgz",
|
||||||
"integrity": "sha512-tS6LRyBhY6yAqxrfsA9IYpGWPUJOri6sclySa7TdC7XQfGLvTwDY531KLgfQwHEtQsn+sT4JlUspbeQDBVGWig==",
|
"integrity": "sha512-IvPrtNi8MvjiuDgoSmPYgg27Lvu38fnLD1OSd8Y103xXsPAqezVNnNeHnVCZ/d+CMXJblflGaIyHxAYIF3O71w==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scarf/scarf": "=1.4.0"
|
"@scarf/scarf": "=1.4.0"
|
||||||
@@ -8588,13 +8581,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/type-fest": {
|
"node_modules/type-fest": {
|
||||||
"version": "0.20.2",
|
"version": "4.41.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
|
||||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
|
||||||
"dev": true,
|
|
||||||
"license": "(MIT OR CC0-1.0)",
|
"license": "(MIT OR CC0-1.0)",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=16"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
@@ -8640,18 +8632,18 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "7.12.0",
|
"version": "7.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-7.15.0.tgz",
|
||||||
"integrity": "sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==",
|
"integrity": "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.18.1"
|
"node": ">=20.18.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "7.8.0",
|
"version": "7.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
|
||||||
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
|
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unfetch": {
|
"node_modules/unfetch": {
|
||||||
@@ -9031,6 +9023,18 @@
|
|||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/winston/node_modules/is-stream": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
|
|||||||
+1
-1
@@ -46,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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const CheckSchema = new mongoose.Schema(
|
|||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: ["http", "hardware", "pagespeed", "distributed"],
|
enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"],
|
||||||
required: true,
|
required: true,
|
||||||
index: true,
|
index: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const MonitorSchema = mongoose.Schema(
|
|||||||
},
|
},
|
||||||
statusWindowThreshold: {
|
statusWindowThreshold: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0.6,
|
default: 60,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
import AppSettings from "../models/AppSettings.js";
|
import AppSettings from "../models/AppSettings.js";
|
||||||
|
import { runMigrations } from "./migration/index.js";
|
||||||
class MongoDB {
|
class MongoDB {
|
||||||
static SERVICE_NAME = "MongoDB";
|
static SERVICE_NAME = "MongoDB";
|
||||||
|
|
||||||
@@ -65,6 +65,8 @@ class MongoDB {
|
|||||||
service: this.SERVICE_NAME,
|
service: this.SERVICE_NAME,
|
||||||
method: "connect",
|
method: "connect",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runMigrations();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error({
|
this.logger.error({
|
||||||
message: error.message,
|
message: error.message,
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import Monitor from "../../models/Monitor.js";
|
||||||
|
async function migrateStatusWindowThreshold() {
|
||||||
|
try {
|
||||||
|
const monitors = await Monitor.find({ statusWindowThreshold: { $lt: 1 } });
|
||||||
|
for (const monitor of monitors) {
|
||||||
|
monitor.statusWindowThreshold = monitor.statusWindowThreshold * 100;
|
||||||
|
await monitor.save();
|
||||||
|
console.log(`Migrated monitor ${monitor._id}: statusWindowThreshold set to ${monitor.statusWindowThreshold}`);
|
||||||
|
}
|
||||||
|
console.log("StatusWindowThreshold migration complete.");
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Migration error:", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { migrateStatusWindowThreshold };
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { migrateStatusWindowThreshold } from "./0001_migrateStatusWindowThreshold.js";
|
||||||
|
|
||||||
|
const runMigrations = async () => {
|
||||||
|
await migrateStatusWindowThreshold();
|
||||||
|
};
|
||||||
|
|
||||||
|
export { runMigrations };
|
||||||
@@ -162,6 +162,14 @@ class StatusPageModule {
|
|||||||
as: "monitors.checks",
|
as: "monitors.checks",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "monitorstats",
|
||||||
|
localField: "monitors._id",
|
||||||
|
foreignField: "monitorId",
|
||||||
|
as: "monitors.stats",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
$addFields: {
|
$addFields: {
|
||||||
"monitors.orderIndex": {
|
"monitors.orderIndex": {
|
||||||
@@ -181,6 +189,9 @@ class StatusPageModule {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"monitors.uptimePercentage": {
|
||||||
|
$arrayElemAt: ["$monitors.stats.uptimePercentage", 0],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ $match: { "monitors.orderIndex": { $ne: -1 } } },
|
{ $match: { "monitors.orderIndex": { $ne: -1 } } },
|
||||||
|
|||||||
@@ -149,10 +149,12 @@
|
|||||||
"statusPageByTeamId": "Got status pages by team id successfully",
|
"statusPageByTeamId": "Got status pages by team id successfully",
|
||||||
"httpNetworkError": "Network error",
|
"httpNetworkError": "Network error",
|
||||||
"httpNotJson": "Response data is not json",
|
"httpNotJson": "Response data is not json",
|
||||||
|
"httpExpectedValueFail": "Expected value did not match",
|
||||||
"httpJsonPathError": "Failed to parse json data",
|
"httpJsonPathError": "Failed to parse json data",
|
||||||
"httpEmptyResult": "Result is empty",
|
"httpEmptyResult": "Result is empty",
|
||||||
"httpMatchSuccess": "Response data match successfully",
|
"httpMatchSuccess": "Response data match successfully",
|
||||||
"httpMatchFail": "Failed to match response data",
|
"httpMatchFail": "Failed to match response data",
|
||||||
|
"httpJsonPathFail": "JSONPath did not match expected value",
|
||||||
"webhookSendSuccess": "Webhook notification sent successfully",
|
"webhookSendSuccess": "Webhook notification sent successfully",
|
||||||
"telegramRequiresBotTokenAndChatId": "Telegram notifications require both botToken and chatId",
|
"telegramRequiresBotTokenAndChatId": "Telegram notifications require both botToken and chatId",
|
||||||
"webhookUrlRequired": "Webhook URL is required",
|
"webhookUrlRequired": "Webhook URL is required",
|
||||||
@@ -162,5 +164,18 @@
|
|||||||
"monitorDownAlert": "Downtime Alert: One of your monitors went offline.\n📌 Monitor: {monitorName}\n📅 Time: {time}\n⚠️ Status: DOWN\n📟 Status Code: {code}\n\u200B\n",
|
"monitorDownAlert": "Downtime Alert: One of your monitors went offline.\n📌 Monitor: {monitorName}\n📅 Time: {time}\n⚠️ Status: DOWN\n📟 Status Code: {code}\n\u200B\n",
|
||||||
"sendTestEmail": "Test email sent successfully",
|
"sendTestEmail": "Test email sent successfully",
|
||||||
"errorForValidEmailAddress": "A valid recipient email address is required.",
|
"errorForValidEmailAddress": "A valid recipient email address is required.",
|
||||||
"testEmailSubject": "Test E-mail from Checkmate"
|
"testEmailSubject": "Test E-mail from Checkmate",
|
||||||
|
"discordNotification": {
|
||||||
|
"monitor": "Monitor",
|
||||||
|
"status": "Status",
|
||||||
|
"statusCode": "Status Code",
|
||||||
|
"time": "Time",
|
||||||
|
"up": "UP",
|
||||||
|
"down": "DOWN",
|
||||||
|
"checkmate": "Checkmate",
|
||||||
|
"url": "URL",
|
||||||
|
"unknown": "Unknown",
|
||||||
|
"uptimeAlert": "Uptime Alert: One of your monitors is back online",
|
||||||
|
"downtimeAlert": "Downtime Alert: One of your monitors went offline"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ class SuperSimpleQueue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateJob = async (monitor) => {
|
updateJob = async (monitor) => {
|
||||||
this.scheduler.updateJob(monitor._id.toString(), monitor.interval);
|
this.scheduler.updateJob(monitor._id.toString(), { repeat: monitor.interval, data: monitor.toObject() });
|
||||||
};
|
};
|
||||||
|
|
||||||
shutdown = async () => {
|
shutdown = async () => {
|
||||||
@@ -141,6 +141,7 @@ class SuperSimpleQueue {
|
|||||||
monitorId: job.id,
|
monitorId: job.id,
|
||||||
monitorUrl: job?.data?.url || null,
|
monitorUrl: job?.data?.url || null,
|
||||||
monitorType: job?.data?.type || null,
|
monitorType: job?.data?.type || null,
|
||||||
|
monitorInterval: job?.data?.interval || null,
|
||||||
active: job.active,
|
active: job.active,
|
||||||
lockedAt: job.lockedAt,
|
lockedAt: job.lockedAt,
|
||||||
runCount: job.runCount || 0,
|
runCount: job.runCount || 0,
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ class SuperSimpleQueueHelper {
|
|||||||
return async (monitor) => {
|
return async (monitor) => {
|
||||||
try {
|
try {
|
||||||
const monitorId = monitor._id;
|
const monitorId = monitor._id;
|
||||||
|
const teamId = monitor.teamId;
|
||||||
if (!monitorId) {
|
if (!monitorId) {
|
||||||
throw new Error("No monitor id");
|
throw new Error("No monitor id");
|
||||||
}
|
}
|
||||||
|
|
||||||
const maintenanceWindowActive = await this.isInMaintenanceWindow(monitorId);
|
const maintenanceWindowActive = await this.isInMaintenanceWindow(monitorId, teamId);
|
||||||
if (maintenanceWindowActive) {
|
if (maintenanceWindowActive) {
|
||||||
this.logger.info({
|
this.logger.info({
|
||||||
message: `Monitor ${monitorId} is in maintenance window`,
|
message: `Monitor ${monitorId} is in maintenance window`,
|
||||||
@@ -77,8 +78,11 @@ class SuperSimpleQueueHelper {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
async isInMaintenanceWindow(monitorId) {
|
async isInMaintenanceWindow(monitorId, teamId) {
|
||||||
const maintenanceWindows = await this.db.maintenanceWindowModule.getMaintenanceWindowsByMonitorId(monitorId);
|
const maintenanceWindows = await this.db.maintenanceWindowModule.getMaintenanceWindowsByMonitorId({
|
||||||
|
monitorId: monitorId.toString(),
|
||||||
|
teamId: teamId.toString(),
|
||||||
|
});
|
||||||
// Check for active maintenance window:
|
// Check for active maintenance window:
|
||||||
const maintenanceWindowIsActive = maintenanceWindows.reduce((acc, window) => {
|
const maintenanceWindowIsActive = maintenanceWindows.reduce((acc, window) => {
|
||||||
if (window.active) {
|
if (window.active) {
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ class NetworkService {
|
|||||||
const { response, responseTime, error } = await this.timeRequest(() => this.ping.promise.probe(monitor.url));
|
const { response, responseTime, error } = await this.timeRequest(() => this.ping.promise.probe(monitor.url));
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
throw new Error("Ping failed - no result returned");
|
throw new Error("Ping failed - no result returned");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +105,7 @@ class NetworkService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async requestHttp(monitor) {
|
async requestHttp(monitor) {
|
||||||
const { url, secret, _id, name, teamId, type, ignoreTlsErrors, jsonPath, matchMethod, expectedValue } = monitor;
|
const { url, secret, _id, teamId, type, ignoreTlsErrors, jsonPath, matchMethod, expectedValue } = monitor;
|
||||||
const httpResponse = {
|
const httpResponse = {
|
||||||
monitorId: _id,
|
monitorId: _id,
|
||||||
teamId: teamId,
|
teamId: teamId,
|
||||||
@@ -147,29 +150,65 @@ class NetworkService {
|
|||||||
httpResponse.payload = payload;
|
httpResponse.payload = payload;
|
||||||
httpResponse.timings = response.timings || {};
|
httpResponse.timings = response.timings || {};
|
||||||
|
|
||||||
if (!expectedValue) {
|
if (!expectedValue && !jsonPath) {
|
||||||
return httpResponse;
|
return httpResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.info({
|
if (expectedValue && !jsonPath) {
|
||||||
service: this.SERVICE_NAME,
|
let ok = false;
|
||||||
method: "requestHttp",
|
if (matchMethod === "equal") ok = payload === expectedValue;
|
||||||
message: `Job: [${name}](${_id}) match result with expected value`,
|
if (matchMethod === "include" && typeof payload === "string") ok = payload.includes(expectedValue);
|
||||||
details: { expectedValue, payload, jsonPath, matchMethod },
|
if (matchMethod === "regex" && typeof payload === "string") ok = new RegExp(expectedValue).test(payload);
|
||||||
});
|
|
||||||
|
if (ok === true) {
|
||||||
|
return httpResponse;
|
||||||
|
} else {
|
||||||
|
httpResponse.code = 500;
|
||||||
|
httpResponse.status = false;
|
||||||
|
httpResponse.message = this.stringService.httpExpectedValueFail;
|
||||||
|
return httpResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (jsonPath) {
|
if (jsonPath) {
|
||||||
const contentType = response.headers["content-type"];
|
const contentType = response.headers["content-type"];
|
||||||
|
|
||||||
const isJson = contentType?.includes("application/json");
|
const isJson = contentType?.includes("application/json");
|
||||||
if (!isJson) {
|
if (!isJson) {
|
||||||
httpResponse.status = false;
|
httpResponse.status = false;
|
||||||
httpResponse.message = this.stringService.httpNotJson;
|
httpResponse.message = this.stringService.httpNotJson;
|
||||||
return httpResponse;
|
return httpResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.jmespath.search(payload, jsonPath);
|
const extracted = this.jmespath.search(payload, jsonPath);
|
||||||
|
if (expectedValue) {
|
||||||
|
let ok = false;
|
||||||
|
if (matchMethod === "equal") ok = extracted === expectedValue;
|
||||||
|
if (matchMethod === "include" && typeof extracted === "string") ok = extracted.includes(expectedValue);
|
||||||
|
if (matchMethod === "regex" && typeof extracted === "string") ok = new RegExp(expectedValue).test(extracted);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
httpResponse.extracted = extracted;
|
||||||
|
return httpResponse;
|
||||||
|
} else {
|
||||||
|
httpResponse.status = false;
|
||||||
|
httpResponse.code = 500;
|
||||||
|
httpResponse.message = this.stringService.httpJsonPathFail;
|
||||||
|
httpResponse.extracted = extracted;
|
||||||
|
return httpResponse;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const isFalsey = extracted === false || extracted === "false" || extracted === undefined || extracted === null;
|
||||||
|
if (!isFalsey) {
|
||||||
|
httpResponse.extracted = extracted;
|
||||||
|
return httpResponse;
|
||||||
|
} else {
|
||||||
|
httpResponse.status = false;
|
||||||
|
httpResponse.code = 500;
|
||||||
|
httpResponse.message = this.stringService.httpJsonPathFail;
|
||||||
|
httpResponse.extracted = extracted;
|
||||||
|
return httpResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
httpResponse.status = false;
|
httpResponse.status = false;
|
||||||
httpResponse.message = this.stringService.httpJsonPathError;
|
httpResponse.message = this.stringService.httpJsonPathError;
|
||||||
@@ -243,24 +282,76 @@ class NetworkService {
|
|||||||
handleError: true, // Enable error handling
|
handleError: true, // Enable error handling
|
||||||
});
|
});
|
||||||
|
|
||||||
const containers = await docker.listContainers({ all: true });
|
|
||||||
const containerExists = containers.some((c) => c.Id.startsWith(monitor.url));
|
|
||||||
if (!containerExists) {
|
|
||||||
throw new Error(this.stringService.dockerNotFound);
|
|
||||||
}
|
|
||||||
|
|
||||||
const container = docker.getContainer(monitor.url);
|
|
||||||
const { response, responseTime, error } = await this.timeRequest(() => container.inspect());
|
|
||||||
|
|
||||||
const dockerResponse = {
|
const dockerResponse = {
|
||||||
monitorId: monitor._id,
|
monitorId: monitor._id,
|
||||||
type: monitor.type,
|
type: monitor.type,
|
||||||
responseTime,
|
|
||||||
status: response?.State?.Status === "running" ? true : false,
|
|
||||||
code: 200,
|
|
||||||
message: "Docker container status fetched successfully",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const containers = await docker.listContainers({ all: true });
|
||||||
|
|
||||||
|
// Normalize input: strip leading slashes and convert to lowercase for comparison
|
||||||
|
const normalizedInput = monitor.url.replace(/^\/+/, "").toLowerCase();
|
||||||
|
|
||||||
|
// Priority-based matching to avoid ambiguity:
|
||||||
|
// 1. Exact full ID match (64-char)
|
||||||
|
let exactIdMatch = containers.find((c) => c.Id.toLowerCase() === normalizedInput);
|
||||||
|
|
||||||
|
// 2. Exact container name match (case-insensitive)
|
||||||
|
let exactNameMatch = containers.find((c) =>
|
||||||
|
c.Names.some((name) => {
|
||||||
|
const cleanName = name.replace(/^\/+/, "").toLowerCase();
|
||||||
|
return cleanName === normalizedInput;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Partial ID match (fallback for backwards compatibility)
|
||||||
|
let partialIdMatch = containers.find((c) => c.Id.toLowerCase().startsWith(normalizedInput));
|
||||||
|
|
||||||
|
// Select container based on priority
|
||||||
|
let targetContainer = exactIdMatch || exactNameMatch || partialIdMatch;
|
||||||
|
|
||||||
|
// Return negative response if no container
|
||||||
|
if (!targetContainer) {
|
||||||
|
this.logger.warn({
|
||||||
|
message: `No container found for "${monitor.url}".`,
|
||||||
|
service: this.SERVICE_NAME,
|
||||||
|
method: "requestDocker",
|
||||||
|
details: { url: monitor.url },
|
||||||
|
});
|
||||||
|
|
||||||
|
dockerResponse.code = 404;
|
||||||
|
dockerResponse.status = false;
|
||||||
|
dockerResponse.message = this.stringService.dockerNotFound;
|
||||||
|
return dockerResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return negative response if ambiguous matches exist
|
||||||
|
const matchTypes = [];
|
||||||
|
if (exactIdMatch) matchTypes.push("exact ID");
|
||||||
|
if (exactNameMatch) matchTypes.push("exact name");
|
||||||
|
if (partialIdMatch && !exactIdMatch) matchTypes.push("partial ID");
|
||||||
|
|
||||||
|
if (matchTypes.length > 1) {
|
||||||
|
this.logger.warn({
|
||||||
|
message: `Ambiguous container match for "${monitor.url}". Matched by: ${matchTypes.join(", ")}. Using ${exactIdMatch ? "exact ID" : exactNameMatch ? "exact name" : "partial ID"} match.`,
|
||||||
|
service: this.SERVICE_NAME,
|
||||||
|
method: "requestDocker",
|
||||||
|
details: { url: monitor.url },
|
||||||
|
});
|
||||||
|
dockerResponse.status = 404;
|
||||||
|
dockerResponse.status = false;
|
||||||
|
dockerResponse.message = `Ambiguous container match for "${monitor.url}". Matched by: ${matchTypes.join(", ")}. Using ${exactIdMatch ? "exact ID" : exactNameMatch ? "exact name" : "partial ID"} match.`;
|
||||||
|
return dockerResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = docker.getContainer(targetContainer.Id);
|
||||||
|
const { response, responseTime, error } = await this.timeRequest(() => container.inspect());
|
||||||
|
|
||||||
|
dockerResponse.responseTime = responseTime;
|
||||||
|
dockerResponse.status = response?.State?.Status === "running" ? true : false;
|
||||||
|
dockerResponse.code = 200;
|
||||||
|
dockerResponse.message = "Docker container status fetched successfully";
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dockerResponse.status = false;
|
dockerResponse.status = false;
|
||||||
dockerResponse.code = error.statusCode || this.NETWORK_ERROR;
|
dockerResponse.code = error.statusCode || this.NETWORK_ERROR;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class NotificationService {
|
|||||||
return NotificationService.SERVICE_NAME;
|
return NotificationService.SERVICE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendNotification = async ({ notification, subject, content, html }) => {
|
sendNotification = async ({ notification, subject, content, html, discordContent = null, webhookBody = null }) => {
|
||||||
const { type, address } = notification;
|
const { type, address } = notification;
|
||||||
|
|
||||||
if (type === "email") {
|
if (type === "email") {
|
||||||
@@ -28,9 +28,11 @@ class NotificationService {
|
|||||||
// Create a body for webhooks
|
// Create a body for webhooks
|
||||||
let body = { text: content };
|
let body = { text: content };
|
||||||
if (type === "discord") {
|
if (type === "discord") {
|
||||||
body = { content };
|
body = !discordContent ? { content } : discordContent;
|
||||||
|
}
|
||||||
|
if (type === "webhook") {
|
||||||
|
body = !webhookBody ? { content } : webhookBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === "slack" || type === "discord" || type === "webhook") {
|
if (type === "slack" || type === "discord" || type === "webhook") {
|
||||||
const response = await this.networkService.requestWebhook(type, address, body);
|
const response = await this.networkService.requestWebhook(type, address, body);
|
||||||
return response.status;
|
return response.status;
|
||||||
@@ -55,7 +57,6 @@ class NotificationService {
|
|||||||
|
|
||||||
const notificationIDs = networkResponse.monitor?.notifications ?? [];
|
const notificationIDs = networkResponse.monitor?.notifications ?? [];
|
||||||
if (notificationIDs.length === 0) return false;
|
if (notificationIDs.length === 0) return false;
|
||||||
|
|
||||||
if (networkResponse.monitor.type === "hardware") {
|
if (networkResponse.monitor.type === "hardware") {
|
||||||
const thresholds = networkResponse?.monitor?.thresholds;
|
const thresholds = networkResponse?.monitor?.thresholds;
|
||||||
|
|
||||||
@@ -63,30 +64,29 @@ class NotificationService {
|
|||||||
const metrics = networkResponse?.payload?.data ?? null;
|
const metrics = networkResponse?.payload?.data ?? null;
|
||||||
if (metrics === null) return false; // No metrics, we're done
|
if (metrics === null) return false; // No metrics, we're done
|
||||||
|
|
||||||
const alerts = await this.notificationUtils.buildHardwareAlerts(networkResponse);
|
const [alerts, discordContent] = await this.notificationUtils.buildHardwareAlerts(networkResponse);
|
||||||
if (alerts.length === 0) return false;
|
if (alerts.length === 0) return false;
|
||||||
|
|
||||||
const { subject, html } = await this.notificationUtils.buildHardwareEmail(networkResponse, alerts);
|
const { subject, html } = await this.notificationUtils.buildHardwareEmail(networkResponse, alerts);
|
||||||
const content = await this.notificationUtils.buildHardwareNotificationMessage(alerts);
|
const content = await this.notificationUtils.buildHardwareNotificationMessage(alerts, monitor);
|
||||||
|
const webhookBody = await this.notificationUtils.buildHardwareWebhookBody(alerts, monitor);
|
||||||
const success = await this.notifyAll({ notificationIDs, subject, html, content });
|
const success = await this.notifyAll({ notificationIDs, subject, html, content, discordContent, webhookBody });
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status monitors
|
// Status monitors
|
||||||
const { subject, html } = await this.notificationUtils.buildStatusEmail(networkResponse);
|
const { subject, html } = await this.notificationUtils.buildStatusEmail(networkResponse);
|
||||||
const content = await this.notificationUtils.buildWebhookMessage(networkResponse);
|
const [content, discordContent] = await this.notificationUtils.buildWebhookMessage(networkResponse);
|
||||||
const success = this.notifyAll({ notificationIDs, subject, html, content });
|
const success = this.notifyAll({ notificationIDs, subject, html, content, discordContent });
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
async notifyAll({ notificationIDs, subject, html, content }) {
|
async notifyAll({ notificationIDs, subject, html, content, discordContent = null, webhookBody = null }) {
|
||||||
const notifications = await this.db.notificationModule.getNotificationsByIds(notificationIDs);
|
const notifications = await this.db.notificationModule.getNotificationsByIds(notificationIDs);
|
||||||
|
|
||||||
// Map each notification to a test promise
|
// Map each notification to a test promise
|
||||||
const promises = notifications.map(async (notification) => {
|
const promises = notifications.map(async (notification) => {
|
||||||
try {
|
try {
|
||||||
await this.sendNotification({ notification, subject, content, html });
|
await this.sendNotification({ notification, subject, content, html, discordContent, webhookBody });
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -70,7 +70,25 @@ class NotificationUtils {
|
|||||||
.replace("{time}", formattedTime)
|
.replace("{time}", formattedTime)
|
||||||
.replace("{code}", code || "Unknown");
|
.replace("{code}", code || "Unknown");
|
||||||
}
|
}
|
||||||
return messageText;
|
const dn = this.stringService.discordNotification;
|
||||||
|
let discordMessageText = {
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
title: status ? dn.uptimeAlert : dn.downtimeAlert,
|
||||||
|
color: status ? 5763719 : 15548997,
|
||||||
|
|
||||||
|
fields: [
|
||||||
|
{ name: dn.monitor, value: monitor?.name ?? dn.unknown, inline: true },
|
||||||
|
{ name: dn.status, value: status ? dn.up : dn.down, inline: true },
|
||||||
|
{ name: dn.statusCode, value: String(code ?? dn.unknown), inline: true },
|
||||||
|
{ name: dn.time, value: formattedTime, inline: true },
|
||||||
|
{ name: dn.url, value: monitor?.url ?? dn.unknown, inline: false },
|
||||||
|
],
|
||||||
|
footer: { text: dn.checkmate },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return [messageText, discordMessageText];
|
||||||
};
|
};
|
||||||
|
|
||||||
buildHardwareAlerts = async (networkResponse) => {
|
buildHardwareAlerts = async (networkResponse) => {
|
||||||
@@ -88,6 +106,43 @@ class NotificationUtils {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const alertsToSend = [];
|
const alertsToSend = [];
|
||||||
|
const discordEmbeds = [];
|
||||||
|
const monitorInfoFields = [
|
||||||
|
{ name: "Monitor", value: monitor.name, inline: true },
|
||||||
|
{ name: "URL", value: monitor.url, inline: false },
|
||||||
|
];
|
||||||
|
const formatDiscordAlert = {
|
||||||
|
cpu: () => ({
|
||||||
|
title: "CPU alert",
|
||||||
|
description: `Your current CPU usage (${(cpuUsage * 100).toFixed(0)}%) is above your threshold (${(cpuThreshold * 100).toFixed(0)}%)`,
|
||||||
|
color: 15548997,
|
||||||
|
fields: monitorInfoFields,
|
||||||
|
footer: { text: "Checkmate" },
|
||||||
|
}),
|
||||||
|
|
||||||
|
memory: () => ({
|
||||||
|
title: "Memory alert",
|
||||||
|
description: `Your current memory usage (${(memoryUsage * 100).toFixed(0)}%) is above your threshold (${(memoryThreshold * 100).toFixed(0)}%)`,
|
||||||
|
color: 15548997,
|
||||||
|
fields: monitorInfoFields,
|
||||||
|
footer: { text: "Checkmate" },
|
||||||
|
}),
|
||||||
|
|
||||||
|
disk: () => ({
|
||||||
|
title: "Disk alert",
|
||||||
|
description: `Your current disk usage is above your threshold (${(diskThreshold * 100).toFixed(0)}%)`,
|
||||||
|
color: 15548997,
|
||||||
|
footer: { text: "Checkmate" },
|
||||||
|
fields: [
|
||||||
|
...monitorInfoFields,
|
||||||
|
...(Array.isArray(disk) ? disk : []).map((d, idx) => ({
|
||||||
|
name: `Disk ${idx}`,
|
||||||
|
value: `${(d?.usage_percent * 100).toFixed(0)}%`,
|
||||||
|
inline: true,
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
};
|
||||||
const alertTypes = ["cpu", "memory", "disk"];
|
const alertTypes = ["cpu", "memory", "disk"];
|
||||||
for (const type of alertTypes) {
|
for (const type of alertTypes) {
|
||||||
// Iterate over each alert type to see if any need to be decremented
|
// Iterate over each alert type to see if any need to be decremented
|
||||||
@@ -108,11 +163,13 @@ class NotificationUtils {
|
|||||||
.join(", ")} is above your threshold (${(diskThreshold * 100).toFixed(0)}%)`,
|
.join(", ")} is above your threshold (${(diskThreshold * 100).toFixed(0)}%)`,
|
||||||
};
|
};
|
||||||
alertsToSend.push(formatAlert[type]());
|
alertsToSend.push(formatAlert[type]());
|
||||||
|
discordEmbeds.push(formatDiscordAlert[type]());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await monitor.save();
|
await monitor.save();
|
||||||
return alertsToSend;
|
const discordPayload = discordEmbeds.length ? { embeds: discordEmbeds } : null;
|
||||||
|
return [alertsToSend, discordPayload];
|
||||||
};
|
};
|
||||||
|
|
||||||
buildHardwareEmail = async (networkResponse, alerts) => {
|
buildHardwareEmail = async (networkResponse, alerts) => {
|
||||||
@@ -124,8 +181,15 @@ class NotificationUtils {
|
|||||||
return { subject, html };
|
return { subject, html };
|
||||||
};
|
};
|
||||||
|
|
||||||
buildHardwareNotificationMessage = (alerts) => {
|
buildHardwareNotificationMessage = (alerts, monitor) => {
|
||||||
return alerts.map((alert) => alert).join("\n");
|
const alertsHeader = [`Monitor: ${monitor.name}`, `URL: ${monitor.url}`];
|
||||||
|
const alertText = alerts.length > 0 ? [...alertsHeader, ...alerts] : [];
|
||||||
|
return alertText.map((alert) => alert).join("\n");
|
||||||
|
};
|
||||||
|
buildHardwareWebhookBody = (alerts, monitor) => {
|
||||||
|
const content = alerts.map((alert) => alert).join("\n");
|
||||||
|
const body = { text: content, name: monitor.name, url: monitor.url };
|
||||||
|
return body;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ class StatusService {
|
|||||||
statusChanged = true;
|
statusChanged = true;
|
||||||
}
|
}
|
||||||
// If the failure rate is below the threshold and the monitor is down, recover:
|
// If the failure rate is below the threshold and the monitor is down, recover:
|
||||||
else if (failureRate <= monitor.statusWindowThreshold && monitor.status === false) {
|
else if (failureRate < monitor.statusWindowThreshold && monitor.status === false) {
|
||||||
newStatus = true;
|
newStatus = true;
|
||||||
statusChanged = true;
|
statusChanged = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,10 @@ class StringService {
|
|||||||
return this.translationService.getTranslation("monitorDownAlert");
|
return this.translationService.getTranslation("monitorDownAlert");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get discordNotification() {
|
||||||
|
return this.translationService.getTranslation("discordNotification");
|
||||||
|
}
|
||||||
|
|
||||||
getWebhookUnsupportedPlatform(platform) {
|
getWebhookUnsupportedPlatform(platform) {
|
||||||
return this.translationService.getTranslation("webhookUnsupportedPlatform").replace("{platform}", platform);
|
return this.translationService.getTranslation("webhookUnsupportedPlatform").replace("{platform}", platform);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user