mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-07 09:35:54 -08:00
Compare commits
368 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc7e73eba2 | ||
|
|
14b886793c | ||
|
|
c460b7594f | ||
|
|
6cfb150c9a | ||
|
|
f107481da2 | ||
|
|
96891e3205 | ||
|
|
582f916379 | ||
|
|
b4d12cad9d | ||
|
|
2c9225cde2 | ||
|
|
26715edbd0 | ||
|
|
4a11c34db6 | ||
|
|
de3ff0b3ba | ||
|
|
338715fe58 | ||
|
|
8dbe0d7fe1 | ||
|
|
f63d9ea7c1 | ||
|
|
00b590ed2a | ||
|
|
e72d58a382 | ||
|
|
ad87faa7ed | ||
|
|
fc41d144f6 | ||
|
|
6c64295505 | ||
|
|
ebd48e4081 | ||
|
|
71439eb689 | ||
|
|
9c33a30fb1 | ||
|
|
f8e1207abc | ||
|
|
93f2bc7773 | ||
|
|
04f947b920 | ||
|
|
d1ebfde45c | ||
|
|
b22fdb42f4 | ||
|
|
c79d57775f | ||
|
|
caaf6c86ba | ||
|
|
9484e9f963 | ||
|
|
2d13648e01 | ||
|
|
2ddddf5cfe | ||
|
|
9086fcadc9 | ||
|
|
4502dba6ca | ||
|
|
92d1ad2d9d | ||
|
|
eb15ab054f | ||
|
|
1047da8e23 | ||
|
|
69ded4bd2f | ||
|
|
6898ed3676 | ||
|
|
e12184863a | ||
|
|
81f2906ae7 | ||
|
|
84296e573f | ||
|
|
4b4c63d562 | ||
|
|
1faaa1466a | ||
|
|
3a75fbb77d | ||
|
|
ad586f3853 | ||
|
|
5800957ec1 | ||
|
|
a58eabdb9b | ||
|
|
7cede1318e | ||
|
|
a234eeffb1 | ||
|
|
38bb974c64 | ||
|
|
0976c21fa4 | ||
|
|
a4c046c3e1 | ||
|
|
eb67cf1d6f | ||
|
|
fb04972701 | ||
|
|
4a80b32bb6 | ||
|
|
d00d9ffee3 | ||
|
|
c0af877e91 | ||
|
|
f8586a9df6 | ||
|
|
8cc19daf24 | ||
|
|
9f57f45816 | ||
|
|
a11df88d8a | ||
|
|
ff81233772 | ||
|
|
7cec116b11 | ||
|
|
4dc84201a0 | ||
|
|
9abdcc56a0 | ||
|
|
5b5fc60a0c | ||
|
|
63b59c3964 | ||
|
|
15d30abc93 | ||
|
|
a7d73828e6 | ||
|
|
749d039896 | ||
|
|
651243cd9f | ||
|
|
b5ae79e1d3 | ||
|
|
5d81b56189 | ||
|
|
c7c600b47d | ||
|
|
8907a9cecf | ||
|
|
529927bc8b | ||
|
|
f27f7b3fa6 | ||
|
|
a755a0ae83 | ||
|
|
0d1a7f1717 | ||
|
|
ebf036c241 | ||
|
|
3fd83f9f2d | ||
|
|
67d64264bc | ||
|
|
69e187f574 | ||
|
|
83e27aa41a | ||
|
|
37b6aba1d4 | ||
|
|
33d4b4d43d | ||
|
|
4e230fb76a | ||
|
|
04ac922cfe | ||
|
|
59c22820c0 | ||
|
|
f463f99cbe | ||
|
|
1e27da0024 | ||
|
|
bc9e331ac5 | ||
|
|
f7f1aa88b1 | ||
|
|
da3541cafe | ||
|
|
a6dac34b24 | ||
|
|
7bd433922f | ||
|
|
deaacc3b05 | ||
|
|
2e4808db63 | ||
|
|
b033869345 | ||
|
|
b56de26a2f | ||
|
|
6bc9c4d861 | ||
|
|
78622d368e | ||
|
|
491bf0f3a9 | ||
|
|
ea1435cd87 | ||
|
|
f25f834809 | ||
|
|
7d66b5c895 | ||
|
|
0dc473909e | ||
|
|
d54230745b | ||
|
|
c4cbd870d1 | ||
|
|
8229d28c41 | ||
|
|
861f726079 | ||
|
|
0065311f33 | ||
|
|
de064fd883 | ||
|
|
f93d66dc44 | ||
|
|
24ed90f3a6 | ||
|
|
727a4f41f1 | ||
|
|
b1e8bbfb56 | ||
|
|
702b8683c0 | ||
|
|
3ee96372fd | ||
|
|
c405cfe574 | ||
|
|
4906d21c84 | ||
|
|
a650f7689d | ||
|
|
6410fcbaa2 | ||
|
|
aa31922681 | ||
|
|
1cb0012a5a | ||
|
|
9a7a2f25f2 | ||
|
|
a201e0fb7f | ||
|
|
0913ef74c2 | ||
|
|
96e887fa25 | ||
|
|
36b95e68ce | ||
|
|
3d2905b63c | ||
|
|
375011bbea | ||
|
|
56bd321f03 | ||
|
|
b07fd98fc6 | ||
|
|
6744ef49c9 | ||
|
|
25672a0147 | ||
|
|
4c49767a0f | ||
|
|
bb8ad4747c | ||
|
|
80f26676d7 | ||
|
|
70b4f4e1e6 | ||
|
|
dce89f0c01 | ||
|
|
5b5e561c3c | ||
|
|
31aff205e0 | ||
|
|
1136d7d2cb | ||
|
|
74a2245c29 | ||
|
|
0e1a41fdd1 | ||
|
|
7a51b62e43 | ||
|
|
75ecf3eba5 | ||
|
|
f18146063f | ||
|
|
0af60d06c2 | ||
|
|
1f00b3828b | ||
|
|
9e96738487 | ||
|
|
d2fb93f7e9 | ||
|
|
7834f2fecb | ||
|
|
9cd25d541f | ||
|
|
95707d527f | ||
|
|
b64bcdb817 | ||
|
|
4cc113697c | ||
|
|
65115cf6dc | ||
|
|
1af888934e | ||
|
|
7281f6d3a1 | ||
|
|
804b69d5a6 | ||
|
|
4cb18f7129 | ||
|
|
7558a24242 | ||
|
|
e17f594101 | ||
|
|
ed6000262d | ||
|
|
f2900ac859 | ||
|
|
e9c5aa13de | ||
|
|
ede5a53b7f | ||
|
|
11fa395b76 | ||
|
|
63bc0c971e | ||
|
|
6712219d59 | ||
|
|
dbfd92b643 | ||
|
|
c30f2ec4ca | ||
|
|
ff620cebf1 | ||
|
|
73c30cc3b5 | ||
|
|
6eb8d6a93d | ||
|
|
5786b8b895 | ||
|
|
1015005086 | ||
|
|
51db779007 | ||
|
|
eb06eaf292 | ||
|
|
46d34040af | ||
|
|
e567d6b6b6 | ||
|
|
70ffe63e59 | ||
|
|
39a94190cf | ||
|
|
a8dfdcdac0 | ||
|
|
5dcfd555cb | ||
|
|
583494f27a | ||
|
|
af43b62e2f | ||
|
|
dfb1e25877 | ||
|
|
5765d48bba | ||
|
|
15f1d0ecd2 | ||
|
|
2da13e3cd4 | ||
|
|
32b139a436 | ||
|
|
8b6f174c51 | ||
|
|
33b0aefd8a | ||
|
|
d8bd19d997 | ||
|
|
6cfd08bb85 | ||
|
|
deaf49ce8b | ||
|
|
4cafb8decd | ||
|
|
a4cc538388 | ||
|
|
828c52d90a | ||
|
|
52bf9718ca | ||
|
|
48bd6e8436 | ||
|
|
5e9d2d8439 | ||
|
|
08dbd59f1b | ||
|
|
b1706e79be | ||
|
|
62c914c57e | ||
|
|
d55e328c90 | ||
|
|
f80e7c4f25 | ||
|
|
0d38cbae8e | ||
|
|
6e5f15b6ec | ||
|
|
6f6f06ed38 | ||
|
|
7a930d2173 | ||
|
|
d71e316b5d | ||
|
|
63f8e1e5b1 | ||
|
|
c542ca1d0c | ||
|
|
3f3f315e19 | ||
|
|
9f632c58fc | ||
|
|
7e0ed2b8a7 | ||
|
|
22a2649b6e | ||
|
|
2ea780435a | ||
|
|
7174b0ab24 | ||
|
|
112d1e77b9 | ||
|
|
f89cccf209 | ||
|
|
41b1589347 | ||
|
|
4896cc9457 | ||
|
|
b9d523f0c4 | ||
|
|
d1a8523630 | ||
|
|
46b2fc029d | ||
|
|
f2f199124f | ||
|
|
8d6f3b82f3 | ||
|
|
b0f29709c2 | ||
|
|
bf8c10bb61 | ||
|
|
dc19ce4d38 | ||
|
|
3b1c9a69a4 | ||
|
|
5c25279439 | ||
|
|
19bf7a0e5a | ||
|
|
9a3eb5a2b3 | ||
|
|
58f4cf6edd | ||
|
|
63d4c6bdf8 | ||
|
|
369031a5e1 | ||
|
|
3bf59245a6 | ||
|
|
ef04ae8abe | ||
|
|
64c0e9909d | ||
|
|
2e6a146cb6 | ||
|
|
a605b64d18 | ||
|
|
747cc147cb | ||
|
|
3986634e0d | ||
|
|
022dff6b99 | ||
|
|
828d1a5a3a | ||
|
|
1b629aed4f | ||
|
|
77eaf00c06 | ||
|
|
247d46bbbc | ||
|
|
7f8782732d | ||
|
|
ffae7e1058 | ||
|
|
6414b7c61d | ||
|
|
a0b6a90042 | ||
|
|
b6141c7235 | ||
|
|
719f6c8a3a | ||
|
|
6d22e1b283 | ||
|
|
64025ddb1b | ||
|
|
338a9da697 | ||
|
|
af9dc9311c | ||
|
|
b63977a129 | ||
|
|
8058736918 | ||
|
|
e805ed2e88 | ||
|
|
3ebc302f02 | ||
|
|
61cb50e12a | ||
|
|
56c1627c7e | ||
|
|
d41abd7126 | ||
|
|
781dc4b02c | ||
|
|
fa78735f12 | ||
|
|
a6dc7db96e | ||
|
|
ab8e4e21a1 | ||
|
|
ae124e49b3 | ||
|
|
e4c7a90d14 | ||
|
|
db6b5bb175 | ||
|
|
a96e875944 | ||
|
|
b0ae89c4ba | ||
|
|
3802b54593 | ||
|
|
f2fdd77f96 | ||
|
|
75ae5a9cf1 | ||
|
|
715ceed97b | ||
|
|
1db38e5ca2 | ||
|
|
70ea5ad60d | ||
|
|
12736cc003 | ||
|
|
5611baa0b8 | ||
|
|
f8c382c480 | ||
|
|
ba19f77b8f | ||
|
|
167ecb42de | ||
|
|
15bf55952b | ||
|
|
0f8f5e15a3 | ||
|
|
33e3603d26 | ||
|
|
63a56225bb | ||
|
|
952c72a3a5 | ||
|
|
552f2c4a98 | ||
|
|
ec165b8c74 | ||
|
|
cf05a85ad6 | ||
|
|
69d828ec8e | ||
|
|
b6072200a2 | ||
|
|
fab975062d | ||
|
|
5f01196b21 | ||
|
|
2faaaf5a9c | ||
|
|
8d91aeaf9d | ||
|
|
2609694dd7 | ||
|
|
9c5521ba35 | ||
|
|
6ae351b2ba | ||
|
|
7116b093cb | ||
|
|
c5aa89e533 | ||
|
|
69b660b829 | ||
|
|
ceca1d8ae7 | ||
|
|
1369a356a8 | ||
|
|
a6014d3d06 | ||
|
|
5de0f4f61e | ||
|
|
1371767481 | ||
|
|
8534fcfa58 | ||
|
|
0bc8d74694 | ||
|
|
11b2bd6db1 | ||
|
|
3b943cabed | ||
|
|
5a14917aa7 | ||
|
|
7583b3dfd1 | ||
|
|
ec61e2dd23 | ||
|
|
5bda68d51d | ||
|
|
c75e3cdf40 | ||
|
|
2029df1ed0 | ||
|
|
eb475e8655 | ||
|
|
bfada0f5f3 | ||
|
|
6e33e62540 | ||
|
|
b6ff3da1f0 | ||
|
|
ae14158f35 | ||
|
|
149e653e59 | ||
|
|
05a90e83ef | ||
|
|
e7430af074 | ||
|
|
0752ffce90 | ||
|
|
2451fae52a | ||
|
|
fa45d09568 | ||
|
|
5806ac91b0 | ||
|
|
92114046dd | ||
|
|
4fee35d05a | ||
|
|
2685f92229 | ||
|
|
bb1f9f162a | ||
|
|
687dda0665 | ||
|
|
23a06ec87e | ||
|
|
3002dd2531 | ||
|
|
068150b603 | ||
|
|
e97af12f69 | ||
|
|
93566320db | ||
|
|
9c4d1cf108 | ||
|
|
daa7ef2a3d | ||
|
|
09d44da087 | ||
|
|
9d10de9949 | ||
|
|
a0ffb46a6f | ||
|
|
3e8a8c649b | ||
|
|
0c8131f27e | ||
|
|
cd2c24d47b | ||
|
|
b77909a360 | ||
|
|
3fa72e48cc | ||
|
|
9aba70d214 | ||
|
|
302bff865c | ||
|
|
7cb5bcd468 | ||
|
|
804d9f66de | ||
|
|
489cfb5f10 | ||
|
|
45ee37c86d | ||
|
|
5221ed06ed | ||
|
|
206e5034c5 |
@@ -16,6 +16,7 @@
|
||||
**/compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
!**/node_modules/.pnpm/compressjs@*/**
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
|
||||
@@ -52,6 +52,8 @@ COPY --link --chown=1000:1000 /public ./public/
|
||||
# Copy files from builder
|
||||
COPY --link --from=builder --chown=1000:1000 /app/.next/standalone ./
|
||||
COPY --link --from=builder --chown=1000:1000 /app/.next/static/ ./.next/static/
|
||||
# see https://github.com/benphelps/homepage/issues/1795
|
||||
COPY --link --from=builder /app/node_modules/.pnpm/compressjs@1.0.3/node_modules/compressjs/lib/ ./node_modules/.pnpm/compressjs@1.0.3/node_modules/compressjs/lib/
|
||||
COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
|
||||
|
||||
RUN apk add --no-cache su-exec
|
||||
|
||||
@@ -85,6 +85,8 @@ services:
|
||||
volumes:
|
||||
- /path/to/config:/app/config # Make sure your local config directory exists
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations
|
||||
# user: 1000:1000 optional, not compatibile with direct socket see https://gethomepage.dev/en/configs/docker/#using-socket-directly
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
or docker run:
|
||||
|
||||
970
package-lock.json
generated
970
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,7 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.6",
|
||||
"react-icons": "^4.4.0",
|
||||
"recharts": "^2.7.2",
|
||||
"shvl": "^3.0.0",
|
||||
"swr": "^1.3.0",
|
||||
"systeminformation": "^5.17.12",
|
||||
|
||||
260
pnpm-lock.yaml
generated
260
pnpm-lock.yaml
generated
@@ -1,5 +1,9 @@
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@headlessui/react':
|
||||
specifier: ^1.7.2
|
||||
@@ -61,6 +65,9 @@ dependencies:
|
||||
react-icons:
|
||||
specifier: ^4.4.0
|
||||
version: 4.8.0(react@18.2.0)
|
||||
recharts:
|
||||
specifier: ^2.7.2
|
||||
version: 2.7.2(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
shvl:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
@@ -435,6 +442,48 @@ packages:
|
||||
tailwindcss: 3.3.0(postcss@8.4.21)
|
||||
dev: true
|
||||
|
||||
/@types/d3-array@3.0.5:
|
||||
resolution: {integrity: sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A==}
|
||||
dev: false
|
||||
|
||||
/@types/d3-color@3.1.0:
|
||||
resolution: {integrity: sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==}
|
||||
dev: false
|
||||
|
||||
/@types/d3-ease@3.0.0:
|
||||
resolution: {integrity: sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==}
|
||||
dev: false
|
||||
|
||||
/@types/d3-interpolate@3.0.1:
|
||||
resolution: {integrity: sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==}
|
||||
dependencies:
|
||||
'@types/d3-color': 3.1.0
|
||||
dev: false
|
||||
|
||||
/@types/d3-path@3.0.0:
|
||||
resolution: {integrity: sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==}
|
||||
dev: false
|
||||
|
||||
/@types/d3-scale@4.0.3:
|
||||
resolution: {integrity: sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==}
|
||||
dependencies:
|
||||
'@types/d3-time': 3.0.0
|
||||
dev: false
|
||||
|
||||
/@types/d3-shape@3.1.1:
|
||||
resolution: {integrity: sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==}
|
||||
dependencies:
|
||||
'@types/d3-path': 3.0.0
|
||||
dev: false
|
||||
|
||||
/@types/d3-time@3.0.0:
|
||||
resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==}
|
||||
dev: false
|
||||
|
||||
/@types/d3-timer@3.0.0:
|
||||
resolution: {integrity: sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==}
|
||||
dev: false
|
||||
|
||||
/@types/hoist-non-react-statics@3.3.1:
|
||||
resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==}
|
||||
dependencies:
|
||||
@@ -785,6 +834,7 @@ packages:
|
||||
/buildcheck@0.0.3:
|
||||
resolution: {integrity: sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -1020,6 +1070,10 @@ packages:
|
||||
nth-check: 2.1.1
|
||||
dev: false
|
||||
|
||||
/css-unit-converter@1.1.2:
|
||||
resolution: {integrity: sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==}
|
||||
dev: false
|
||||
|
||||
/css-what@6.1.0:
|
||||
resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -1034,6 +1088,77 @@ packages:
|
||||
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
||||
dev: false
|
||||
|
||||
/d3-array@3.2.4:
|
||||
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
internmap: 2.0.3
|
||||
dev: false
|
||||
|
||||
/d3-color@3.1.0:
|
||||
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/d3-ease@3.0.1:
|
||||
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/d3-format@3.1.0:
|
||||
resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/d3-interpolate@3.0.1:
|
||||
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
d3-color: 3.1.0
|
||||
dev: false
|
||||
|
||||
/d3-path@3.1.0:
|
||||
resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/d3-scale@4.0.2:
|
||||
resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
d3-format: 3.1.0
|
||||
d3-interpolate: 3.0.1
|
||||
d3-time: 3.1.0
|
||||
d3-time-format: 4.1.0
|
||||
dev: false
|
||||
|
||||
/d3-shape@3.2.0:
|
||||
resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
d3-path: 3.1.0
|
||||
dev: false
|
||||
|
||||
/d3-time-format@4.1.0:
|
||||
resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
d3-time: 3.1.0
|
||||
dev: false
|
||||
|
||||
/d3-time@3.1.0:
|
||||
resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
dev: false
|
||||
|
||||
/d3-timer@3.0.1:
|
||||
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/damerau-levenshtein@1.0.8:
|
||||
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
|
||||
dev: true
|
||||
@@ -1067,6 +1192,10 @@ packages:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
|
||||
/decimal.js-light@2.5.1:
|
||||
resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==}
|
||||
dev: false
|
||||
|
||||
/decompress-response@6.0.0:
|
||||
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -1175,6 +1304,12 @@ packages:
|
||||
esutils: 2.0.3
|
||||
dev: true
|
||||
|
||||
/dom-helpers@3.4.0:
|
||||
resolution: {integrity: sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
dev: false
|
||||
|
||||
/dom-serializer@2.0.0:
|
||||
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
|
||||
dependencies:
|
||||
@@ -1654,6 +1789,10 @@ packages:
|
||||
deprecated: Use promise-toolbox/fromEvent instead
|
||||
dev: false
|
||||
|
||||
/eventemitter3@4.0.7:
|
||||
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
|
||||
dev: false
|
||||
|
||||
/execa@5.0.0:
|
||||
resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -1685,6 +1824,11 @@ packages:
|
||||
resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==}
|
||||
dev: true
|
||||
|
||||
/fast-equals@5.0.1:
|
||||
resolution: {integrity: sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: false
|
||||
|
||||
/fast-glob@3.2.12:
|
||||
resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
|
||||
engines: {node: '>=8.6.0'}
|
||||
@@ -2158,6 +2302,11 @@ packages:
|
||||
side-channel: 1.0.4
|
||||
dev: true
|
||||
|
||||
/internmap@2.0.3:
|
||||
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/interpret@1.4.0:
|
||||
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@@ -2361,6 +2510,7 @@ packages:
|
||||
|
||||
/jose@4.13.1:
|
||||
resolution: {integrity: sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -2480,6 +2630,10 @@ packages:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
dev: true
|
||||
|
||||
/lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
dev: false
|
||||
|
||||
/logform@2.5.1:
|
||||
resolution: {integrity: sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==}
|
||||
dependencies:
|
||||
@@ -2623,6 +2777,7 @@ packages:
|
||||
|
||||
/nan@2.17.0:
|
||||
resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -2755,11 +2910,11 @@ packages:
|
||||
/object-assign@4.1.1:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/object-hash@2.2.0:
|
||||
resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
|
||||
engines: {node: '>= 6'}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -2832,6 +2987,7 @@ packages:
|
||||
/oidc-token-hash@5.0.1:
|
||||
resolution: {integrity: sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ==}
|
||||
engines: {node: ^10.13.0 || >=12.0.0}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -3023,6 +3179,10 @@ packages:
|
||||
util-deprecate: 1.0.2
|
||||
dev: true
|
||||
|
||||
/postcss-value-parser@3.3.1:
|
||||
resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==}
|
||||
dev: false
|
||||
|
||||
/postcss-value-parser@4.2.0:
|
||||
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
|
||||
dev: true
|
||||
@@ -3077,7 +3237,6 @@ packages:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
react-is: 16.13.1
|
||||
dev: true
|
||||
|
||||
/psl@1.9.0:
|
||||
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
||||
@@ -3162,6 +3321,49 @@ packages:
|
||||
/react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
/react-lifecycles-compat@3.0.4:
|
||||
resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
|
||||
dev: false
|
||||
|
||||
/react-resize-detector@8.1.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-S7szxlaIuiy5UqLhLL1KY3aoyGHbZzsTpYal9eYMwCyKqoqoVLCmIgAgNyIM1FhnP2KyBygASJxdhejrzjMb+w==}
|
||||
peerDependencies:
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-smooth@2.0.3(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-yl4y3XiMorss7ayF5QnBiSprig0+qFHui8uh7Hgg46QX5O+aRMRKlfGGNGLHno35JkQSvSYY8eCWkBfHfrSHfg==}
|
||||
peerDependencies:
|
||||
prop-types: ^15.6.0
|
||||
react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
fast-equals: 5.0.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-transition-group: 2.9.0(react-dom@18.2.0)(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-transition-group@2.9.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==}
|
||||
peerDependencies:
|
||||
react: '>=15.0.0'
|
||||
react-dom: '>=15.0.0'
|
||||
dependencies:
|
||||
dom-helpers: 3.4.0
|
||||
loose-envify: 1.4.0
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-lifecycles-compat: 3.0.4
|
||||
dev: false
|
||||
|
||||
/react@18.2.0:
|
||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -3212,6 +3414,34 @@ packages:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/recharts-scale@0.4.5:
|
||||
resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==}
|
||||
dependencies:
|
||||
decimal.js-light: 2.5.1
|
||||
dev: false
|
||||
|
||||
/recharts@2.7.2(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-HMKRBkGoOXHW+7JcRa6+MukPSifNtJlqbc+JreGVNA407VLE/vOP+8n3YYjprDVVIF9E2ZgwWnL3D7K/LUFzBg==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
prop-types: ^15.6.0
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
classnames: 2.3.2
|
||||
eventemitter3: 4.0.7
|
||||
lodash: 4.17.21
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-is: 16.13.1
|
||||
react-resize-detector: 8.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||
react-smooth: 2.0.3(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
recharts-scale: 0.4.5
|
||||
reduce-css-calc: 2.1.8
|
||||
victory-vendor: 36.6.11
|
||||
dev: false
|
||||
|
||||
/rechoir@0.6.2:
|
||||
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@@ -3219,6 +3449,13 @@ packages:
|
||||
resolve: 1.22.1
|
||||
dev: false
|
||||
|
||||
/reduce-css-calc@2.1.8:
|
||||
resolution: {integrity: sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==}
|
||||
dependencies:
|
||||
css-unit-converter: 1.1.2
|
||||
postcss-value-parser: 3.3.1
|
||||
dev: false
|
||||
|
||||
/regenerator-runtime@0.13.11:
|
||||
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
|
||||
|
||||
@@ -3896,6 +4133,25 @@ packages:
|
||||
extsprintf: 1.3.0
|
||||
dev: false
|
||||
|
||||
/victory-vendor@36.6.11:
|
||||
resolution: {integrity: sha512-nT8kCiJp8dQh8g991J/R5w5eE2KnO8EAIP0xocWlh9l2okngMWglOPoMZzJvek8Q1KUc4XE/mJxTZnvOB1sTYg==}
|
||||
dependencies:
|
||||
'@types/d3-array': 3.0.5
|
||||
'@types/d3-ease': 3.0.0
|
||||
'@types/d3-interpolate': 3.0.1
|
||||
'@types/d3-scale': 4.0.3
|
||||
'@types/d3-shape': 3.1.1
|
||||
'@types/d3-time': 3.0.0
|
||||
'@types/d3-timer': 3.0.0
|
||||
d3-array: 3.2.4
|
||||
d3-ease: 3.0.1
|
||||
d3-interpolate: 3.0.1
|
||||
d3-scale: 4.0.2
|
||||
d3-shape: 3.2.0
|
||||
d3-time: 3.1.0
|
||||
d3-timer: 3.0.1
|
||||
dev: false
|
||||
|
||||
/void-elements@3.1.0:
|
||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
@@ -310,7 +310,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "مفضلة",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
},
|
||||
"calibreweb": {
|
||||
"categories": "Categories",
|
||||
"series": "Series",
|
||||
"books": "Books",
|
||||
"authors": "Authors"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total d'observats",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"totalUsed": "Used Storage",
|
||||
"noRecent": "Out of Date"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +322,13 @@
|
||||
"free": "Free",
|
||||
"used": "Used",
|
||||
"load": "Load",
|
||||
"warn": "Warn"
|
||||
"warn": "Warn",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Záložka",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"wmo": {
|
||||
"1-day": "Hovedsageligt solrigt",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warnung",
|
||||
"total": "Gesamt",
|
||||
"free": "Frei",
|
||||
"used": "Verwendet"
|
||||
"used": "Verwendet",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap",
|
||||
"crit": "Crit",
|
||||
"read": "Read"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Gesamt beobachtet",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping",
|
||||
"maxPlayers": "Max players"
|
||||
"maxPlayers": "Max players",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,9 +150,9 @@
|
||||
},
|
||||
"flood": {
|
||||
"download": "Λήξη",
|
||||
"upload": "Φόρτωση",
|
||||
"leech": "Αφαίμαξη",
|
||||
"seed": "Σπείρε"
|
||||
"upload": "Μεταφόρτωση",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Συνολικά παρατηρηθείσα",
|
||||
@@ -163,7 +163,7 @@
|
||||
"transcoding": "Μετακωδικοποίηση",
|
||||
"bitrate": "Ρυθμός bit",
|
||||
"no_active": "Δεν υπάρχουν ενεργές ροές",
|
||||
"plex_connection_error": "Check Plex Connection"
|
||||
"plex_connection_error": "Έλεγχος Σύνδεσης με Plex"
|
||||
},
|
||||
"nzbget": {
|
||||
"rate": "Ρυθμός",
|
||||
@@ -208,12 +208,12 @@
|
||||
"series": "Σειρές",
|
||||
"wanted": "Επιθυμούντε",
|
||||
"queued": "Σε σειρά",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Ούρα",
|
||||
"unknown": "Άγνωστο"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Μεταφόρτωση",
|
||||
"upload": "Φόρτωση",
|
||||
"download": "Λήψη",
|
||||
"upload": "Μεταφόρτωση",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
@@ -222,13 +222,13 @@
|
||||
"missing": "Απουσιάζει",
|
||||
"queued": "Σε σειρά",
|
||||
"movies": "Ταινίες",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Ουρά",
|
||||
"unknown": "Άγνωστο"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Θέλετε",
|
||||
"queued": "Στη σειρά",
|
||||
"artists": "Artists"
|
||||
"artists": "Καλλιτέχνες"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Θέλετε",
|
||||
@@ -237,17 +237,17 @@
|
||||
},
|
||||
"bazarr": {
|
||||
"missingEpisodes": "Επεισόδια που λείπουν",
|
||||
"missingMovies": "Missing Movies"
|
||||
"missingMovies": "Ταινίες που Λείπουν"
|
||||
},
|
||||
"ombi": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"pending": "Σε εκκρεμότητα",
|
||||
"approved": "Εγκρίθηκε",
|
||||
"available": "Διαθέσιμο"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"pending": "Σε εκκρεμότητα",
|
||||
"approved": "Εγκρίθηκε",
|
||||
"available": "Διαθέσιμο"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Pending",
|
||||
@@ -257,25 +257,25 @@
|
||||
},
|
||||
"pihole": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"blocked": "Αποκλεισμένο",
|
||||
"gravity": "Gravity",
|
||||
"blocked_percent": "Blocked %"
|
||||
"blocked_percent": "Αποκλεισμένο %"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"filtered": "Filtered",
|
||||
"latency": "Latency"
|
||||
"queries": "Αναζητήσεις",
|
||||
"blocked": "Αποκλεισμένο",
|
||||
"filtered": "Φιλτραρισμένα",
|
||||
"latency": "Καθυστέρηση"
|
||||
},
|
||||
"speedtest": {
|
||||
"upload": "Upload",
|
||||
"download": "Download",
|
||||
"upload": "Ανέβασμα",
|
||||
"download": "Λήψη",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"portainer": {
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"total": "Total"
|
||||
"stopped": "Σταματημένο",
|
||||
"total": "Σύνολο"
|
||||
},
|
||||
"tdarr": {
|
||||
"queue": "Queue",
|
||||
@@ -369,7 +369,13 @@
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used",
|
||||
"load": "Load"
|
||||
"load": "Load",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -557,7 +563,7 @@
|
||||
"records_total": "Queue Length"
|
||||
},
|
||||
"pterodactyl": {
|
||||
"servers": "Servers",
|
||||
"servers": "Διακομιστές",
|
||||
"nodes": "Nodes"
|
||||
},
|
||||
"prometheus": {
|
||||
@@ -583,28 +589,28 @@
|
||||
},
|
||||
"freshrss": {
|
||||
"subscriptions": "Συνδρομές",
|
||||
"unread": "Αδιάβαστο"
|
||||
"unread": "Μη Διαβασμένο"
|
||||
},
|
||||
"channelsdvrserver": {
|
||||
"shows": "Εκπομπές",
|
||||
"recordings": "Εγγραφές",
|
||||
"scheduled": "Προγραμματισμένα",
|
||||
"passes": "Passes"
|
||||
"passes": "Περάσματα"
|
||||
},
|
||||
"whatsupdocker": {
|
||||
"monitoring": "Monitoring",
|
||||
"updates": "Updates"
|
||||
},
|
||||
"tailscale": {
|
||||
"address": "Address",
|
||||
"never": "Never",
|
||||
"address": "Διεύθυνση",
|
||||
"never": "Ποτέ",
|
||||
"years": "{{number}}y",
|
||||
"weeks": "{{number}}w",
|
||||
"days": "{{number}}d",
|
||||
"hours": "{{number}}h",
|
||||
"expires": "Expires",
|
||||
"expires": "Λήγει",
|
||||
"last_seen": "Last Seen",
|
||||
"now": "Now",
|
||||
"now": "Τώρα",
|
||||
"minutes": "{{number}}m",
|
||||
"seconds": "{{number}}s",
|
||||
"ago": "{{value}} Ago"
|
||||
@@ -615,7 +621,7 @@
|
||||
"systemTempC": "Θερμοκρασία συστήματος",
|
||||
"poolUsage": "Χρήση πισίνας",
|
||||
"volumeUsage": "Volume Usage",
|
||||
"invalid": "Invalid"
|
||||
"invalid": "Μη έγκυρο"
|
||||
},
|
||||
"pfsense": {
|
||||
"load": "Load Avg",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"myPrs": "My PRs",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +371,13 @@
|
||||
"free": "Free",
|
||||
"used": "Used",
|
||||
"days": "d",
|
||||
"hours": "h"
|
||||
"hours": "h",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -573,6 +579,12 @@
|
||||
"incident": "Incident",
|
||||
"m": "m"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"komga": {
|
||||
"libraries": "Libraries",
|
||||
"series": "Series",
|
||||
@@ -655,6 +667,12 @@
|
||||
"monitoring": "Monitoring",
|
||||
"updates": "Updates"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
},
|
||||
"jdownloader": {
|
||||
"downloadCount": "Queue",
|
||||
"downloadBytesRemaining": "Remaining",
|
||||
@@ -679,6 +697,9 @@
|
||||
"approved": "Approved"
|
||||
},
|
||||
"gamedig": {
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline",
|
||||
"name": "Name",
|
||||
"map": "Map",
|
||||
"currentPlayers": "Current players",
|
||||
@@ -692,5 +713,19 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +266,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"categories": "Categories",
|
||||
"authors": "Authors",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Advertir",
|
||||
"total": "Total",
|
||||
"free": "Libre",
|
||||
"used": "Utilizado"
|
||||
"used": "Utilizado",
|
||||
"crit": "Crít.",
|
||||
"read": "Leer",
|
||||
"write": "Escribir",
|
||||
"gpu": "GPU",
|
||||
"mem": "Memoria",
|
||||
"swap": "Intercambiar"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observados",
|
||||
@@ -663,25 +669,54 @@
|
||||
"players": "Jugadores",
|
||||
"maxPlayers": "Jugadores máximos",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Estado",
|
||||
"online": "En línea",
|
||||
"offline": "Sin conexión"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
"status": "Status",
|
||||
"buildId": "Build ID",
|
||||
"succeeded": "Succeeded",
|
||||
"notStarted": "Not Started",
|
||||
"failed": "Failed",
|
||||
"canceled": "Canceled",
|
||||
"inProgress": "In Progress",
|
||||
"totalPrs": "Total PRs",
|
||||
"myPrs": "My PRs",
|
||||
"approved": "Approved"
|
||||
"result": "Resultado",
|
||||
"status": "Estado",
|
||||
"buildId": "Identificador de la construcción",
|
||||
"succeeded": "Exitoso",
|
||||
"notStarted": "Sin empezar",
|
||||
"failed": "Fallido",
|
||||
"canceled": "Cancelado",
|
||||
"inProgress": "En curso",
|
||||
"totalPrs": "RP totales",
|
||||
"myPrs": "Mis logros",
|
||||
"approved": "Aprobados"
|
||||
},
|
||||
"urbackup": {
|
||||
"ok": "Ok",
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
"ok": "De acuerdo",
|
||||
"errored": "Errores",
|
||||
"noRecent": "Caducado",
|
||||
"totalUsed": "Almacenamiento usado"
|
||||
},
|
||||
"openmediavault": {
|
||||
"running": "Ejecutando",
|
||||
"downloading": "Descargando",
|
||||
"total": "Total",
|
||||
"stopped": "Detenido",
|
||||
"passed": "Aprobado",
|
||||
"failed": "Fallido"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recetas",
|
||||
"users": "Usuarios",
|
||||
"categories": "Categorías",
|
||||
"tags": "Etiquetas"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archivos",
|
||||
"chapters": "Capítulos",
|
||||
"categories": "Categorías"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +431,13 @@
|
||||
"free": "Free",
|
||||
"used": "Used",
|
||||
"days": "d",
|
||||
"hours": "h"
|
||||
"hours": "h",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"notStarted": "Not Started",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Alerte",
|
||||
"total": "Total",
|
||||
"free": "Libre",
|
||||
"used": "Utilisé"
|
||||
"used": "Utilisé",
|
||||
"crit": "Crit.",
|
||||
"read": "Lect.",
|
||||
"write": "Écrit.",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mém.",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observé",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Joueurs",
|
||||
"maxPlayers": "Joueurs max",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Statut",
|
||||
"online": "En ligne",
|
||||
"offline": "Hors ligne"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Résultat",
|
||||
@@ -680,8 +689,34 @@
|
||||
},
|
||||
"urbackup": {
|
||||
"ok": "Ok",
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
"errored": "Erreur",
|
||||
"noRecent": "Obsolète",
|
||||
"totalUsed": "Esp. Utilisé"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Téléchargement",
|
||||
"total": "Total",
|
||||
"running": "Démarré",
|
||||
"stopped": "Arrêté",
|
||||
"passed": "Réussi",
|
||||
"failed": "Échoué"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recettes",
|
||||
"users": "Utilisateurs",
|
||||
"categories": "Catégories",
|
||||
"tags": "Étiquettes"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Séries",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapitres",
|
||||
"categories": "Catégories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"series": "Series",
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"load": "Load",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"myPrs": "My PRs",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories",
|
||||
"series": "Series",
|
||||
"archives": "Archives"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"load": "Opterećenje",
|
||||
"warn": "Upozori",
|
||||
"total": "Ukupno",
|
||||
"free": "Slobodno"
|
||||
"free": "Slobodno",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Ukupno promatrano",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"totalUsed": "Used Storage",
|
||||
"ok": "Ok",
|
||||
"errored": "Errors"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"categories": "Categories",
|
||||
"series": "Series",
|
||||
"authors": "Authors"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Figyelmeztet",
|
||||
"total": "Összes",
|
||||
"free": "Szabad",
|
||||
"used": "Felhasznált"
|
||||
"used": "Felhasznált",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Összes Megfigyelt",
|
||||
@@ -663,7 +669,10 @@
|
||||
"currentPlayers": "Current players",
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots"
|
||||
"bots": "Bots",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"status": "Status",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"series": "Series",
|
||||
"categories": "Categories"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,13 @@
|
||||
"wait": "Please wait",
|
||||
"used": "Used",
|
||||
"days": "d",
|
||||
"hours": "h"
|
||||
"hours": "h",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Avviso",
|
||||
"total": "Totale",
|
||||
"free": "Libero",
|
||||
"used": "Usato"
|
||||
"used": "Usato",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Totale Osservato",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"downloading": "Downloading",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"autobrr": {
|
||||
"filters": "フィルター",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +315,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"currentPlayers": "Current players",
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots"
|
||||
"bots": "Bots",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories",
|
||||
"series": "Series",
|
||||
"archives": "Archives"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,7 +304,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"online": "Online",
|
||||
"status": "Status",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"chapters": "Chapters",
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Tandabuku",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@
|
||||
"devices": "Apparaten",
|
||||
"lan_devices": "LAN Apparaten",
|
||||
"wlan_devices": "WLAN Apparaten",
|
||||
"empty_data": "Subsystem status unknown"
|
||||
"empty_data": "Subsystem status onbekend"
|
||||
},
|
||||
"plex": {
|
||||
"streams": "Actieve Streams",
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Totaal waargenomen",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"online": "Online",
|
||||
"status": "Status",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"diffsDetected": "Wykryto różnic",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"status": "Status",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Aviso",
|
||||
"total": "Total",
|
||||
"free": "Livre",
|
||||
"used": "Usado"
|
||||
"used": "Usado",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Observados",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Jogadores",
|
||||
"maxPlayers": "Jogadores Max",
|
||||
"bots": "Robos",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observado",
|
||||
@@ -672,7 +678,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -692,5 +701,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"canceled": "Canceled",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
"free": "Свободно",
|
||||
"used": "Использовано",
|
||||
"load": "Загрузка",
|
||||
"cpu": "Процессор",
|
||||
"mem": "Память",
|
||||
"temp": "Температура",
|
||||
"cpu": "ЦП",
|
||||
"mem": "ОЗУ",
|
||||
"temp": "Темпер.",
|
||||
"max": "Макс.",
|
||||
"uptime": "UP",
|
||||
"uptime": "Работает",
|
||||
"months": "мес",
|
||||
"days": "д",
|
||||
"hours": "ч",
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Всего наблюдаемых",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Серии",
|
||||
"archives": "Архивы",
|
||||
"chapters": "Главы",
|
||||
"categories": "Категории"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +412,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"succeeded": "Succeeded",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"total": "Total",
|
||||
"downloading": "Downloading",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,7 +364,13 @@
|
||||
"load": "Obremenitev",
|
||||
"warn": "Opoz.",
|
||||
"total": "Skupaj",
|
||||
"used": "V uporabi"
|
||||
"used": "V uporabi",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Uporabniki",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed",
|
||||
"downloading": "Downloading"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"approved": "Approved",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "మొత్తం గమనించబడింది",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"failed": "Failed",
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +324,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Uyarı",
|
||||
"total": "Toplam",
|
||||
"free": "Boş",
|
||||
"used": "Kullanım"
|
||||
"used": "Kullanım",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Toplam Gözlenen",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +372,13 @@
|
||||
"warn": "Увага",
|
||||
"total": "Всього",
|
||||
"free": "Вільний",
|
||||
"used": "Використовується"
|
||||
"used": "Використовується",
|
||||
"crit": "Crit",
|
||||
"read": "Прочитати",
|
||||
"write": "Написати",
|
||||
"gpu": "GPU",
|
||||
"mem": "Пам'ять",
|
||||
"swap": "Обмін"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Закладка",
|
||||
@@ -663,25 +669,54 @@
|
||||
"players": "Гравці",
|
||||
"maxPlayers": "Максимум гравців",
|
||||
"bots": "Ботів",
|
||||
"ping": "Пінг"
|
||||
"ping": "Пінг",
|
||||
"status": "Статус",
|
||||
"online": "В мережі",
|
||||
"offline": "Не в мережі"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
"status": "Status",
|
||||
"buildId": "Build ID",
|
||||
"succeeded": "Succeeded",
|
||||
"notStarted": "Not Started",
|
||||
"failed": "Failed",
|
||||
"canceled": "Canceled",
|
||||
"inProgress": "In Progress",
|
||||
"totalPrs": "Total PRs",
|
||||
"myPrs": "My PRs",
|
||||
"approved": "Approved"
|
||||
"result": "Результат",
|
||||
"status": "Статус",
|
||||
"buildId": "ID збірки",
|
||||
"succeeded": "Успішно",
|
||||
"notStarted": "Не розпочато",
|
||||
"failed": "Невдача",
|
||||
"canceled": "Скасовано",
|
||||
"inProgress": "В процесі",
|
||||
"totalPrs": "Всього PR",
|
||||
"myPrs": "Мій PR",
|
||||
"approved": "Затверджено"
|
||||
},
|
||||
"urbackup": {
|
||||
"ok": "Ok",
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
"ok": "Добре",
|
||||
"errored": "Помилки",
|
||||
"noRecent": "Застарілий",
|
||||
"totalUsed": "Використовувана пам'ять"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Серії",
|
||||
"archives": "Архіви",
|
||||
"chapters": "Глави",
|
||||
"categories": "Категорії"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@
|
||||
"warn": "Warn",
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used"
|
||||
"used": "Used",
|
||||
"crit": "Crit",
|
||||
"read": "Read",
|
||||
"write": "Write",
|
||||
"gpu": "GPU",
|
||||
"mem": "Mem",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "观察到的总数",
|
||||
@@ -663,7 +669,10 @@
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"canceled": "Canceled",
|
||||
@@ -683,5 +692,31 @@
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"transcoding": "轉碼",
|
||||
"bitrate": "位元率",
|
||||
"no_active": "無播放活動",
|
||||
"plex_connection_error": "Check Plex Connection"
|
||||
"plex_connection_error": "檢查Plex的連接狀態"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"pending": "待下載",
|
||||
@@ -90,15 +90,15 @@
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"missing": "缺少",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "佇列",
|
||||
"unknown": "未知的"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"series": "影集",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "佇列",
|
||||
"unknown": "未知的"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "關注中",
|
||||
@@ -178,7 +178,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"artists": "Artists"
|
||||
"artists": "創作者"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "查詢",
|
||||
@@ -248,7 +248,13 @@
|
||||
"used": "已使用",
|
||||
"load": "負載量",
|
||||
"warn": "警告",
|
||||
"total": "總共"
|
||||
"total": "總共",
|
||||
"crit": "Crit",
|
||||
"read": "讀取",
|
||||
"write": "寫入",
|
||||
"gpu": "GPU",
|
||||
"mem": "記憶體",
|
||||
"swap": "Swap"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "總監測數",
|
||||
@@ -647,41 +653,70 @@
|
||||
"down_alerts": "離線警告"
|
||||
},
|
||||
"jdownloader": {
|
||||
"downloadCount": "Queue Count",
|
||||
"downloadSpeed": "Download Speed",
|
||||
"downloadBytesRemaining": "Remaining",
|
||||
"downloadTotalBytes": "Size"
|
||||
"downloadCount": "下載佇列",
|
||||
"downloadSpeed": "下載速率",
|
||||
"downloadBytesRemaining": "剩餘",
|
||||
"downloadTotalBytes": "總下載量"
|
||||
},
|
||||
"kavita": {
|
||||
"seriesCount": "Series",
|
||||
"totalFiles": "Files"
|
||||
"seriesCount": "叢刊",
|
||||
"totalFiles": "檔案"
|
||||
},
|
||||
"gamedig": {
|
||||
"name": "Name",
|
||||
"map": "Map",
|
||||
"currentPlayers": "Current players",
|
||||
"players": "Players",
|
||||
"maxPlayers": "Max players",
|
||||
"bots": "Bots",
|
||||
"ping": "Ping"
|
||||
"name": "名稱",
|
||||
"map": "地圖",
|
||||
"currentPlayers": "當前玩家數",
|
||||
"players": "玩家",
|
||||
"maxPlayers": "玩家數上限",
|
||||
"bots": "機器人",
|
||||
"ping": "Ping",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline"
|
||||
},
|
||||
"azuredevops": {
|
||||
"result": "Result",
|
||||
"status": "Status",
|
||||
"buildId": "Build ID",
|
||||
"succeeded": "Succeeded",
|
||||
"notStarted": "Not Started",
|
||||
"failed": "Failed",
|
||||
"canceled": "Canceled",
|
||||
"inProgress": "In Progress",
|
||||
"totalPrs": "Total PRs",
|
||||
"myPrs": "My PRs",
|
||||
"approved": "Approved"
|
||||
"result": "結果",
|
||||
"status": "狀態",
|
||||
"buildId": "組建編號",
|
||||
"succeeded": "成功",
|
||||
"notStarted": "尚未啟用",
|
||||
"failed": "失敗",
|
||||
"canceled": "取消",
|
||||
"inProgress": "執行中",
|
||||
"totalPrs": "總提取要求",
|
||||
"myPrs": "我的提取要求",
|
||||
"approved": "已核准"
|
||||
},
|
||||
"urbackup": {
|
||||
"ok": "Ok",
|
||||
"errored": "Errors",
|
||||
"noRecent": "Out of Date",
|
||||
"totalUsed": "Used Storage"
|
||||
"errored": "錯誤",
|
||||
"noRecent": "已過時",
|
||||
"totalUsed": "已使用空間"
|
||||
},
|
||||
"openmediavault": {
|
||||
"downloading": "Downloading",
|
||||
"total": "Total",
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"passed": "Passed",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"mealie": {
|
||||
"recipes": "Recipes",
|
||||
"users": "Users",
|
||||
"categories": "Categories",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"atsumeru": {
|
||||
"series": "Series",
|
||||
"archives": "Archives",
|
||||
"chapters": "Chapters",
|
||||
"categories": "Categories"
|
||||
},
|
||||
"calibreweb": {
|
||||
"books": "Books",
|
||||
"authors": "Authors",
|
||||
"categories": "Categories",
|
||||
"series": "Series"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useContext } from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
import { SettingsContext } from "utils/contexts/settings";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
@@ -16,7 +17,10 @@ export default function Item({ bookmark }) {
|
||||
className="block w-full text-left cursor-pointer transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10"
|
||||
>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md">
|
||||
<div className={classNames(
|
||||
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
|
||||
"flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md"
|
||||
)}>
|
||||
{bookmark.icon &&
|
||||
<div className="flex-shrink-0 w-5 h-5">
|
||||
<ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
|
||||
@@ -24,7 +28,10 @@ export default function Item({ bookmark }) {
|
||||
}
|
||||
{!bookmark.icon && bookmark.abbr}
|
||||
</div>
|
||||
<div className="flex-1 flex items-center justify-between rounded-r-md ">
|
||||
<div className={classNames(
|
||||
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
|
||||
"flex-1 flex items-center justify-between rounded-r-md"
|
||||
)}>
|
||||
<div className="flex-1 grow pl-3 py-2 text-xs">{bookmark.name}</div>
|
||||
<div className="px-2 py-2 truncate text-theme-500 dark:text-theme-300 text-xs">{hostname}</div>
|
||||
</div>
|
||||
|
||||
@@ -145,7 +145,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
|
||||
return (
|
||||
<div className={classNames(
|
||||
"relative z-20 ease-in-out duration-300 transition-opacity",
|
||||
"relative z-40 ease-in-out duration-300 transition-opacity",
|
||||
hidden && !isOpen && "hidden",
|
||||
!hidden && isOpen && "opacity-100",
|
||||
!isOpen && "opacity-0",
|
||||
|
||||
@@ -16,45 +16,47 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
|
||||
className={classNames(
|
||||
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
|
||||
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
|
||||
"flex-1 p-1"
|
||||
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1",
|
||||
)}
|
||||
>
|
||||
<Disclosure defaultOpen>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
|
||||
{layout?.icon &&
|
||||
<div className="flex-shrink-0 mr-2 w-7 h-7">
|
||||
<ResolvedIcon icon={layout.icon} />
|
||||
</div>
|
||||
<Disclosure defaultOpen>
|
||||
{({ open }) => (
|
||||
<>
|
||||
{ layout?.header !== false &&
|
||||
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
|
||||
{layout?.icon &&
|
||||
<div className="flex-shrink-0 mr-2 w-7 h-7">
|
||||
<ResolvedIcon icon={layout.icon} />
|
||||
</div>
|
||||
}
|
||||
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
|
||||
<MdKeyboardArrowDown className={classNames(
|
||||
disableCollapse ? 'hidden' : '',
|
||||
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
|
||||
open ? '' : 'rotate-90'
|
||||
)} />
|
||||
</Disclosure.Button>
|
||||
}
|
||||
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
|
||||
<MdKeyboardArrowDown className={classNames(
|
||||
disableCollapse ? 'hidden' : '',
|
||||
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
|
||||
open ? '' : 'rotate-90'
|
||||
)} />
|
||||
</Disclosure.Button>
|
||||
<Transition
|
||||
// Otherwise the transition group does display: none and cancels animation
|
||||
className="!block"
|
||||
unmount={false}
|
||||
beforeLeave={() => {
|
||||
panel.current.style.height = `${panel.current.scrollHeight}px`;
|
||||
setTimeout(() => {panel.current.style.height = `0`}, 1);
|
||||
}}
|
||||
beforeEnter={() => {
|
||||
panel.current.style.height = `0px`;
|
||||
setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
|
||||
}}
|
||||
>
|
||||
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
|
||||
<List group={group} services={services.services} layout={layout} />
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
<Transition
|
||||
// Otherwise the transition group does display: none and cancels animation
|
||||
className="!block"
|
||||
unmount={false}
|
||||
beforeLeave={() => {
|
||||
panel.current.style.height = `${panel.current.scrollHeight}px`;
|
||||
setTimeout(() => {panel.current.style.height = `0`}, 1);
|
||||
}}
|
||||
beforeEnter={() => {
|
||||
panel.current.style.height = `0px`;
|
||||
setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
|
||||
}}
|
||||
>
|
||||
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
|
||||
<List group={group} services={services.services} layout={layout} />
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,11 +32,13 @@ export default function Item({ service, group }) {
|
||||
return (
|
||||
<li key={service.name}>
|
||||
<div
|
||||
className={`${
|
||||
hasLink ? "cursor-pointer " : " "
|
||||
}transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative`}
|
||||
className={classNames(
|
||||
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
|
||||
hasLink && "cursor-pointer",
|
||||
'transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip'
|
||||
)}
|
||||
>
|
||||
<div className="flex select-none">
|
||||
<div className="flex select-none z-0">
|
||||
{service.icon &&
|
||||
(hasLink ? (
|
||||
<a
|
||||
@@ -60,21 +62,21 @@ export default function Item({ service, group }) {
|
||||
rel="noreferrer"
|
||||
className="flex-1 flex items-center justify-between rounded-r-md "
|
||||
>
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left">
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left z-10">
|
||||
{service.name}
|
||||
<p className="text-theme-500 dark:text-theme-300 text-xs font-light">{service.description}</p>
|
||||
</div>
|
||||
</a>
|
||||
) : (
|
||||
<div className="flex-1 flex items-center justify-between rounded-r-md ">
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left">
|
||||
<div className="flex-1 px-2 py-2 text-sm text-left z-10">
|
||||
{service.name}
|
||||
<p className="text-theme-500 dark:text-theme-300 text-xs font-light">{service.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="absolute top-0 right-0 w-1/2 flex flex-row justify-end gap-2 mr-2">
|
||||
<div className="absolute top-0 right-0 w-1/2 flex flex-row justify-end gap-2 mr-2 z-30">
|
||||
{service.ping && (
|
||||
<div className="flex-shrink-0 flex items-center justify-center cursor-pointer">
|
||||
<Ping group={group} service={service.name} />
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function Container({ error = false, children, service }) {
|
||||
|
||||
let visibleChildren = childrenArray;
|
||||
let fields = service?.widget?.fields;
|
||||
if (typeof service.widget.fields === 'string') fields = JSON.parse(service.widget.fields);
|
||||
if (typeof fields === 'string') fields = JSON.parse(service.widget.fields);
|
||||
const type = service?.widget?.type;
|
||||
if (fields && type) {
|
||||
// if the field contains a "." then it most likely contains a common loc value
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function Widget({ options }) {
|
||||
<Resource icon={FaMemory} label={t("glances.wait")} percentage="0" />
|
||||
{ options.cputemp && <Resource icon={FaThermometerHalf} label={t("glances.wait")} percentage="0" /> }
|
||||
{ options.disk && !Array.isArray(options.disk) && <Resource key={options.disk} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> }
|
||||
{ options.disk && Array.isArray(options.disk) && options.disk.map((disk) => <Resource key={`disk_${disk.mnt_point}`} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> ) }
|
||||
{ options.disk && Array.isArray(options.disk) && options.disk.map((disk) => <Resource key={`disk_${disk}`} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> ) }
|
||||
{ options.uptime && <Resource icon={FaRegClock} label={t("glances.wait")} percentage="0" /> }
|
||||
{ options.label && <WidgetLabel label={options.label} /> }
|
||||
</Resources>;
|
||||
@@ -108,7 +108,7 @@ export default function Widget({ options }) {
|
||||
expanded={options.expanded}
|
||||
/>
|
||||
{disks.map((disk) => (
|
||||
<Resource key={`disk_${disk.mnt_point}`}
|
||||
<Resource key={`disk_${disk.mnt_point ?? disk.device_name}`}
|
||||
icon={FiHardDrive}
|
||||
value={t("common.bytes", { value: disk.free })}
|
||||
label={t("glances.free")}
|
||||
|
||||
@@ -10,6 +10,7 @@ import Uptime from "./uptime";
|
||||
export default function Resources({ options }) {
|
||||
const { expanded, units } = options;
|
||||
let { refresh } = options;
|
||||
if (!refresh) refresh = 1500;
|
||||
refresh = Math.max(refresh, 1000);
|
||||
return <Container options={options}>
|
||||
<Raw>
|
||||
|
||||
@@ -7,6 +7,11 @@ import Raw from "./raw";
|
||||
|
||||
export function getAllClasses(options, additionalClassNames = '') {
|
||||
if (options?.style?.header === "boxedWidgets") {
|
||||
if (options?.style?.cardBlur !== undefined) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
additionalClassNames = additionalClassNames.concat(additionalClassNames, ` backdrop-blur${options.style.cardBlur.length ? '-' : ""}${options.style.cardBlur}`)
|
||||
}
|
||||
|
||||
return classNames(
|
||||
"flex flex-col justify-center first:ml-0 ml-2 mr-2",
|
||||
"mt-2 m:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-2 pl-3 pr-3",
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function Resource({ children, icon, value, label, expandedValue =
|
||||
<div className="pr-1">{expandedLabel}</div>
|
||||
</div>
|
||||
}
|
||||
{ percentage && <UsageBar percent={percentage} /> }
|
||||
{ percentage >= 0 && <UsageBar percent={percentage} /> }
|
||||
{ children }
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
@@ -55,6 +55,10 @@ export default async function handler(req, res) {
|
||||
req.query.endpoint = `${req.query.endpoint}?${query}`;
|
||||
}
|
||||
|
||||
if (mapping?.headers) {
|
||||
req.extraHeaders = mapping.headers;
|
||||
}
|
||||
|
||||
if (endpointProxy instanceof Function) {
|
||||
return endpointProxy(req, res, map);
|
||||
}
|
||||
|
||||
@@ -257,8 +257,9 @@ function Home({ initialSettings }) {
|
||||
<div className="relative container m-auto flex flex-col justify-start z-10 h-full">
|
||||
<div
|
||||
className={classNames(
|
||||
"flex flex-row flex-wrap justify-between",
|
||||
headerStyles[headerStyle]
|
||||
"flex flex-row flex-wrap justify-between",
|
||||
headerStyles[headerStyle],
|
||||
initialSettings.cardBlur !== undefined && headerStyle === "boxed" && `backdrop-blur${initialSettings.cardBlur.length ? '-' : ""}${initialSettings.cardBlur}`
|
||||
)}
|
||||
>
|
||||
<QuickLaunch
|
||||
@@ -274,7 +275,7 @@ function Home({ initialSettings }) {
|
||||
{widgets
|
||||
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
|
||||
.map((widget, i) => (
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false}} />
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false, cardBlur: initialSettings.cardBlur }} />
|
||||
))}
|
||||
|
||||
<div className={classNames(
|
||||
@@ -284,7 +285,7 @@ function Home({ initialSettings }) {
|
||||
{widgets
|
||||
.filter((widget) => rightAlignedWidgets.includes(widget.type))
|
||||
.map((widget, i) => (
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true}} />
|
||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true, cardBlur: initialSettings.cardBlur }} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -294,7 +294,13 @@ export function cleanServiceGroups(groups) {
|
||||
snapshotHost, // kopia
|
||||
snapshotPath,
|
||||
userEmail, // azuredevops
|
||||
repositoryId
|
||||
repositoryId,
|
||||
metric, // glances
|
||||
stream, // mjpeg
|
||||
fit,
|
||||
method, // openmediavault widget
|
||||
mappings, // customapi widget
|
||||
refreshInterval,
|
||||
} = cleanedService.widget;
|
||||
|
||||
let fieldsList = fields;
|
||||
@@ -358,6 +364,20 @@ export function cleanServiceGroups(groups) {
|
||||
if (snapshotHost) cleanedService.widget.snapshotHost = snapshotHost;
|
||||
if (snapshotPath) cleanedService.widget.snapshotPath = snapshotPath;
|
||||
}
|
||||
if (type === "glances") {
|
||||
if (metric) cleanedService.widget.metric = metric;
|
||||
}
|
||||
if (type === "mjpeg") {
|
||||
if (stream) cleanedService.widget.stream = stream;
|
||||
if (fit) cleanedService.widget.fit = fit;
|
||||
}
|
||||
if (type === "openmediavault") {
|
||||
if (method) cleanedService.widget.method = method;
|
||||
}
|
||||
if (type === "customapi") {
|
||||
if (mappings) cleanedService.widget.mappings = mappings;
|
||||
if (refreshInterval) cleanedService.widget.refreshInterval = refreshInterval;
|
||||
}
|
||||
}
|
||||
|
||||
return cleanedService;
|
||||
|
||||
@@ -32,6 +32,7 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
"authentik",
|
||||
"cloudflared",
|
||||
"ghostfolio",
|
||||
"mealie",
|
||||
"tailscale",
|
||||
"truenas",
|
||||
"pterodactyl",
|
||||
@@ -64,6 +65,8 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
}
|
||||
else if (widget.type === "azuredevops") {
|
||||
headers.Authorization = `Basic ${Buffer.from(`$:${widget.key}`).toString("base64")}`;
|
||||
} else if (widget.type === "glances") {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
} else {
|
||||
headers["X-API-Key"] = `${widget.key}`;
|
||||
}
|
||||
|
||||
@@ -20,11 +20,10 @@ export default async function genericProxyHandler(req, res, map) {
|
||||
if (widget) {
|
||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||
|
||||
let headers;
|
||||
const headers = req.extraHeaders ?? {};
|
||||
|
||||
if (widget.username && widget.password) {
|
||||
headers = {
|
||||
Authorization: `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`,
|
||||
};
|
||||
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
|
||||
}
|
||||
|
||||
const params = {
|
||||
|
||||
36
src/widgets/atsumeru/component.jsx
Normal file
36
src/widgets/atsumeru/component.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
|
||||
const { data: infoData, error: infoError } = useWidgetAPI(widget, "info");
|
||||
|
||||
if (infoError) {
|
||||
return <Container service={service} error={infoError} />;
|
||||
}
|
||||
|
||||
if (!infoData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="atsumeru.series" />
|
||||
<Block label="atsumeru.archives" />
|
||||
<Block label="atsumeru.chapters" />
|
||||
<Block label="atsumeru.categories" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="atsumeru.series" value={t("common.number", { value: infoData.stats.total_series })} />
|
||||
<Block label="atsumeru.archives" value={t("common.number", { value: infoData.stats.total_archives })} />
|
||||
<Block label="atsumeru.chapters" value={t("common.number", { value: infoData.stats.total_chapters })} />
|
||||
<Block label="atsumeru.categories" value={t("common.number", { value: infoData.stats.total_categories })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
14
src/widgets/atsumeru/widget.js
Normal file
14
src/widgets/atsumeru/widget.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/server/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
info: {
|
||||
endpoint: "info"
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -9,10 +9,10 @@ const widget = {
|
||||
endpoint: "core/users?page_size=1",
|
||||
},
|
||||
login: {
|
||||
endpoint: "events/events/per_month/?action=login&query={}",
|
||||
endpoint: "events/events/per_month/?action=login",
|
||||
},
|
||||
login_failed: {
|
||||
endpoint: "events/events/per_month/?action=login_failed&query={}",
|
||||
endpoint: "events/events/per_month/?action=login_failed",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -56,7 +56,7 @@ export default function Component({ service }) {
|
||||
value={t("common.number", {
|
||||
value: prData.value
|
||||
?.filter((item) => item.createdBy.uniqueName.toLowerCase() === userEmail.toLowerCase())
|
||||
.filter((item) => item.reviewers.some((reviewer) => reviewer.vote === 10)).length,
|
||||
.filter((item) => item.reviewers.some((reviewer) => [5,10].includes(reviewer.vote))).length
|
||||
})}
|
||||
/>}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const widget = {
|
||||
},
|
||||
|
||||
pipeline: {
|
||||
endpoint: "build/Builds?branchName={branchName}&definitions={definitionId}&$top=1"
|
||||
endpoint: "build/Builds?branchName={branchName}&definitions={definitionId}"
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
36
src/widgets/calibreweb/component.jsx
Normal file
36
src/widgets/calibreweb/component.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
const { data, error } = useWidgetAPI(widget, "stats");
|
||||
|
||||
if (error) {
|
||||
return <Container service={service} error={error} />;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="calibreweb.books" />
|
||||
<Block label="calibreweb.authors" />
|
||||
<Block label="calibreweb.categories" />
|
||||
<Block label="calibreweb.series" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="calibreweb.books" value={t("common.number", { value: data.books })} />
|
||||
<Block label="calibreweb.authors" value={t("common.number", { value: data.authors })} />
|
||||
<Block label="calibreweb.categories" value={t("common.number", { value: data.categories })} />
|
||||
<Block label="calibreweb.series" value={t("common.number", { value: data.series })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
14
src/widgets/calibreweb/widget.js
Normal file
14
src/widgets/calibreweb/widget.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import genericProxyHandler from "../../utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
stats: {
|
||||
endpoint: "opds/stats",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -2,16 +2,19 @@ import dynamic from "next/dynamic";
|
||||
|
||||
const components = {
|
||||
adguard: dynamic(() => import("./adguard/component")),
|
||||
atsumeru: dynamic(() => import("./atsumeru/component")),
|
||||
audiobookshelf: dynamic(() => import("./audiobookshelf/component")),
|
||||
authentik: dynamic(() => import("./authentik/component")),
|
||||
autobrr: dynamic(() => import("./autobrr/component")),
|
||||
azuredevops: dynamic(() => import("./azuredevops/component")),
|
||||
bazarr: dynamic(() => import("./bazarr/component")),
|
||||
caddy: dynamic(() => import("./caddy/component")),
|
||||
calibreweb: dynamic(() => import("./calibreweb/component")),
|
||||
changedetectionio: dynamic(() => import("./changedetectionio/component")),
|
||||
channelsdvrserver: dynamic(() => import("./channelsdvrserver/component")),
|
||||
cloudflared: dynamic(() => import("./cloudflared/component")),
|
||||
coinmarketcap: dynamic(() => import("./coinmarketcap/component")),
|
||||
customapi: dynamic(() => import("./customapi/component")),
|
||||
deluge: dynamic(() => import("./deluge/component")),
|
||||
diskstation: dynamic(() => import("./diskstation/component")),
|
||||
downloadstation: dynamic(() => import("./downloadstation/component")),
|
||||
@@ -24,6 +27,7 @@ const components = {
|
||||
freshrss: dynamic(() => import("./freshrss/component")),
|
||||
gamedig: dynamic(() => import("./gamedig/component")),
|
||||
ghostfolio: dynamic(() => import("./ghostfolio/component")),
|
||||
glances: dynamic(() => import("./glances/component")),
|
||||
gluetun: dynamic(() => import("./gluetun/component")),
|
||||
gotify: dynamic(() => import("./gotify/component")),
|
||||
grafana: dynamic(() => import("./grafana/component")),
|
||||
@@ -41,10 +45,12 @@ const components = {
|
||||
kopia: dynamic(() => import("./kopia/component")),
|
||||
lidarr: dynamic(() => import("./lidarr/component")),
|
||||
mastodon: dynamic(() => import("./mastodon/component")),
|
||||
mealie: dynamic(() => import("./mealie/component")),
|
||||
medusa: dynamic(() => import("./medusa/component")),
|
||||
minecraft: dynamic(() => import("./minecraft/component")),
|
||||
miniflux: dynamic(() => import("./miniflux/component")),
|
||||
mikrotik: dynamic(() => import("./mikrotik/component")),
|
||||
mjpeg: dynamic(() => import("./mjpeg/component")),
|
||||
moonraker: dynamic(() => import("./moonraker/component")),
|
||||
mylar: dynamic(() => import("./mylar/component")),
|
||||
navidrome: dynamic(() => import("./navidrome/component")),
|
||||
@@ -57,6 +63,7 @@ const components = {
|
||||
ombi: dynamic(() => import("./ombi/component")),
|
||||
opnsense: dynamic(() => import("./opnsense/component")),
|
||||
overseerr: dynamic(() => import("./overseerr/component")),
|
||||
openmediavault: dynamic(() => import("./openmediavault/component")),
|
||||
paperlessngx: dynamic(() => import("./paperlessngx/component")),
|
||||
pfsense: dynamic(() => import("./pfsense/component")),
|
||||
photoprism: dynamic(() => import("./photoprism/component")),
|
||||
|
||||
75
src/widgets/customapi/component.jsx
Normal file
75
src/widgets/customapi/component.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
function getValue(field, data) {
|
||||
let value = data;
|
||||
let lastField = field;
|
||||
let key = '';
|
||||
|
||||
while (typeof lastField === "object") {
|
||||
key = Object.keys(lastField)[0] ?? null;
|
||||
|
||||
if (key === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
value = value[key];
|
||||
lastField = lastField[key];
|
||||
}
|
||||
|
||||
if (typeof value === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return value[lastField] ?? null;
|
||||
}
|
||||
|
||||
function formatValue(t, mapping, value) {
|
||||
switch (mapping?.format) {
|
||||
case 'number':
|
||||
return t("common.number", { value: parseInt(value, 10) });
|
||||
case 'float':
|
||||
return t("common.number", { value });
|
||||
case 'percent':
|
||||
return t("common.percent", { value });
|
||||
case 'text':
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { mappings = [], refreshInterval = 10000 } = widget;
|
||||
const { data: customData, error: customError } = useWidgetAPI(widget, null, {
|
||||
refreshInterval: Math.max(1000, refreshInterval),
|
||||
});
|
||||
|
||||
if (customError) {
|
||||
return <Container service={service} error={customError} />;
|
||||
}
|
||||
|
||||
if (!customData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
{ mappings.slice(0,4).map(item => <Block label={item.label} key={item.field} />) }
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
{ mappings.slice(0,4).map(mapping => <Block
|
||||
label={mapping.label}
|
||||
key={mapping.field}
|
||||
value={formatValue(t, mapping, getValue(mapping.field, customData))}
|
||||
/>) }
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
8
src/widgets/customapi/widget.js
Normal file
8
src/widgets/customapi/widget.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -26,6 +26,7 @@ export default function Component({ service }) {
|
||||
if (!serverData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="gamedig.status"/>
|
||||
<Block label="gamedig.name"/>
|
||||
<Block label="gamedig.map"/>
|
||||
<Block label="gamedig.currentPlayers" />
|
||||
@@ -37,23 +38,25 @@ export default function Component({ service }) {
|
||||
);
|
||||
}
|
||||
|
||||
const status = serverData.online ? <span className="text-green-500">{t("gamedig.online")}</span> : <span className="text-red-500">{t("gamedig.offline")}</span>;
|
||||
const name = serverData.online ? serverData.name : "-";
|
||||
const map = serverData.online ? serverData.map : "-";
|
||||
const currentPlayers = serverData.online ? `${serverData.players} / ${serverData.maxplayers}` : "-";
|
||||
const players = serverData.online ? `${serverData.players}` : "-";
|
||||
const maxPlayers = serverData.online ? `${serverData.maxplayers}` : "-";
|
||||
const bots = serverData.online ? `${serverData.bots}` : "-";
|
||||
const ping = serverData.online ? `${serverData.ping}` : 0;
|
||||
const ping = serverData.online ? `${t("common.ms", { value: serverData.ping, style: "unit", unit: "millisecond" })}` : "-";
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="gamedig.status" value={status} />
|
||||
<Block label="gamedig.name" value={name} />
|
||||
<Block label="gamedig.map" value={map} />
|
||||
<Block label="gamedig.currentPlayers" value={currentPlayers} />
|
||||
<Block label="gamedig.players" value={players} />
|
||||
<Block label="gamedig.maxPlayers" value={maxPlayers} />
|
||||
<Block label="gamedig.bots" value={bots} />
|
||||
<Block label="gamedig.ping" value={t("common.ms", { value: ping, style: "unit", unit: "millisecond" })} />
|
||||
<Block label="gamedig.ping" value={ping} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
44
src/widgets/glances/component.jsx
Normal file
44
src/widgets/glances/component.jsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import Memory from "./metrics/memory";
|
||||
import Cpu from "./metrics/cpu";
|
||||
import Sensor from "./metrics/sensor";
|
||||
import Net from "./metrics/net";
|
||||
import Process from "./metrics/process";
|
||||
import Disk from "./metrics/disk";
|
||||
import GPU from "./metrics/gpu";
|
||||
import Info from "./metrics/info";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
|
||||
if (widget.metric === "info") {
|
||||
return <Info service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric === "memory") {
|
||||
return <Memory service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric === "process") {
|
||||
return <Process service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric.match(/^network:/)) {
|
||||
return <Net service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric.match(/^sensor:/)) {
|
||||
return <Sensor service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric.match(/^disk:/)) {
|
||||
return <Disk service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric.match(/^gpu:/)) {
|
||||
return <GPU service={service} />;
|
||||
}
|
||||
|
||||
if (widget.metric === "cpu") {
|
||||
return <Cpu service={service} />;
|
||||
}
|
||||
}
|
||||
7
src/widgets/glances/components/block.jsx
Normal file
7
src/widgets/glances/components/block.jsx
Normal file
@@ -0,0 +1,7 @@
|
||||
export default function Block({ position, children }) {
|
||||
return (
|
||||
<div className={`absolute ${position} z-20 text-sm pointer-events-none`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
48
src/widgets/glances/components/chart.jsx
Normal file
48
src/widgets/glances/components/chart.jsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { PureComponent } from "react";
|
||||
import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
|
||||
|
||||
import CustomTooltip from "./custom_tooltip";
|
||||
|
||||
class Chart extends PureComponent {
|
||||
render() {
|
||||
const { dataPoints, formatter, label } = this.props;
|
||||
|
||||
return (
|
||||
<div className="absolute -top-1 -left-1 h-[120px] w-[calc(100%+0.5em)] z-0">
|
||||
<div className="overflow-clip z-10 w-full h-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart data={dataPoints}>
|
||||
<defs>
|
||||
<linearGradient id="color" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="rgb(var(--color-500))" stopOpacity={0.4}/>
|
||||
<stop offset="95%" stopColor="rgb(var(--color-500))" stopOpacity={0.1}/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Area
|
||||
name={label[0]}
|
||||
isAnimationActive={false}
|
||||
type="monotoneX"
|
||||
dataKey="value"
|
||||
stroke="rgb(var(--color-500))"
|
||||
fillOpacity={1} fill="url(#color)"
|
||||
baseLine={0}
|
||||
/>
|
||||
<Tooltip
|
||||
allowEscapeViewBox={{ x: false, y: false }}
|
||||
formatter={formatter}
|
||||
content={<CustomTooltip formatter={formatter} />}
|
||||
classNames="rounded-md text-xs p-0.5"
|
||||
contentStyle={{
|
||||
backgroundColor: "rgb(var(--color-800))",
|
||||
color: "rgb(var(--color-100))"
|
||||
}}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Chart;
|
||||
63
src/widgets/glances/components/chart_dual.jsx
Normal file
63
src/widgets/glances/components/chart_dual.jsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import { PureComponent } from "react";
|
||||
import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
|
||||
|
||||
import CustomTooltip from "./custom_tooltip";
|
||||
|
||||
class ChartDual extends PureComponent {
|
||||
render() {
|
||||
const { dataPoints, formatter, stack, label, stackOffset } = this.props;
|
||||
|
||||
return (
|
||||
<div className="absolute -top-1 -left-1 h-[120px] w-[calc(100%+0.5em)] z-0">
|
||||
<div className="overflow-clip z-10 w-full h-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart data={dataPoints} stackOffset={stackOffset ?? "none"}>
|
||||
<defs>
|
||||
<linearGradient id="colorA" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="rgb(var(--color-800))" stopOpacity={0.8}/>
|
||||
<stop offset="95%" stopColor="rgb(var(--color-800))" stopOpacity={0.5}/>
|
||||
</linearGradient>
|
||||
<linearGradient id="colorB" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="rgb(var(--color-500))" stopOpacity={0.4}/>
|
||||
<stop offset="95%" stopColor="rgb(var(--color-500))" stopOpacity={0.1}/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<Area
|
||||
name={label[0]}
|
||||
stackId={(stack && stack[0]) ?? "1"}
|
||||
isAnimationActive={false}
|
||||
type="monotoneX"
|
||||
dataKey="a"
|
||||
stroke="rgb(var(--color-700))"
|
||||
fillOpacity={1} fill="url(#colorA)"
|
||||
/>
|
||||
<Area
|
||||
name={label[1]}
|
||||
stackId={(stack && stack[1]) ?? "1"}
|
||||
isAnimationActive={false}
|
||||
type="monotoneX"
|
||||
dataKey="b"
|
||||
stroke="rgb(var(--color-500))"
|
||||
fillOpacity={1} fill="url(#colorB)"
|
||||
/>
|
||||
<Tooltip
|
||||
allowEscapeViewBox={{ x: false, y: false }}
|
||||
formatter={formatter}
|
||||
content={<CustomTooltip formatter={formatter} />}
|
||||
classNames="rounded-md text-xs p-0.5"
|
||||
contentStyle={{
|
||||
backgroundColor: "rgb(var(--color-800))",
|
||||
color: "rgb(var(--color-100))"
|
||||
}}
|
||||
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ChartDual;
|
||||
9
src/widgets/glances/components/container.jsx
Normal file
9
src/widgets/glances/components/container.jsx
Normal file
@@ -0,0 +1,9 @@
|
||||
export default function Container({ children, className = "" }) {
|
||||
return (
|
||||
<div>
|
||||
{children}
|
||||
<div className={`absolute top-0 right-0 bottom-0 left-0 overflow-clip pointer-events-none ${className}`} />
|
||||
<div className="h-[68px] overflow-clip" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
15
src/widgets/glances/components/custom_tooltip.jsx
Normal file
15
src/widgets/glances/components/custom_tooltip.jsx
Normal file
@@ -0,0 +1,15 @@
|
||||
export default function Tooltip({ active, payload, formatter }) {
|
||||
if (active && payload && payload.length) {
|
||||
return (
|
||||
<div className="bg-theme-800/80 rounded-md text-theme-200 px-2 py-0">
|
||||
{payload.map((pld, id) => (
|
||||
<div key={Math.random()} className="first-of-type:pt-0 pt-0.5">
|
||||
<div>{formatter(pld.value)} {payload[id].name}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
9
src/widgets/glances/components/error.jsx
Normal file
9
src/widgets/glances/components/error.jsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
export default function Error() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return <div className="absolute bottom-2 left-2 z-20 text-red-400 text-xs opacity-75">
|
||||
{t("widget.api_error")}
|
||||
</div>;
|
||||
}
|
||||
91
src/widgets/glances/metrics/cpu.jsx
Normal file
91
src/widgets/glances/metrics/cpu.jsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
const Chart = dynamic(() => import("../components/chart"), { ssr: false });
|
||||
|
||||
const pointsLimit = 15;
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
|
||||
|
||||
const { data, error } = useWidgetAPI(service.widget, 'cpu', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
const { data: systemData, error: systemError } = useWidgetAPI(service.widget, 'system');
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setDataPoints((prevDataPoints) => {
|
||||
const newDataPoints = [...prevDataPoints, { value: data.total }];
|
||||
if (newDataPoints.length > pointsLimit) {
|
||||
newDataPoints.shift();
|
||||
}
|
||||
return newDataPoints;
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Chart
|
||||
dataPoints={dataPoints}
|
||||
label={[t("resources.used")]}
|
||||
formatter={(value) => t("common.number", {
|
||||
value,
|
||||
style: "unit",
|
||||
unit: "percent",
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
/>
|
||||
|
||||
{systemData && !systemError && (
|
||||
<Block position="bottom-3 left-3">
|
||||
{systemData.linux_distro && (
|
||||
<div className="text-xs opacity-50">
|
||||
{systemData.linux_distro}
|
||||
</div>
|
||||
)}
|
||||
{systemData.os_version && (
|
||||
<div className="text-xs opacity-50">
|
||||
{systemData.os_version}
|
||||
</div>
|
||||
)}
|
||||
{systemData.hostname && (
|
||||
<div className="text-xs opacity-75">
|
||||
{systemData.hostname}
|
||||
</div>
|
||||
)}
|
||||
</Block>
|
||||
)}
|
||||
|
||||
<Block position="bottom-3 right-3">
|
||||
<div className="text-xs font-bold opacity-75">
|
||||
{t("common.number", {
|
||||
value: data.total,
|
||||
style: "unit",
|
||||
unit: "percent",
|
||||
maximumFractionDigits: 0,
|
||||
})} {t("resources.used")}
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
102
src/widgets/glances/metrics/disk.jsx
Normal file
102
src/widgets/glances/metrics/disk.jsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
|
||||
|
||||
const pointsLimit = 15;
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
const [, diskName] = widget.metric.split(':');
|
||||
|
||||
const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ read_bytes: 0, write_bytes: 0, time_since_update: 0 }, 0, pointsLimit));
|
||||
const [ratePoints, setRatePoints] = useState(new Array(pointsLimit).fill({ a: 0, b: 0 }, 0, pointsLimit));
|
||||
|
||||
const { data, error } = useWidgetAPI(service.widget, 'diskio', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
const calculateRates = (d) => d.map(item => ({
|
||||
a: item.read_bytes / item.time_since_update,
|
||||
b: item.write_bytes / item.time_since_update
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const diskData = data.find((item) => item.disk_name === diskName);
|
||||
|
||||
setDataPoints((prevDataPoints) => {
|
||||
const newDataPoints = [...prevDataPoints, diskData];
|
||||
if (newDataPoints.length > pointsLimit) {
|
||||
newDataPoints.shift();
|
||||
}
|
||||
return newDataPoints;
|
||||
});
|
||||
}
|
||||
}, [data, diskName]);
|
||||
|
||||
useEffect(() => {
|
||||
setRatePoints(calculateRates(dataPoints));
|
||||
}, [dataPoints]);
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
const diskData = data.find((item) => item.disk_name === diskName);
|
||||
|
||||
if (!diskData) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
const diskRates = calculateRates(dataPoints);
|
||||
const currentRate = diskRates[diskRates.length - 1];
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ChartDual
|
||||
dataPoints={ratePoints}
|
||||
label={[t("glances.read"), t("glances.write")]}
|
||||
max={diskData.critical}
|
||||
formatter={(value) => t("common.bitrate", {
|
||||
value,
|
||||
})}
|
||||
/>
|
||||
|
||||
{currentRate && !error && (
|
||||
<Block position="bottom-3 left-3">
|
||||
<div className="text-xs opacity-50">
|
||||
{t("common.bitrate", {
|
||||
value: currentRate.a,
|
||||
})} {t("glances.read")}
|
||||
</div>
|
||||
<div className="text-xs opacity-50">
|
||||
{t("common.bitrate", {
|
||||
value: currentRate.b,
|
||||
})} {t("glances.write")}
|
||||
</div>
|
||||
</Block>
|
||||
)}
|
||||
|
||||
<Block position="bottom-3 right-3">
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.bitrate", {
|
||||
value: currentRate.a + currentRate.b,
|
||||
})}
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
104
src/widgets/glances/metrics/gpu.jsx
Normal file
104
src/widgets/glances/metrics/gpu.jsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
|
||||
|
||||
const pointsLimit = 15;
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
const [, gpuName] = widget.metric.split(':');
|
||||
|
||||
const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ a: 0, b: 0 }, 0, pointsLimit));
|
||||
|
||||
const { data, error } = useWidgetAPI(widget, 'gpu', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const gpuData = data.find((item) => item[item.key] == gpuName);
|
||||
|
||||
if (gpuData) {
|
||||
setDataPoints((prevDataPoints) => {
|
||||
const newDataPoints = [...prevDataPoints, { a: gpuData.mem, b: gpuData.proc }];
|
||||
if (newDataPoints.length > pointsLimit) {
|
||||
newDataPoints.shift();
|
||||
}
|
||||
return newDataPoints;
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [data, gpuName]);
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const gpuData = data.find((item) => item[item.key] == gpuName);
|
||||
|
||||
if (!gpuData) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ChartDual
|
||||
dataPoints={dataPoints}
|
||||
label={[t("glances.mem"), t("glances.gpu")]}
|
||||
stack={['mem', 'proc']}
|
||||
formatter={(value) => t("common.percent", {
|
||||
value,
|
||||
maximumFractionDigits: 1,
|
||||
})}
|
||||
/>
|
||||
|
||||
<Block position="bottom-3 left-3">
|
||||
{gpuData && gpuData.name && (
|
||||
<div className="text-xs opacity-50">
|
||||
{gpuData.name}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.number", {
|
||||
value: gpuData.mem,
|
||||
maximumFractionDigits: 1,
|
||||
})}% {t("glances.mem")} {t("resources.used")}
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block position="bottom-3 right-3">
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.number", {
|
||||
value: gpuData.proc,
|
||||
maximumFractionDigits: 1,
|
||||
})}% {t("glances.gpu")}
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block position="top-3 right-3">
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.number", {
|
||||
value: gpuData.temperature,
|
||||
maximumFractionDigits: 1,
|
||||
})}°
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
115
src/widgets/glances/metrics/info.jsx
Normal file
115
src/widgets/glances/metrics/info.jsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { data: quicklookData, errorL: quicklookError } = useWidgetAPI(service.widget, 'quicklook', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
const { data: systemData, errorL: systemError } = useWidgetAPI(service.widget, 'system', {
|
||||
refreshInterval: 30000,
|
||||
});
|
||||
|
||||
if (quicklookError) {
|
||||
return <Container><Error error={quicklookError} /></Container>;
|
||||
}
|
||||
|
||||
if (systemError) {
|
||||
return <Container><Error error={systemError} /></Container>;
|
||||
}
|
||||
|
||||
const dataCharts = [];
|
||||
|
||||
if (quicklookData) {
|
||||
quicklookData.percpu.forEach((cpu, index) => {
|
||||
dataCharts.push({
|
||||
name: `CPU ${index}`,
|
||||
cpu: cpu.total,
|
||||
mem: quicklookData.mem,
|
||||
swap: quicklookData.swap,
|
||||
proc: quicklookData.cpu,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Container className="bg-gradient-to-br from-theme-500/30 via-theme-600/20 to-theme-700/10">
|
||||
<Block position="top-3 right-3">
|
||||
{quicklookData && quicklookData.cpu_name && (
|
||||
<div className="text-[0.6rem] opacity-50">
|
||||
{quicklookData.cpu_name}
|
||||
</div>
|
||||
)}
|
||||
</Block>
|
||||
<Block position="bottom-3 left-3">
|
||||
{systemData && systemData.linux_distro && (
|
||||
<div className="text-xs opacity-50">
|
||||
{systemData.linux_distro}
|
||||
</div>
|
||||
)}
|
||||
{systemData && systemData.os_version && (
|
||||
<div className="text-xs opacity-50">
|
||||
{systemData.os_version}
|
||||
</div>
|
||||
)}
|
||||
{systemData && systemData.hostname && (
|
||||
<div className="text-xs opacity-75">
|
||||
{systemData.hostname}
|
||||
</div>
|
||||
)}
|
||||
</Block>
|
||||
|
||||
<Block position="bottom-3 right-3 w-[4rem]">
|
||||
{quicklookData && quicklookData.cpu && (
|
||||
<div className="text-xs opacity-25 flex place-content-between">
|
||||
<div>{t("glances.cpu")}</div>
|
||||
<div className="opacity-75">
|
||||
{t("common.number", {
|
||||
value: quicklookData.cpu,
|
||||
style: "unit",
|
||||
unit: "percent",
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{quicklookData && quicklookData.mem && (
|
||||
<div className="text-xs opacity-25 flex place-content-between">
|
||||
<div>{t("glances.mem")}</div>
|
||||
<div className="opacity-75">
|
||||
{t("common.number", {
|
||||
value: quicklookData.mem,
|
||||
style: "unit",
|
||||
unit: "percent",
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{quicklookData && quicklookData.swap && (
|
||||
<div className="text-xs opacity-25 flex place-content-between">
|
||||
<div>{t("glances.swap")}</div>
|
||||
<div className="opacity-75">
|
||||
{t("common.number", {
|
||||
value: quicklookData.swap,
|
||||
style: "unit",
|
||||
unit: "percent",
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
92
src/widgets/glances/metrics/memory.jsx
Normal file
92
src/widgets/glances/metrics/memory.jsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
|
||||
|
||||
const pointsLimit = 15;
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
|
||||
|
||||
const { data, error } = useWidgetAPI(service.widget, 'mem', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setDataPoints((prevDataPoints) => {
|
||||
const newDataPoints = [...prevDataPoints, { a: data.used, b: data.free }];
|
||||
if (newDataPoints.length > pointsLimit) {
|
||||
newDataPoints.shift();
|
||||
}
|
||||
return newDataPoints;
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ChartDual
|
||||
dataPoints={dataPoints}
|
||||
max={data.total}
|
||||
label={[t("resources.used"), t("resources.free")]}
|
||||
formatter={(value) => t("common.bytes", {
|
||||
value,
|
||||
maximumFractionDigits: 0,
|
||||
binary: true,
|
||||
})}
|
||||
/>
|
||||
|
||||
{data && !error && (
|
||||
<Block position="bottom-3 left-3">
|
||||
{data.free && (
|
||||
<div className="text-xs opacity-50">
|
||||
{t("common.bytes", {
|
||||
value: data.free,
|
||||
maximumFractionDigits: 0,
|
||||
binary: true,
|
||||
})} {t("resources.free")}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{data.total && (
|
||||
<div className="text-xs opacity-50">
|
||||
{t("common.bytes", {
|
||||
value: data.total,
|
||||
maximumFractionDigits: 0,
|
||||
binary: true,
|
||||
})} {t("resources.total")}
|
||||
</div>
|
||||
)}
|
||||
</Block>
|
||||
)}
|
||||
|
||||
<Block position="bottom-3 right-3">
|
||||
<div className="text-xs font-bold opacity-75">
|
||||
{t("common.bytes", {
|
||||
value: data.used,
|
||||
maximumFractionDigits: 0,
|
||||
binary: true,
|
||||
})} {t("resources.used")}
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
92
src/widgets/glances/metrics/net.jsx
Normal file
92
src/widgets/glances/metrics/net.jsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
|
||||
|
||||
const pointsLimit = 15;
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
const [, interfaceName] = widget.metric.split(':');
|
||||
|
||||
const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
|
||||
|
||||
const { data, error } = useWidgetAPI(widget, 'network', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const interfaceData = data.find((item) => item[item.key] === interfaceName);
|
||||
|
||||
if (interfaceData) {
|
||||
setDataPoints((prevDataPoints) => {
|
||||
const newDataPoints = [...prevDataPoints, { a: interfaceData.tx, b: interfaceData.rx }];
|
||||
if (newDataPoints.length > pointsLimit) {
|
||||
newDataPoints.shift();
|
||||
}
|
||||
return newDataPoints;
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [data, interfaceName]);
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
const interfaceData = data.find((item) => item[item.key] === interfaceName);
|
||||
|
||||
if (!interfaceData) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ChartDual
|
||||
dataPoints={dataPoints}
|
||||
label={[t("docker.tx"), t("docker.rx")]}
|
||||
formatter={(value) => t("common.byterate", {
|
||||
value,
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
/>
|
||||
|
||||
<Block position="bottom-3 left-3">
|
||||
{interfaceData && interfaceData.interface_name && (
|
||||
<div className="text-xs opacity-50">
|
||||
{interfaceData.interface_name}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.bitrate", {
|
||||
value: interfaceData.tx,
|
||||
maximumFractionDigits: 0,
|
||||
})} {t("docker.tx")}
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block position="bottom-3 right-3">
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.bitrate", {
|
||||
value: interfaceData.rx,
|
||||
maximumFractionDigits: 0,
|
||||
})} {t("docker.rx")}
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
66
src/widgets/glances/metrics/process.jsx
Normal file
66
src/widgets/glances/metrics/process.jsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
const statusMap = {
|
||||
"R": <ResolvedIcon icon="mdi-circle" width={32} height={32} />, // running
|
||||
"S": <ResolvedIcon icon="mdi-circle-outline" width={32} height={32} />, // sleeping
|
||||
"D": <ResolvedIcon icon="mdi-circle-double" width={32} height={32} />, // disk sleep
|
||||
"Z": <ResolvedIcon icon="mdi-circle-opacity" width={32} height={32} />, // zombie
|
||||
"T": <ResolvedIcon icon="mdi-decagram-outline" width={32} height={32} />, // traced
|
||||
"t": <ResolvedIcon icon="mdi-hexagon-outline" width={32} height={32} />, // traced
|
||||
"X": <ResolvedIcon icon="mdi-rhombus-outline" width={32} height={32} />, // dead
|
||||
};
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { data, error } = useWidgetAPI(service.widget, 'processlist', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
data.splice(5);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Block position="top-4 right-3 left-3">
|
||||
<div className="flex items-center text-xs">
|
||||
<div className="grow" />
|
||||
<div className="w-14 text-right italic">{t("resources.cpu")}</div>
|
||||
<div className="w-14 text-right">{t("resources.mem")}</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block position="bottom-4 right-3 left-3">
|
||||
<div className="pointer-events-none text-theme-900 dark:text-theme-200">
|
||||
{ data.map((item) => <div key={item.pid} className="text-[0.75rem] h-[0.8rem]">
|
||||
<div className="flex items-center">
|
||||
<div className="w-3 h-3 mr-1.5 opacity-50">
|
||||
{statusMap[item.status]}
|
||||
</div>
|
||||
<div className="opacity-75 grow">{item.name}</div>
|
||||
<div className="opacity-25 w-14 text-right">{item.cpu_percent.toFixed(1)}%</div>
|
||||
<div className="opacity-25 w-14 text-right">{t("common.bytes", {
|
||||
value: item.memory_info[0],
|
||||
maximumFractionDigits: 0,
|
||||
})}</div>
|
||||
</div>
|
||||
</div>) }
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
88
src/widgets/glances/metrics/sensor.jsx
Normal file
88
src/widgets/glances/metrics/sensor.jsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Error from "../components/error";
|
||||
import Container from "../components/container";
|
||||
import Block from "../components/block";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
const Chart = dynamic(() => import("../components/chart"), { ssr: false });
|
||||
|
||||
const pointsLimit = 15;
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
const [, sensorName] = widget.metric.split(':');
|
||||
|
||||
const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
|
||||
|
||||
const { data, error } = useWidgetAPI(service.widget, 'sensors', {
|
||||
refreshInterval: 1000,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
const sensorData = data.find((item) => item.label === sensorName);
|
||||
setDataPoints((prevDataPoints) => {
|
||||
const newDataPoints = [...prevDataPoints, { value: sensorData.value }];
|
||||
if (newDataPoints.length > pointsLimit) {
|
||||
newDataPoints.shift();
|
||||
}
|
||||
return newDataPoints;
|
||||
});
|
||||
}
|
||||
}, [data, sensorName]);
|
||||
|
||||
if (error) {
|
||||
return <Container><Error error={error} /></Container>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
const sensorData = data.find((item) => item.label === sensorName);
|
||||
|
||||
if (!sensorData) {
|
||||
return <Container><Block position="bottom-3 left-3">-</Block></Container>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Chart
|
||||
dataPoints={dataPoints}
|
||||
label={[sensorData.unit]}
|
||||
max={sensorData.critical}
|
||||
formatter={(value) => t("common.number", {
|
||||
value,
|
||||
})}
|
||||
/>
|
||||
|
||||
{sensorData && !error && (
|
||||
<Block position="bottom-3 left-3">
|
||||
{sensorData.warning && (
|
||||
<div className="text-xs opacity-50">
|
||||
{sensorData.warning}{sensorData.unit} {t("glances.warn")}
|
||||
</div>
|
||||
)}
|
||||
{sensorData.critical && (
|
||||
<div className="text-xs opacity-50">
|
||||
{sensorData.critical} {sensorData.unit} {t("glances.crit")}
|
||||
</div>
|
||||
)}
|
||||
</Block>
|
||||
)}
|
||||
|
||||
<Block position="bottom-3 right-3">
|
||||
<div className="text-xs opacity-75">
|
||||
{t("common.number", {
|
||||
value: sensorData.value,
|
||||
})} {sensorData.unit}
|
||||
</div>
|
||||
</Block>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
8
src/widgets/glances/widget.js
Normal file
8
src/widgets/glances/widget.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/3/{endpoint}",
|
||||
proxyHandler: credentialedProxyHandler,
|
||||
};
|
||||
|
||||
export default widget;
|
||||
33
src/widgets/mealie/component.jsx
Normal file
33
src/widgets/mealie/component.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
|
||||
const { data: mealieData, error: mealieError } = useWidgetAPI(widget);
|
||||
|
||||
if (mealieError || mealieData?.statusCode === 401) {
|
||||
return <Container service={service} error={mealieError ?? mealieData} />;
|
||||
}
|
||||
|
||||
if (!mealieData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="mealie.recipes" />
|
||||
<Block label="mealie.users" />
|
||||
<Block label="mealie.categories" />
|
||||
<Block label="mealie.tags" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="mealie.recipes" value={mealieData.totalRecipes} />
|
||||
<Block label="mealie.users" value={mealieData.totalUsers} />
|
||||
<Block label="mealie.categories" value={mealieData.totalCategories} />
|
||||
<Block label="mealie.tags" value={mealieData.totalTags} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
8
src/widgets/mealie/widget.js
Normal file
8
src/widgets/mealie/widget.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/groups/statistics",
|
||||
proxyHandler: credentialedProxyHandler,
|
||||
};
|
||||
|
||||
export default widget;
|
||||
17
src/widgets/mjpeg/component.jsx
Normal file
17
src/widgets/mjpeg/component.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import Image from "next/image";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
const { stream, fit = "contain" } = widget;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="absolute top-0 bottom-0 right-0 left-0">
|
||||
<Image layout="fill" objectFit="fill" className="blur-md" src={stream} alt="stream" />
|
||||
<Image layout="fill" objectFit={fit} className="drop-shadow-2xl" src={stream} alt="stream" />
|
||||
</div>
|
||||
<div className="absolute top-0 right-0 bottom-0 left-0 overflow-clip shadow-[inset_0_0_200px_#000] shadow-theme-700/10 dark:shadow-theme-900/10" />
|
||||
<div className="h-[68px] overflow-clip" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
8
src/widgets/mjpeg/widget.js
Normal file
8
src/widgets/mjpeg/widget.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -31,7 +31,7 @@ export default function Component({ service }) {
|
||||
const printingStateFalgs = ["Printing", "Paused", "Pausing", "Resuming"];
|
||||
|
||||
if (printingStateFalgs.includes(state)) {
|
||||
const { completion } = jobStats.progress;
|
||||
const { completion } = jobStats?.progress ?? undefined;
|
||||
|
||||
if (!jobStats || !completion) {
|
||||
return (
|
||||
|
||||
16
src/widgets/openmediavault/component.jsx
Normal file
16
src/widgets/openmediavault/component.jsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import ServicesGetStatus from "./methods/services_get_status";
|
||||
import SmartGetList from "./methods/smart_get_list";
|
||||
import DownloaderGetDownloadList from "./methods/downloader_get_downloadlist";
|
||||
|
||||
export default function Component({ service }) {
|
||||
switch (service.widget.method) {
|
||||
case "services.getStatus":
|
||||
return <ServicesGetStatus service={service} />;
|
||||
case "smart.getListBg":
|
||||
return <SmartGetList service={service} />;
|
||||
case "downloader.getDownloadList":
|
||||
return <DownloaderGetDownloadList service={service} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
|
||||
const downloadReduce = (acc, e) => {
|
||||
if (e.downloading) {
|
||||
return acc + 1;
|
||||
}
|
||||
return acc;
|
||||
};
|
||||
|
||||
const items = [
|
||||
{ label: "openmediavault.downloading", getNumber: (data) => (!data ? null : data.reduce(downloadReduce, 0)) },
|
||||
{ label: "openmediavault.total", getNumber: (data) => (!data ? null : data?.length) },
|
||||
];
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { data, error } = useWidgetAPI(service.widget);
|
||||
|
||||
if (error) {
|
||||
return <Container service={service} error={error} />;
|
||||
}
|
||||
|
||||
const itemsWithData = items.map((item) => ({
|
||||
...item,
|
||||
number: item.getNumber(data?.response?.data),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
{itemsWithData.map((e) => (
|
||||
<Block key={e.label} label={e.label} value={e.number} />
|
||||
))}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
43
src/widgets/openmediavault/methods/services_get_status.jsx
Normal file
43
src/widgets/openmediavault/methods/services_get_status.jsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
|
||||
const isRunningReduce = (acc, e) => {
|
||||
if (e.running) {
|
||||
return acc + 1;
|
||||
}
|
||||
return acc;
|
||||
};
|
||||
const notRunningReduce = (acc, e) => {
|
||||
if (!e.running) {
|
||||
return acc + 1;
|
||||
}
|
||||
return acc;
|
||||
};
|
||||
|
||||
const items = [
|
||||
{ label: "openmediavault.running", getNumber: (data) => (!data ? null : data.reduce(isRunningReduce, 0)) },
|
||||
{ label: "openmediavault.stopped", getNumber: (data) => (!data ? null : data.reduce(notRunningReduce, 0)) },
|
||||
{ label: "openmediavault.total", getNumber: (data) => (!data ? null : data?.length) },
|
||||
];
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { data, error } = useWidgetAPI(service.widget);
|
||||
|
||||
if (error) {
|
||||
return <Container service={service} error={error} />;
|
||||
}
|
||||
|
||||
const itemsWithData = items.map((item) => ({
|
||||
...item,
|
||||
number: item.getNumber(data?.response?.data),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
{itemsWithData.map((e) => (
|
||||
<Block key={e.label} label={e.label} value={e.number} />
|
||||
))}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
42
src/widgets/openmediavault/methods/smart_get_list.jsx
Normal file
42
src/widgets/openmediavault/methods/smart_get_list.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
|
||||
const passedReduce = (acc, e) => {
|
||||
if (e.overallstatus === "GOOD") {
|
||||
return acc + 1;
|
||||
}
|
||||
return acc;
|
||||
};
|
||||
const failedReduce = (acc, e) => {
|
||||
if (e.overallstatus !== "GOOD") {
|
||||
return acc + 1;
|
||||
}
|
||||
return acc;
|
||||
};
|
||||
|
||||
const items = [
|
||||
{ label: "openmediavault.passed", getNumber: (data) => (!data ? null : data.reduce(passedReduce, 0)) },
|
||||
{ label: "openmediavault.failed", getNumber: (data) => (!data ? null : data.reduce(failedReduce, 0)) },
|
||||
];
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { data, error } = useWidgetAPI(service.widget);
|
||||
|
||||
if (error) {
|
||||
return <Container service={service} error={error} />;
|
||||
}
|
||||
|
||||
const itemsWithData = items.map((item) => ({
|
||||
...item,
|
||||
number: item.getNumber(JSON.parse(data?.response?.output || "{}")?.data),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
{itemsWithData.map((e) => (
|
||||
<Block key={e.label} label={e.label} value={e.number} />
|
||||
))}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
151
src/widgets/openmediavault/proxy.js
Normal file
151
src/widgets/openmediavault/proxy.js
Normal file
@@ -0,0 +1,151 @@
|
||||
import { formatApiCall } from "utils/proxy/api-helpers";
|
||||
import { httpProxy } from "utils/proxy/http";
|
||||
import getServiceWidget from "utils/config/service-helpers";
|
||||
import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar";
|
||||
import createLogger from "utils/logger";
|
||||
import widgets from "widgets/widgets";
|
||||
|
||||
const PROXY_NAME = "OMVProxyHandler";
|
||||
const BG_MAX_RETRIES = 50;
|
||||
const BG_POLL_PERIOD = 500;
|
||||
|
||||
const logger = createLogger(PROXY_NAME);
|
||||
|
||||
async function getWidget(req) {
|
||||
const { group, service } = req.query;
|
||||
|
||||
if (!group || !service) {
|
||||
logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
|
||||
return null;
|
||||
}
|
||||
|
||||
const widget = await getServiceWidget(group, service);
|
||||
|
||||
if (!widget) {
|
||||
logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
|
||||
return null;
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
async function rpc(url, request) {
|
||||
const params = {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(request),
|
||||
};
|
||||
setCookieHeader(url, params);
|
||||
const [status, contentType, data, headers] = await httpProxy(url, params);
|
||||
|
||||
return { status, contentType, data, headers };
|
||||
}
|
||||
|
||||
async function poll(attemptsLeft, makeReqByPos, pos = 0) {
|
||||
if (attemptsLeft <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const resp = await makeReqByPos(pos);
|
||||
|
||||
const data = JSON.parse(resp.data.toString()).response;
|
||||
if (data.running === true || data.outputPending) {
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(resolve, BG_POLL_PERIOD);
|
||||
});
|
||||
return poll(attemptsLeft - 1, makeReqByPos, data.pos);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
async function tryLogin(widget) {
|
||||
const url = new URL(formatApiCall(widgets?.[widget.type]?.api, { ...widget }));
|
||||
const { username, password } = widget;
|
||||
const resp = await rpc(url, {
|
||||
method: "login",
|
||||
service: "session",
|
||||
params: { username, password },
|
||||
});
|
||||
|
||||
if (resp.status !== 200) {
|
||||
logger.error("HTTP %d logging in to OpenMediaVault. Data: %s", resp.status, resp.data);
|
||||
return [false, resp];
|
||||
}
|
||||
|
||||
const json = JSON.parse(resp.data.toString());
|
||||
if (json.response.authenticated !== true) {
|
||||
logger.error("Login error in OpenMediaVault. Data: %s", resp.data);
|
||||
resp.status = 401;
|
||||
return [false, resp];
|
||||
}
|
||||
|
||||
return [true, resp];
|
||||
}
|
||||
async function processBg(url, filename) {
|
||||
const resp = await poll(BG_MAX_RETRIES, (pos) =>
|
||||
rpc(url, {
|
||||
service: "exec",
|
||||
method: "getOutput",
|
||||
params: { pos, filename },
|
||||
})
|
||||
);
|
||||
|
||||
if (resp == null) {
|
||||
const errText = "The maximum number of attempts to receive a response from Bg data has been exceeded.";
|
||||
logger.error(errText);
|
||||
return errText;
|
||||
}
|
||||
if (resp.status !== 200) {
|
||||
logger.error("HTTP %d getting Bg data from OpenMediaVault RPC. Data: %s", resp.status, resp.data);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
export default async function proxyHandler(req, res) {
|
||||
const widget = await getWidget(req);
|
||||
if (!widget) {
|
||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||
}
|
||||
|
||||
const api = widgets?.[widget.type]?.api;
|
||||
if (!api) {
|
||||
return res.status(403).json({ error: "Service does not support RPC calls" });
|
||||
}
|
||||
|
||||
const url = new URL(formatApiCall(api, { ...widget }));
|
||||
const [service, method] = widget.method.split(".");
|
||||
const rpcReq = { params: { limit: -1, start: 0 }, service, method };
|
||||
|
||||
let resp = await rpc(url, rpcReq);
|
||||
|
||||
if (resp.status === 401) {
|
||||
logger.debug("Session not authenticated.");
|
||||
const [success, lResp] = await tryLogin(widget);
|
||||
|
||||
if (success) {
|
||||
addCookieToJar(url, lResp.headers);
|
||||
} else {
|
||||
res.status(lResp.status).json({ error: { message: `HTTP Error ${lResp.status}`, url, data: lResp.data } });
|
||||
}
|
||||
|
||||
logger.debug("Retrying OpenMediaVault request after login.");
|
||||
resp = await rpc(url, rpcReq);
|
||||
}
|
||||
|
||||
if (resp.status !== 200) {
|
||||
logger.error("HTTP %d getting data from OpenMediaVault RPC. Data: %s", resp.status, resp.data);
|
||||
return res.status(resp.status).json({ error: { message: `HTTP Error ${resp.status}`, url, data: resp.data } });
|
||||
}
|
||||
|
||||
if (method.endsWith("Bg")) {
|
||||
const json = JSON.parse(resp.data.toString());
|
||||
const bgResp = await processBg(url, json.response);
|
||||
|
||||
if (typeof bgResp === "string") {
|
||||
return res.status(400).json({ error: bgResp });
|
||||
}
|
||||
return res.status(bgResp.status).send(bgResp.data);
|
||||
}
|
||||
|
||||
return res.status(resp.status).send(resp.data);
|
||||
}
|
||||
8
src/widgets/openmediavault/widget.js
Normal file
8
src/widgets/openmediavault/widget.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import proxyHandler from "./proxy";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/rpc.php",
|
||||
proxyHandler,
|
||||
};
|
||||
|
||||
export default widget;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user