mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-07 09:35:54 -08:00
Compare commits
416 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f63a5a1d5 | ||
|
|
679704949e | ||
|
|
e46d291c78 | ||
|
|
54b01b302b | ||
|
|
aa1726df05 | ||
|
|
810390c1be | ||
|
|
b7b5e4a117 | ||
|
|
e99a38063c | ||
|
|
dacfc30cea | ||
|
|
7803b815af | ||
|
|
3500c81a1c | ||
|
|
6aa77faea0 | ||
|
|
3ca720953a | ||
|
|
4396d0a5f1 | ||
|
|
87ec2ea20c | ||
|
|
700fb09e64 | ||
|
|
3736194c7c | ||
|
|
08c9379eba | ||
|
|
040e784526 | ||
|
|
443a073ae3 | ||
|
|
b792ba8267 | ||
|
|
349f2a1c66 | ||
|
|
7750a1c1f4 | ||
|
|
631e7adb7c | ||
|
|
9a70bb7e3d | ||
|
|
c08ca4ce44 | ||
|
|
cddf393714 | ||
|
|
fe0eeb5332 | ||
|
|
9ad78f8204 | ||
|
|
87be6b1105 | ||
|
|
fc799000d3 | ||
|
|
d4ee7962ce | ||
|
|
762a02f287 | ||
|
|
cc1f580e46 | ||
|
|
765c6f9b99 | ||
|
|
94f43b1210 | ||
|
|
ba4cbad601 | ||
|
|
ab75534d3e | ||
|
|
a697a6e8d4 | ||
|
|
5c3d7af929 | ||
|
|
5b8d781eb3 | ||
|
|
2c8ab6e9d6 | ||
|
|
fb9dc36226 | ||
|
|
e549fc50af | ||
|
|
1b847136ab | ||
|
|
94e156b078 | ||
|
|
00aacba639 | ||
|
|
7ebd509036 | ||
|
|
b335c9603c | ||
|
|
4e58341443 | ||
|
|
3b0931c012 | ||
|
|
513d187567 | ||
|
|
0d9068c6fa | ||
|
|
1f756c1a67 | ||
|
|
0e18d14eb1 | ||
|
|
ccf8d2c611 | ||
|
|
cad721dee2 | ||
|
|
a3e21e56c0 | ||
|
|
e0213269c0 | ||
|
|
d0f83aa30a | ||
|
|
acbc66f26b | ||
|
|
ee1fc2fa55 | ||
|
|
f0231e17fd | ||
|
|
2182ffb894 | ||
|
|
fbbf007fc7 | ||
|
|
ba87f8b64d | ||
|
|
0ab30b711c | ||
|
|
63de2888c4 | ||
|
|
bdbe81268b | ||
|
|
1dd7947c71 | ||
|
|
43a11eadfc | ||
|
|
3a27486c34 | ||
|
|
54fb201874 | ||
|
|
977c65f911 | ||
|
|
8bdd03a632 | ||
|
|
6f34aaefa4 | ||
|
|
4017997448 | ||
|
|
82c290d5d8 | ||
|
|
4417161e0c | ||
|
|
2b41121a80 | ||
|
|
b1a0b4ebcf | ||
|
|
5a8ae8a626 | ||
|
|
59e966c6dd | ||
|
|
4ff2799c0e | ||
|
|
789831ff57 | ||
|
|
b4602a2e4b | ||
|
|
6722c3712d | ||
|
|
d650d1cae5 | ||
|
|
a8084e9e80 | ||
|
|
458d376ce5 | ||
|
|
4c658cf717 | ||
|
|
8dff267305 | ||
|
|
d69dda762a | ||
|
|
b0b5d8b381 | ||
|
|
1662302b13 | ||
|
|
ae781a942e | ||
|
|
f5f6c57ba8 | ||
|
|
ca6065d428 | ||
|
|
7602ec8479 | ||
|
|
cf4c8885a1 | ||
|
|
644014419c | ||
|
|
922df3288b | ||
|
|
195ebf2067 | ||
|
|
f363f90da5 | ||
|
|
667b88a450 | ||
|
|
3b0e2797ca | ||
|
|
cbded542f9 | ||
|
|
e9610f7c34 | ||
|
|
31fec3cead | ||
|
|
38d81b654e | ||
|
|
17e7d449b0 | ||
|
|
3249e03bf6 | ||
|
|
817e5b630e | ||
|
|
953ade7506 | ||
|
|
a834d2a4e4 | ||
|
|
b419ddde2d | ||
|
|
bb422179e5 | ||
|
|
efa35b4bd4 | ||
|
|
450babf95d | ||
|
|
1452d846e4 | ||
|
|
4c646c660b | ||
|
|
40657049a6 | ||
|
|
0c8fe35af1 | ||
|
|
bf1b874368 | ||
|
|
207bd04489 | ||
|
|
b4ca671902 | ||
|
|
4062671466 | ||
|
|
ecccab9ebf | ||
|
|
5c8b821732 | ||
|
|
2400357666 | ||
|
|
b7e58ae07b | ||
|
|
3f523111b3 | ||
|
|
874a51f56c | ||
|
|
efe763fff8 | ||
|
|
05c0f39354 | ||
|
|
3722caee73 | ||
|
|
303acc24f6 | ||
|
|
4a747f1f93 | ||
|
|
caa97f774e | ||
|
|
805d57bf31 | ||
|
|
3e86920b95 | ||
|
|
da32e54a4b | ||
|
|
d1dce8b605 | ||
|
|
79176852b8 | ||
|
|
c68cc3c8ed | ||
|
|
c8ea72c217 | ||
|
|
1cac02f2c0 | ||
|
|
ca2f0ab229 | ||
|
|
e7db56101b | ||
|
|
f63732fd19 | ||
|
|
bbfe92cda6 | ||
|
|
ff54a8d1c3 | ||
|
|
6f912bfcdc | ||
|
|
7c14e682e7 | ||
|
|
15a0e77450 | ||
|
|
35c6e92799 | ||
|
|
b4682aebd6 | ||
|
|
7f1ea3f67b | ||
|
|
b903240b40 | ||
|
|
a5f4e81d37 | ||
|
|
3466732b8e | ||
|
|
e908bc2078 | ||
|
|
0aa8439301 | ||
|
|
7a69636794 | ||
|
|
e4728e2cc9 | ||
|
|
ca1af07aff | ||
|
|
c4e5574518 | ||
|
|
f34e7c9640 | ||
|
|
17f289b00b | ||
|
|
966dabe3b5 | ||
|
|
c3de335f2d | ||
|
|
155ef11596 | ||
|
|
0083379d96 | ||
|
|
f26af72dbe | ||
|
|
c29e97a738 | ||
|
|
1f5aac7e8f | ||
|
|
34673e9bb5 | ||
|
|
a535d052ec | ||
|
|
f48a214024 | ||
|
|
ce629128e1 | ||
|
|
df72dcfc7f | ||
|
|
b9415b43b0 | ||
|
|
cac21ebd38 | ||
|
|
ccba3d87b0 | ||
|
|
23ba45729e | ||
|
|
04f803676a | ||
|
|
61f77947ac | ||
|
|
a9429e5335 | ||
|
|
952305492c | ||
|
|
b01e6eaf56 | ||
|
|
4a3f836020 | ||
|
|
a9cc0100f6 | ||
|
|
de584eae8f | ||
|
|
92641695ad | ||
|
|
8e40aa1869 | ||
|
|
e606b50cd0 | ||
|
|
d16fd0cd05 | ||
|
|
6dc6ee54ea | ||
|
|
5b515822d3 | ||
|
|
f81d754044 | ||
|
|
483c5cf87a | ||
|
|
6b634b4ef5 | ||
|
|
f58ae97c6e | ||
|
|
5deb58f092 | ||
|
|
55cd4c5ada | ||
|
|
27a7adc282 | ||
|
|
6b72b60b5e | ||
|
|
c2d6b9738f | ||
|
|
44dbff308a | ||
|
|
c224a26bc8 | ||
|
|
a1e9afae85 | ||
|
|
bca6340ded | ||
|
|
f1e7df394e | ||
|
|
a2bbcce69e | ||
|
|
de8747c9f5 | ||
|
|
0b8ce67e10 | ||
|
|
0de4d00d83 | ||
|
|
0b47e083ea | ||
|
|
2e0b55bd37 | ||
|
|
ee5bb5364b | ||
|
|
bb3fd88a90 | ||
|
|
ac5dfe5a9c | ||
|
|
0bc65e4345 | ||
|
|
92b80d1e46 | ||
|
|
dab627e248 | ||
|
|
70a77718db | ||
|
|
9a81c9a418 | ||
|
|
6ef05b8118 | ||
|
|
6fd187c54c | ||
|
|
abf65caba7 | ||
|
|
5470c68cb4 | ||
|
|
f0bca41c5e | ||
|
|
c985c4788b | ||
|
|
2df5e8d791 | ||
|
|
2e8ea3b0d8 | ||
|
|
8a2a624956 | ||
|
|
b1aa093f5d | ||
|
|
216a67fc12 | ||
|
|
85d9b2fc8a | ||
|
|
65454014ef | ||
|
|
4e23a931cd | ||
|
|
3446c9b2a1 | ||
|
|
ccda10fca4 | ||
|
|
a14dfb9360 | ||
|
|
f3e52f0bdf | ||
|
|
f7a666e8c5 | ||
|
|
1feaae7291 | ||
|
|
112cbaf813 | ||
|
|
5263a66fbe | ||
|
|
d1971986ea | ||
|
|
988f3dfdd5 | ||
|
|
95794dc837 | ||
|
|
8bb716e1c5 | ||
|
|
ec3faa31a5 | ||
|
|
09d7b8f5ed | ||
|
|
60fcbbfeaf | ||
|
|
6d1c9263b7 | ||
|
|
5bd1dd71f6 | ||
|
|
4fcc8f004d | ||
|
|
a11f22cd49 | ||
|
|
d79bf7ef80 | ||
|
|
a88a803d38 | ||
|
|
23b59dc542 | ||
|
|
751167fb17 | ||
|
|
d1336c5b95 | ||
|
|
18765f7b4d | ||
|
|
04f2d2a0e4 | ||
|
|
64a6af7bf6 | ||
|
|
158bb0ae41 | ||
|
|
c3e14a0593 | ||
|
|
3e177ec39d | ||
|
|
b7d9124228 | ||
|
|
67ed9b294b | ||
|
|
931947bffc | ||
|
|
de9ca09e70 | ||
|
|
7ef294291a | ||
|
|
e44972ec44 | ||
|
|
b7a45512cf | ||
|
|
4621724fc6 | ||
|
|
fb9c673130 | ||
|
|
15b08cdd44 | ||
|
|
76db303368 | ||
|
|
d5d0313b21 | ||
|
|
f419b3753a | ||
|
|
705258d30d | ||
|
|
413b7a7203 | ||
|
|
d3a8d27276 | ||
|
|
725c1b7da4 | ||
|
|
45767d4b27 | ||
|
|
0e4d1da1cc | ||
|
|
55f9d77054 | ||
|
|
757ef40afc | ||
|
|
ee95c23c3d | ||
|
|
93445a2831 | ||
|
|
3bef3dd6c6 | ||
|
|
db46931246 | ||
|
|
7ca7a9cc58 | ||
|
|
f7d5582f57 | ||
|
|
82486d1e13 | ||
|
|
80cc9fc984 | ||
|
|
17b21eb029 | ||
|
|
0a2528d476 | ||
|
|
db9afd4d7c | ||
|
|
5f116226cf | ||
|
|
41ce91cf81 | ||
|
|
a6599b1ea0 | ||
|
|
aed29762fd | ||
|
|
411ca43729 | ||
|
|
5401896829 | ||
|
|
92a5e20c7e | ||
|
|
c6677d55da | ||
|
|
1168b301dd | ||
|
|
e1d835259d | ||
|
|
4b38db6380 | ||
|
|
d7f06dbfbb | ||
|
|
86485740eb | ||
|
|
97550a67b7 | ||
|
|
e8d50201a5 | ||
|
|
39e276644f | ||
|
|
d72cbb79f5 | ||
|
|
0a260db335 | ||
|
|
64a77ce04f | ||
|
|
5f33f061cc | ||
|
|
7606763cc6 | ||
|
|
d73430b299 | ||
|
|
0ab988119d | ||
|
|
6d97ac77f6 | ||
|
|
cd2b9d2e0a | ||
|
|
32ef47e6d2 | ||
|
|
cb3c20ecbd | ||
|
|
12ed730897 | ||
|
|
aaa1f76176 | ||
|
|
fb2492e577 | ||
|
|
e7b0fc1419 | ||
|
|
7dd0b0e4eb | ||
|
|
6b55a50b05 | ||
|
|
4f38c0ee80 | ||
|
|
95dcb8802a | ||
|
|
9188f5cdd9 | ||
|
|
645cf211dd | ||
|
|
c720df0805 | ||
|
|
b7722ed333 | ||
|
|
fb883c7b27 | ||
|
|
f51e755216 | ||
|
|
146326f427 | ||
|
|
ccc1229098 | ||
|
|
f6b6c64b93 | ||
|
|
91d8e56471 | ||
|
|
702dbd8a82 | ||
|
|
5e722b4d11 | ||
|
|
712fbb53c7 | ||
|
|
88c437562b | ||
|
|
537fd0ac21 | ||
|
|
59cb7baf0b | ||
|
|
94af8044f1 | ||
|
|
5d8b937e9c | ||
|
|
f89093a067 | ||
|
|
e303888119 | ||
|
|
a7676c4daa | ||
|
|
535a7d2f2d | ||
|
|
656b818488 | ||
|
|
249c3eab8c | ||
|
|
6de0205d07 | ||
|
|
826fe15e15 | ||
|
|
0ce5311b5f | ||
|
|
90cb395dc6 | ||
|
|
cbf72eedab | ||
|
|
3f79a2fdda | ||
|
|
1a94453849 | ||
|
|
6045e53207 | ||
|
|
d3c6d1fe85 | ||
|
|
35a7ba77e3 | ||
|
|
57d12c32fc | ||
|
|
f09268230e | ||
|
|
98cefe37d2 | ||
|
|
01b55a17f1 | ||
|
|
aaacf2ea4b | ||
|
|
8672998f08 | ||
|
|
d8039031ca | ||
|
|
f5ad46f1e1 | ||
|
|
c1473b4045 | ||
|
|
285ae970c8 | ||
|
|
bf1c67a7ac | ||
|
|
98165bf9dd | ||
|
|
19e297e4c6 | ||
|
|
8eaa942572 | ||
|
|
ce1be46c0b | ||
|
|
da75b7b0d3 | ||
|
|
d70c618442 | ||
|
|
f4e3cafa25 | ||
|
|
dcafcb983e | ||
|
|
faac4518f5 | ||
|
|
45ba9c6961 | ||
|
|
25c5f36a0c | ||
|
|
2ff06d12b0 | ||
|
|
c3305c2cd7 | ||
|
|
7cae96a77b | ||
|
|
0a7616f0f6 | ||
|
|
5de93bcad2 | ||
|
|
c72961573b | ||
|
|
2a9c39532a | ||
|
|
2e6d760c53 | ||
|
|
d2f3098b2a | ||
|
|
22dd4e5f77 | ||
|
|
31e6c1fa86 | ||
|
|
ba44c0ae9d | ||
|
|
8c918f1ea6 | ||
|
|
ff31b36b46 | ||
|
|
01704ec38b | ||
|
|
8a84eba232 | ||
|
|
0d28fe25f8 | ||
|
|
97a3346ff6 | ||
|
|
9d2f1ab8c8 | ||
|
|
7087ed80cc | ||
|
|
1aeb3a3b63 | ||
|
|
99b2ba8944 |
15
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
15
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -68,9 +68,20 @@ body:
|
|||||||
id: browser-logs
|
id: browser-logs
|
||||||
attributes:
|
attributes:
|
||||||
label: Browser Logs
|
label: Browser Logs
|
||||||
description: Please review and provide any relevant logs from the browser, if relevant
|
description: Please review and provide any logs from the browser, if relevant
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: other
|
id: other
|
||||||
attributes:
|
attributes:
|
||||||
label: Other
|
label: Other
|
||||||
description: Any other relevant details. E.g. service version or API version, docker version, etc.
|
description: Please include output from your troubleshooting tests, if relevant. Include any other relevant details. E.g. service version or API version, docker version, etc.
|
||||||
|
- type: checkboxes
|
||||||
|
id: pre-flight
|
||||||
|
attributes:
|
||||||
|
label: Before submitting, I have made sure to
|
||||||
|
options:
|
||||||
|
- label: Check [the documentation](https://gethomepage.dev/)
|
||||||
|
required: true
|
||||||
|
- label: Follow [the troubleshooting guide](https://gethomepage.dev/en/more/troubleshooting/) (please include output above if applicable).
|
||||||
|
required: true
|
||||||
|
- label: Search [existing issues](https://github.com/benphelps/homepage/search?q=&type=issues) and [discussions](https://github.com/benphelps/homepage/search?q=&type=discussions).
|
||||||
|
required: true
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -41,3 +41,8 @@ next-env.d.ts
|
|||||||
|
|
||||||
# homepage
|
# homepage
|
||||||
/config
|
/config
|
||||||
|
|
||||||
|
# IDEs
|
||||||
|
/.idea/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,12 +47,12 @@
|
|||||||
- Service Integration
|
- Service Integration
|
||||||
- Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli (Plex)
|
- Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli (Plex)
|
||||||
- Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent
|
- Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent
|
||||||
- Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server, Authentic, Proxmox
|
- Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server, Authentik, Proxmox
|
||||||
- Information Providers
|
- Information Providers
|
||||||
- Coin Market Cap, Mastodon
|
- Coin Market Cap, Mastodon
|
||||||
- Information & Utility Widgets
|
- Information & Utility Widgets
|
||||||
- System Stats (Disk, CPU, Memory)
|
- System Stats (Disk, CPU, Memory)
|
||||||
- Weather via WeatherAPI.com or OpenWeatherMap
|
- Weather via [OpenWeatherMap](https://openweathermap.org/) or [Open-Meteo](https://open-meteo.com/)
|
||||||
- Search Bar
|
- Search Bar
|
||||||
- Customizable
|
- Customizable
|
||||||
- 21 theme colors with light and dark mode support
|
- 21 theme colors with light and dark mode support
|
||||||
@@ -117,7 +117,7 @@ pnpm start
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Configuration files will be genereted and placed on the first request.
|
Configuration files will be generated and placed on the first request.
|
||||||
|
|
||||||
Configuration is done in the /config directory using .yaml files. Refer to each config for
|
Configuration is done in the /config directory using .yaml files. Refer to each config for
|
||||||
the specific configuration options.
|
the specific configuration options.
|
||||||
|
|||||||
@@ -98,20 +98,21 @@ module.exports = {
|
|||||||
);
|
);
|
||||||
|
|
||||||
i18next.services.formatter.add("rate", (value, lng, options) => {
|
i18next.services.formatter.add("rate", (value, lng, options) => {
|
||||||
if (value === 0) return "0 Bps";
|
|
||||||
|
|
||||||
const bits = options.bits ? value : value / 8;
|
const k = options.binary ? 1024 : 1000;
|
||||||
const k = 1024;
|
const sizes = options.bits ? (options.binary ? BIBIT_UNITS : BIT_UNITS) : (options.binary ? BIBYTE_UNITS : BYTE_UNITS);
|
||||||
|
|
||||||
|
if (value === 0) return `0 ${sizes[0]}/s`;
|
||||||
|
|
||||||
const dm = options.decimals ? options.decimals : 0;
|
const dm = options.decimals ? options.decimals : 0;
|
||||||
const sizes = ["Bps", "KiBps", "MiBps", "GiBps", "TiBps", "PiBps", "EiBps", "ZiBps", "YiBps"];
|
|
||||||
|
|
||||||
const i = Math.floor(Math.log(bits) / Math.log(k));
|
const i = options.binary ? 2 : Math.floor(Math.log(value) / Math.log(k));
|
||||||
|
|
||||||
const formatted = new Intl.NumberFormat(lng, { maximumFractionDigits: dm, minimumFractionDigits: dm }).format(
|
const formatted = new Intl.NumberFormat(lng, { maximumFractionDigits: dm, minimumFractionDigits: dm }).format(
|
||||||
parseFloat(bits / k ** i)
|
parseFloat(value / k ** i)
|
||||||
);
|
);
|
||||||
|
|
||||||
return `${formatted} ${sizes[i]}`;
|
return `${formatted} ${sizes[i]}/s`;
|
||||||
});
|
});
|
||||||
|
|
||||||
i18next.services.formatter.add("percent", (value, lng, options) =>
|
i18next.services.formatter.add("percent", (value, lng, options) =>
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"leech": "Leech",
|
|
||||||
"seed": "Seed",
|
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload"
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"leech": "Leech",
|
||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"saved": "Saved",
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech"
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
"missing_type": "Falta el tipus de widget: {{type}}",
|
"missing_type": "Falta el tipus de widget: {{type}}",
|
||||||
"api_error": "Error d'API",
|
"api_error": "Error d'API",
|
||||||
"status": "Estat",
|
"status": "Estat",
|
||||||
"information": "Information",
|
"information": "Informació",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"raw_error": "Raw Error",
|
"raw_error": "Error sense processar",
|
||||||
"response_data": "Response Data"
|
"response_data": "Dades de resposta"
|
||||||
},
|
},
|
||||||
"weather": {
|
"weather": {
|
||||||
"allow": "Feu clic per permetre",
|
"allow": "Feu clic per permetre",
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
"transmission": {
|
"transmission": {
|
||||||
"seed": "Llavors",
|
"seed": "Llavors",
|
||||||
"download": "Descàrrega",
|
"download": "Descàrrega",
|
||||||
"upload": "Càrrega",
|
"upload": "Pujada",
|
||||||
"leech": "Companys"
|
"leech": "Company"
|
||||||
},
|
},
|
||||||
"sonarr": {
|
"sonarr": {
|
||||||
"wanted": "Volgut",
|
"wanted": "Volgut",
|
||||||
@@ -30,13 +30,13 @@
|
|||||||
},
|
},
|
||||||
"speedtest": {
|
"speedtest": {
|
||||||
"ping": "Ping",
|
"ping": "Ping",
|
||||||
"upload": "Càrrega",
|
"upload": "Pujada",
|
||||||
"download": "Descàrrega"
|
"download": "Descàrrega"
|
||||||
},
|
},
|
||||||
"resources": {
|
"resources": {
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
"free": "Lliure",
|
"free": "Lliure",
|
||||||
"used": "Usat",
|
"used": "Utilitzat",
|
||||||
"load": "Càrrega",
|
"load": "Càrrega",
|
||||||
"cpu": "CPU"
|
"cpu": "CPU"
|
||||||
},
|
},
|
||||||
@@ -47,13 +47,13 @@
|
|||||||
"cpu": "Processador",
|
"cpu": "Processador",
|
||||||
"offline": "Fora de línia",
|
"offline": "Fora de línia",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"unknown": "Unknown"
|
"unknown": "Desconegut"
|
||||||
},
|
},
|
||||||
"emby": {
|
"emby": {
|
||||||
"playing": "Reproduint",
|
"playing": "Reproduint",
|
||||||
"transcoding": "Transcodificant",
|
"transcoding": "Transcodificant",
|
||||||
"bitrate": "Taxa de bits",
|
"bitrate": "Taxa de bits",
|
||||||
"no_active": "Sense transmissions actives"
|
"no_active": "Sense reproduccions actives"
|
||||||
},
|
},
|
||||||
"tautulli": {
|
"tautulli": {
|
||||||
"playing": "Reproduint",
|
"playing": "Reproduint",
|
||||||
@@ -73,14 +73,14 @@
|
|||||||
},
|
},
|
||||||
"rutorrent": {
|
"rutorrent": {
|
||||||
"active": "Actiu",
|
"active": "Actiu",
|
||||||
"upload": "Càrrega",
|
"upload": "Pujada",
|
||||||
"download": "Descàrrega"
|
"download": "Descàrrega"
|
||||||
},
|
},
|
||||||
"radarr": {
|
"radarr": {
|
||||||
"wanted": "Volgut",
|
"wanted": "Volgut",
|
||||||
"queued": "En cua",
|
"queued": "En cua",
|
||||||
"movies": "Pel·lícules",
|
"movies": "Pel·lícules",
|
||||||
"missing": "Missing"
|
"missing": "Faltant"
|
||||||
},
|
},
|
||||||
"readarr": {
|
"readarr": {
|
||||||
"wanted": "Volgut",
|
"wanted": "Volgut",
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
"pending": "Pendent",
|
"pending": "Pendent",
|
||||||
"approved": "Aprovat",
|
"approved": "Aprovat",
|
||||||
"available": "Disponible",
|
"available": "Disponible",
|
||||||
"processing": "Processing"
|
"processing": "Processant"
|
||||||
},
|
},
|
||||||
"pihole": {
|
"pihole": {
|
||||||
"queries": "Consultes",
|
"queries": "Consultes",
|
||||||
@@ -163,8 +163,8 @@
|
|||||||
},
|
},
|
||||||
"qbittorrent": {
|
"qbittorrent": {
|
||||||
"download": "Descàrrega",
|
"download": "Descàrrega",
|
||||||
"upload": "Càrrega",
|
"upload": "Pujada",
|
||||||
"leech": "Companys",
|
"leech": "Company",
|
||||||
"seed": "Llavors"
|
"seed": "Llavors"
|
||||||
},
|
},
|
||||||
"mastodon": {
|
"mastodon": {
|
||||||
@@ -184,26 +184,26 @@
|
|||||||
"failedLoginsLast24H": "Errors d'inici de sessió (24h)"
|
"failedLoginsLast24H": "Errors d'inici de sessió (24h)"
|
||||||
},
|
},
|
||||||
"proxmox": {
|
"proxmox": {
|
||||||
"vms": "VMs",
|
"vms": "Màquines Virtuals",
|
||||||
"mem": "Memòria",
|
"mem": "Memòria",
|
||||||
"cpu": "Processador",
|
"cpu": "Processador",
|
||||||
"lxc": "LXC"
|
"lxc": "LXC"
|
||||||
},
|
},
|
||||||
"unifi": {
|
"unifi": {
|
||||||
"users": "Usuaris",
|
"users": "Usuaris",
|
||||||
"uptime": "System Uptime",
|
"uptime": "Temps actiu",
|
||||||
"days": "Días",
|
"days": "Dies",
|
||||||
"wan": "WAN",
|
"wan": "WAN",
|
||||||
"lan_users": "LAN Users",
|
"lan_users": "Usuaris LAN",
|
||||||
"wlan_users": "WLAN Users",
|
"wlan_users": "Usuaris WLAN",
|
||||||
"up": "UP",
|
"up": "ACTIU",
|
||||||
"down": "DOWN",
|
"down": "INACTIU",
|
||||||
"wait": "Si us plau, espereu",
|
"wait": "Si us plau, espereu",
|
||||||
"lan": "LAN",
|
"lan": "LAN",
|
||||||
"wlan": "WLAN",
|
"wlan": "WLAN",
|
||||||
"devices": "Devices",
|
"devices": "Dispositius",
|
||||||
"lan_devices": "LAN Devices",
|
"lan_devices": "Dispositius LAN",
|
||||||
"wlan_devices": "WLAN Devices"
|
"wlan_devices": "Dispositius WLAN"
|
||||||
},
|
},
|
||||||
"plex": {
|
"plex": {
|
||||||
"streams": "Transmissions actives",
|
"streams": "Transmissions actives",
|
||||||
@@ -216,119 +216,119 @@
|
|||||||
"wait": "Si us plau, espereu"
|
"wait": "Si us plau, espereu"
|
||||||
},
|
},
|
||||||
"changedetectionio": {
|
"changedetectionio": {
|
||||||
"totalObserved": "Total Observed",
|
"totalObserved": "Total d'observats",
|
||||||
"diffsDetected": "Diffs Detected"
|
"diffsDetected": "Diferències detectades"
|
||||||
},
|
},
|
||||||
"wmo": {
|
"wmo": {
|
||||||
"66-day": "Freezing Rain",
|
"66-day": "Pluja gelada",
|
||||||
"95-day": "Thunderstorm",
|
"95-day": "Tempesta",
|
||||||
"95-night": "Thunderstorm",
|
"95-night": "Tempesta",
|
||||||
"96-day": "Thunderstorm With Hail",
|
"96-day": "Tempesta amb calamarsa",
|
||||||
"0-day": "Sunny",
|
"0-day": "Assolellat",
|
||||||
"0-night": "Clear",
|
"0-night": "Cel clar",
|
||||||
"1-day": "Mainly Sunny",
|
"1-day": "Majorment assolellat",
|
||||||
"1-night": "Mainly Clear",
|
"1-night": "Majorment clar",
|
||||||
"2-day": "Partly Cloudy",
|
"2-day": "Parcialment ennuvolat",
|
||||||
"2-night": "Partly Cloudy",
|
"2-night": "Parcialment ennuvolat",
|
||||||
"3-day": "Cloudy",
|
"3-day": "Ennuvolat",
|
||||||
"3-night": "Cloudy",
|
"3-night": "Ennuvolat",
|
||||||
"45-day": "Foggy",
|
"45-day": "Boirós",
|
||||||
"45-night": "Foggy",
|
"45-night": "Boirós",
|
||||||
"48-day": "Foggy",
|
"48-day": "Boirós",
|
||||||
"48-night": "Foggy",
|
"48-night": "Boirós",
|
||||||
"51-day": "Light Drizzle",
|
"51-day": "Ruixats lleugers",
|
||||||
"51-night": "Light Drizzle",
|
"51-night": "Ruixats lleugers",
|
||||||
"53-day": "Drizzle",
|
"53-day": "Ruixat",
|
||||||
"53-night": "Drizzle",
|
"53-night": "Ruxiat",
|
||||||
"55-day": "Heavy Drizzle",
|
"55-day": "Ruixat intens",
|
||||||
"55-night": "Heavy Drizzle",
|
"55-night": "Ruixat intens",
|
||||||
"56-day": "Light Freezing Drizzle",
|
"56-day": "Lleuger ruixat gelat",
|
||||||
"56-night": "Light Freezing Drizzle",
|
"56-night": "Lleuger ruixat gelat",
|
||||||
"65-night": "Heavy Rain",
|
"65-night": "Pluja intensa",
|
||||||
"57-day": "Freezing Drizzle",
|
"57-day": "Ruixat gelat",
|
||||||
"57-night": "Freezing Drizzle",
|
"57-night": "Ruixat gelat",
|
||||||
"61-day": "Light Rain",
|
"61-day": "Pluja lleugera",
|
||||||
"61-night": "Light Rain",
|
"61-night": "Pluja lleugera",
|
||||||
"63-day": "Rain",
|
"63-day": "Pluja",
|
||||||
"63-night": "Rain",
|
"63-night": "Pluja",
|
||||||
"65-day": "Heavy Rain",
|
"65-day": "Pluja intensa",
|
||||||
"66-night": "Freezing Rain",
|
"66-night": "Pluja gelada",
|
||||||
"67-day": "Freezing Rain",
|
"67-day": "Pluja gelada",
|
||||||
"67-night": "Freezing Rain",
|
"67-night": "Pluja gelada",
|
||||||
"71-day": "Light Snow",
|
"71-day": "Neu lleugera",
|
||||||
"71-night": "Light Snow",
|
"71-night": "Neu lleugera",
|
||||||
"73-day": "Snow",
|
"73-day": "Neu",
|
||||||
"73-night": "Snow",
|
"73-night": "Neu",
|
||||||
"75-day": "Heavy Snow",
|
"75-day": "Neu intensa",
|
||||||
"75-night": "Heavy Snow",
|
"75-night": "Neu intensa",
|
||||||
"77-day": "Snow Grains",
|
"77-day": "Neu lleugera",
|
||||||
"77-night": "Snow Grains",
|
"77-night": "Neu lleugera",
|
||||||
"80-day": "Light Showers",
|
"80-day": "Plovisqueig",
|
||||||
"80-night": "Light Showers",
|
"80-night": "Plovisqueig",
|
||||||
"81-day": "Showers",
|
"81-day": "Xàfecs",
|
||||||
"81-night": "Showers",
|
"81-night": "Xàfecs",
|
||||||
"82-day": "Heavy Showers",
|
"82-day": "Xàfecs intensos",
|
||||||
"82-night": "Heavy Showers",
|
"82-night": "Xàfecs intensos",
|
||||||
"85-day": "Snow Showers",
|
"85-day": "Xàfecs de neu",
|
||||||
"85-night": "Snow Showers",
|
"85-night": "Xàfecs de neu",
|
||||||
"86-day": "Snow Showers",
|
"86-day": "Xàfecs de neu",
|
||||||
"86-night": "Snow Showers",
|
"86-night": "Xàfecs de neu",
|
||||||
"96-night": "Thunderstorm With Hail",
|
"96-night": "Tempesta amb calamarsa",
|
||||||
"99-day": "Thunderstorm With Hail",
|
"99-day": "Tempesta amb calamarsa",
|
||||||
"99-night": "Thunderstorm With Hail"
|
"99-night": "Tempesta amb calamarsa"
|
||||||
},
|
},
|
||||||
"quicklaunch": {
|
"quicklaunch": {
|
||||||
"bookmark": "Bookmark",
|
"bookmark": "Marcador",
|
||||||
"service": "Service"
|
"service": "Servei"
|
||||||
},
|
},
|
||||||
"homebridge": {
|
"homebridge": {
|
||||||
"available_update": "System",
|
"available_update": "Sistema",
|
||||||
"updates": "Updates",
|
"updates": "Actualitzacions",
|
||||||
"update_available": "Update Available",
|
"update_available": "Actualització disponible",
|
||||||
"up_to_date": "Up to Date",
|
"up_to_date": "Actualitzat",
|
||||||
"child_bridges": "Child Bridges",
|
"child_bridges": "Child Bridges",
|
||||||
"child_bridges_status": "{{ok}}/{{total}}"
|
"child_bridges_status": "{{ok}}/{{total}}"
|
||||||
},
|
},
|
||||||
"autobrr": {
|
"autobrr": {
|
||||||
"approvedPushes": "Approved",
|
"approvedPushes": "Aprovat",
|
||||||
"rejectedPushes": "Rejected",
|
"rejectedPushes": "Rebutjat",
|
||||||
"filters": "Filters",
|
"filters": "Filtres",
|
||||||
"indexers": "Indexers"
|
"indexers": "Indexadors"
|
||||||
},
|
},
|
||||||
"watchtower": {
|
"watchtower": {
|
||||||
"containers_scanned": "Scanned",
|
"containers_scanned": "Escanejat",
|
||||||
"containers_updated": "Updated",
|
"containers_updated": "Actualitzat",
|
||||||
"containers_failed": "Failed"
|
"containers_failed": "Error"
|
||||||
},
|
},
|
||||||
"tubearchivist": {
|
"tubearchivist": {
|
||||||
"downloads": "Queue",
|
"downloads": "Cua",
|
||||||
"videos": "Videos",
|
"videos": "Vídeos",
|
||||||
"channels": "Channels",
|
"channels": "Canals",
|
||||||
"playlists": "Playlists"
|
"playlists": "Llistes de reproducció"
|
||||||
},
|
},
|
||||||
"truenas": {
|
"truenas": {
|
||||||
"load": "System Load",
|
"load": "Càrrega del sistema",
|
||||||
"uptime": "Uptime",
|
"uptime": "Temps actiu",
|
||||||
"alerts": "Alerts",
|
"alerts": "Alertes",
|
||||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||||
},
|
},
|
||||||
"navidrome": {
|
"navidrome": {
|
||||||
"nothing_streaming": "No Active Streams",
|
"nothing_streaming": "Cap reproducció activa",
|
||||||
"please_wait": "Please Wait"
|
"please_wait": "Espereu si us plau"
|
||||||
},
|
},
|
||||||
"pyload": {
|
"pyload": {
|
||||||
"speed": "Speed",
|
"speed": "Velocitat",
|
||||||
"active": "Active",
|
"active": "Actiu",
|
||||||
"queue": "Queue",
|
"queue": "Cua",
|
||||||
"total": "Total"
|
"total": "Total"
|
||||||
},
|
},
|
||||||
"gluetun": {
|
"gluetun": {
|
||||||
"public_ip": "Public IP",
|
"public_ip": "IP Pública",
|
||||||
"region": "Region",
|
"region": "Regió",
|
||||||
"country": "Country"
|
"country": "País"
|
||||||
},
|
},
|
||||||
"hdhomerun": {
|
"hdhomerun": {
|
||||||
"channels": "Channels",
|
"channels": "Canals",
|
||||||
"hd": "HD"
|
"hd": "HD"
|
||||||
},
|
},
|
||||||
"ping": {
|
"ping": {
|
||||||
@@ -336,24 +336,72 @@
|
|||||||
"ping": "Ping"
|
"ping": "Ping"
|
||||||
},
|
},
|
||||||
"scrutiny": {
|
"scrutiny": {
|
||||||
"passed": "Passed",
|
"passed": "Aprobat",
|
||||||
"failed": "Failed",
|
"failed": "Error",
|
||||||
"unknown": "Unknown"
|
"unknown": "Desconegut"
|
||||||
},
|
},
|
||||||
"paperlessngx": {
|
"paperlessngx": {
|
||||||
"inbox": "Inbox",
|
"inbox": "Safata d'entrada",
|
||||||
"total": "Total"
|
"total": "Total"
|
||||||
},
|
},
|
||||||
"deluge": {
|
"deluge": {
|
||||||
"seed": "Seed",
|
"seed": "Llavor",
|
||||||
"download": "Download",
|
"download": "Descàrrega",
|
||||||
"upload": "Upload",
|
"upload": "Pujada",
|
||||||
"leech": "Leech"
|
"leech": "Company"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"download": "Descarregar",
|
||||||
|
"upload": "Pujada",
|
||||||
|
"leech": "Company",
|
||||||
|
"seed": "Llavor"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
"download": "Download"
|
"download": "Download"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"leech": "Leech",
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"url": "URL",
|
"url": "URL",
|
||||||
"information": "Information",
|
"information": "Information",
|
||||||
"raw_error": "Raw Error",
|
"raw_error": "Raw Error",
|
||||||
"response_data": "Response Data"
|
"response_data": "Empfangene Daten"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"placeholder": "Suche…"
|
"placeholder": "Suche…"
|
||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"unread": "Unread",
|
||||||
|
"read": "Read"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
"bytes": "{{value, bytes}}",
|
"bytes": "{{value, bytes}}",
|
||||||
"bits": "{{value, bytes(bits: true)}}",
|
"bits": "{{value, bytes(bits: true)}}",
|
||||||
"bbytes": "{{value, bytes(binary: true)}}",
|
"bbytes": "{{value, bytes(binary: true)}}",
|
||||||
"bbits": "{{value, bytes(bits: true, binary: true)}}",
|
"bbits": "{{value, bytes(bits: true; binary: true)}}",
|
||||||
"byterate": "{{value, rate}}",
|
"byterate": "{{value, rate(bits: false)}}",
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
"bitrate": "{{value, rate(bits: true)}}",
|
"bitrate": "{{value, rate(bits: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
|
||||||
"percent": "{{value, percent}}",
|
"percent": "{{value, percent}}",
|
||||||
"number": "{{value, number}}",
|
"number": "{{value, number}}",
|
||||||
"ms": "{{value, number}}"
|
"ms": "{{value, number}}"
|
||||||
@@ -70,6 +72,12 @@
|
|||||||
"bitrate": "Bitrate",
|
"bitrate": "Bitrate",
|
||||||
"no_active": "No Active Streams"
|
"no_active": "No Active Streams"
|
||||||
},
|
},
|
||||||
|
"flood": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
"changedetectionio": {
|
"changedetectionio": {
|
||||||
"totalObserved": "Total Observed",
|
"totalObserved": "Total Observed",
|
||||||
"diffsDetected": "Diffs Detected"
|
"diffsDetected": "Diffs Detected"
|
||||||
@@ -80,6 +88,13 @@
|
|||||||
"bitrate": "Bitrate",
|
"bitrate": "Bitrate",
|
||||||
"no_active": "No Active Streams"
|
"no_active": "No Active Streams"
|
||||||
},
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
"nzbget": {
|
"nzbget": {
|
||||||
"rate": "Rate",
|
"rate": "Rate",
|
||||||
"remaining": "Remaining",
|
"remaining": "Remaining",
|
||||||
@@ -118,7 +133,7 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
@@ -186,6 +201,12 @@
|
|||||||
"stopped": "Stopped",
|
"stopped": "Stopped",
|
||||||
"total": "Total"
|
"total": "Total"
|
||||||
},
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
"traefik": {
|
"traefik": {
|
||||||
"routers": "Routers",
|
"routers": "Routers",
|
||||||
"services": "Services",
|
"services": "Services",
|
||||||
@@ -234,6 +255,10 @@
|
|||||||
"status_count": "Posts",
|
"status_count": "Posts",
|
||||||
"domain_count": "Domains"
|
"domain_count": "Domains"
|
||||||
},
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
"authentik": {
|
"authentik": {
|
||||||
"users": "Users",
|
"users": "Users",
|
||||||
"loginsLast24H": "Logins (24h)",
|
"loginsLast24H": "Logins (24h)",
|
||||||
@@ -366,5 +391,26 @@
|
|||||||
"paperlessngx": {
|
"paperlessngx": {
|
||||||
"inbox": "Inbox",
|
"inbox": "Inbox",
|
||||||
"total": "Total"
|
"total": "Total"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"inbox": "Inbox",
|
"inbox": "Inbox",
|
||||||
"total": "Totalo"
|
"total": "Totalo"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"leech": "Leech",
|
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
"pending": "Pendiente",
|
"pending": "Pendiente",
|
||||||
"approved": "Aprobado",
|
"approved": "Aprobado",
|
||||||
"available": "Disponible",
|
"available": "Disponible",
|
||||||
"processing": "Processing"
|
"processing": "Procesando"
|
||||||
},
|
},
|
||||||
"sabnzbd": {
|
"sabnzbd": {
|
||||||
"rate": "Tasa",
|
"rate": "Tasa",
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
"transmission": {
|
"transmission": {
|
||||||
"download": "Bajada",
|
"download": "Bajada",
|
||||||
"upload": "Subida",
|
"upload": "Subida",
|
||||||
"leech": "Compañeros",
|
"leech": "Leech",
|
||||||
"seed": "Semillas"
|
"seed": "Semillas"
|
||||||
},
|
},
|
||||||
"jackett": {
|
"jackett": {
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
"qbittorrent": {
|
"qbittorrent": {
|
||||||
"download": "Bajada",
|
"download": "Bajada",
|
||||||
"upload": "Subida",
|
"upload": "Subida",
|
||||||
"leech": "Compañeros",
|
"leech": "Leech",
|
||||||
"seed": "Semillas"
|
"seed": "Semillas"
|
||||||
},
|
},
|
||||||
"mastodon": {
|
"mastodon": {
|
||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Semilla"
|
"seed": "Semilla"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Descargar",
|
||||||
"upload": "Upload",
|
"upload": "Subir",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Cola",
|
||||||
|
"processed": "Procesado",
|
||||||
|
"saved": "Guardado",
|
||||||
|
"errored": "Error"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Leer",
|
||||||
|
"unread": "Sin leer"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Espere, por favor",
|
||||||
|
"no_devices": "No se reciben datos del dispositivo"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "AP conectados",
|
||||||
|
"activeUser": "Dispositivos activos",
|
||||||
|
"alerts": "Alertas",
|
||||||
|
"connectedGateway": "Pasarelas conectadas",
|
||||||
|
"connectedSwitches": "Interruptores conectados"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Descargar",
|
||||||
|
"upload": "Subir",
|
||||||
|
"leech": "Sanguijuela",
|
||||||
|
"seed": "Semilla"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "Carga de la CPU",
|
||||||
|
"memoryUsed": "Memoria utilizada",
|
||||||
|
"uptime": "Tiempo en funcionamiento",
|
||||||
|
"numberOfLeases": "Alquileres"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
"download": "Download"
|
"download": "Download"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedSwitches": "Connected switches",
|
||||||
|
"connectedGateway": "Connected gateways"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Récep.",
|
||||||
"upload": "Upload",
|
"upload": "Envoi",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "À traiter",
|
||||||
|
"processed": "Traité",
|
||||||
|
"errored": "En erreur",
|
||||||
|
"saved": "Enregistré"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Lu",
|
||||||
|
"unread": "Non lu"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Patientez...",
|
||||||
|
"no_devices": "Aucune donnée d'appareil reçue"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "APs connectées",
|
||||||
|
"activeUser": "Équipts actifs",
|
||||||
|
"alerts": "Alertes",
|
||||||
|
"connectedGateway": "Passerelles connectées",
|
||||||
|
"connectedSwitches": "Switches connectés"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Récep.",
|
||||||
|
"upload": "Envoi",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "Charge CPU",
|
||||||
|
"memoryUsed": "Mém. Utilisée",
|
||||||
|
"uptime": "Disponibilité",
|
||||||
|
"numberOfLeases": "Baux"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "Tous les flux",
|
||||||
|
"streams_active": "Flux actif",
|
||||||
|
"streams_xepg": "Canal XEPG"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"download": "Download",
|
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"available": "Dostupno",
|
"available": "Dostupno",
|
||||||
"pending": "Predstoji",
|
"pending": "Predstoji",
|
||||||
"approved": "Odobreno",
|
"approved": "Odobreno",
|
||||||
"processing": "Processing"
|
"processing": "Obrada"
|
||||||
},
|
},
|
||||||
"pihole": {
|
"pihole": {
|
||||||
"queries": "Upiti",
|
"queries": "Upiti",
|
||||||
@@ -345,15 +345,63 @@
|
|||||||
"total": "Ukupno"
|
"total": "Ukupno"
|
||||||
},
|
},
|
||||||
"deluge": {
|
"deluge": {
|
||||||
|
"download": "Preuzimanje",
|
||||||
|
"upload": "Prijenos",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"flood": {
|
||||||
|
"download": "Preuzimanje",
|
||||||
|
"upload": "Prijenos",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"mikrotik": {
|
||||||
"download": "Download",
|
"cpuLoad": "CPU Load",
|
||||||
"upload": "Upload",
|
"memoryUsed": "Memory Used",
|
||||||
"leech": "Leech",
|
"uptime": "Uptime",
|
||||||
"seed": "Seed"
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech"
|
"leech": "Leech"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,18 @@
|
|||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"offline": "Offline",
|
"offline": "Offline",
|
||||||
"rx": "RX",
|
"rx": "RX",
|
||||||
"error": "Error",
|
"error": "Errore",
|
||||||
"unknown": "Unknown"
|
"unknown": "Sconosciuto"
|
||||||
},
|
},
|
||||||
"emby": {
|
"emby": {
|
||||||
"playing": "In riproduzione",
|
"playing": "In riproduzione",
|
||||||
"transcoding": "Transcoding",
|
"transcoding": "Transcodifica",
|
||||||
"bitrate": "Bitrate",
|
"bitrate": "Bitrate",
|
||||||
"no_active": "Nessuno Stream Attivo"
|
"no_active": "Nessuno Stream Attivo"
|
||||||
},
|
},
|
||||||
"tautulli": {
|
"tautulli": {
|
||||||
"playing": "In riproduzione",
|
"playing": "In riproduzione",
|
||||||
"transcoding": "Transcoding",
|
"transcoding": "Transcodifica",
|
||||||
"bitrate": "Bitrate",
|
"bitrate": "Bitrate",
|
||||||
"no_active": "Nessuno Stream Attivo"
|
"no_active": "Nessuno Stream Attivo"
|
||||||
},
|
},
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"total": "Totali"
|
"total": "Totali"
|
||||||
},
|
},
|
||||||
"traefik": {
|
"traefik": {
|
||||||
"routers": "Routers",
|
"routers": "Router",
|
||||||
"services": "Servizi",
|
"services": "Servizi",
|
||||||
"middleware": "Middleware"
|
"middleware": "Middleware"
|
||||||
},
|
},
|
||||||
@@ -40,9 +40,9 @@
|
|||||||
"api_error": "Errore API",
|
"api_error": "Errore API",
|
||||||
"status": "Stato",
|
"status": "Stato",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"information": "Information",
|
"information": "Informazione",
|
||||||
"raw_error": "Raw Error",
|
"raw_error": "Raw Error",
|
||||||
"response_data": "Response Data"
|
"response_data": "Dati risposta"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"placeholder": "Cerca…"
|
"placeholder": "Cerca…"
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
"pending": "In attesa",
|
"pending": "In attesa",
|
||||||
"approved": "Approvati",
|
"approved": "Approvati",
|
||||||
"available": "Disponibili",
|
"available": "Disponibili",
|
||||||
"processing": "Processing"
|
"processing": "In lavorazione"
|
||||||
},
|
},
|
||||||
"sabnzbd": {
|
"sabnzbd": {
|
||||||
"rate": "Rapporto",
|
"rate": "Rapporto",
|
||||||
@@ -126,13 +126,13 @@
|
|||||||
},
|
},
|
||||||
"gotify": {
|
"gotify": {
|
||||||
"apps": "Applicazioni",
|
"apps": "Applicazioni",
|
||||||
"clients": "Clients",
|
"clients": "Client",
|
||||||
"messages": "Messaggi"
|
"messages": "Messaggi"
|
||||||
},
|
},
|
||||||
"prowlarr": {
|
"prowlarr": {
|
||||||
"enableIndexers": "Indicizzatori",
|
"enableIndexers": "Indicizzatori",
|
||||||
"numberOfGrabs": "Grabs",
|
"numberOfGrabs": "Grabs",
|
||||||
"numberOfQueries": "Queries",
|
"numberOfQueries": "Interrogazioni",
|
||||||
"numberOfFailGrabs": "Grabs Falliti",
|
"numberOfFailGrabs": "Grabs Falliti",
|
||||||
"numberOfFailQueries": "Queries Fallite"
|
"numberOfFailQueries": "Queries Fallite"
|
||||||
},
|
},
|
||||||
@@ -153,10 +153,10 @@
|
|||||||
"lidarr": {
|
"lidarr": {
|
||||||
"wanted": "Mancanti",
|
"wanted": "Mancanti",
|
||||||
"queued": "In coda",
|
"queued": "In coda",
|
||||||
"albums": "Albums"
|
"albums": "Album"
|
||||||
},
|
},
|
||||||
"adguard": {
|
"adguard": {
|
||||||
"queries": "Queries",
|
"queries": "Interrogazioni",
|
||||||
"blocked": "Bloccati",
|
"blocked": "Bloccati",
|
||||||
"filtered": "Filtrati",
|
"filtered": "Filtrati",
|
||||||
"latency": "Latenza"
|
"latency": "Latenza"
|
||||||
@@ -304,12 +304,12 @@
|
|||||||
"downloads": "Coda",
|
"downloads": "Coda",
|
||||||
"videos": "Video",
|
"videos": "Video",
|
||||||
"channels": "Canali",
|
"channels": "Canali",
|
||||||
"playlists": "Playlists"
|
"playlists": "Playlist"
|
||||||
},
|
},
|
||||||
"truenas": {
|
"truenas": {
|
||||||
"load": "Carico di Sistema",
|
"load": "Carico di Sistema",
|
||||||
"uptime": "Uptime",
|
"uptime": "Tempo di attività",
|
||||||
"alerts": "Alerts",
|
"alerts": "Avvisi",
|
||||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||||
},
|
},
|
||||||
"navidrome": {
|
"navidrome": {
|
||||||
@@ -323,26 +323,26 @@
|
|||||||
"total": "Totale"
|
"total": "Totale"
|
||||||
},
|
},
|
||||||
"gluetun": {
|
"gluetun": {
|
||||||
"public_ip": "Public IP",
|
"public_ip": "IP pubblico",
|
||||||
"region": "Region",
|
"region": "Località",
|
||||||
"country": "Country"
|
"country": "Stato"
|
||||||
},
|
},
|
||||||
"hdhomerun": {
|
"hdhomerun": {
|
||||||
"channels": "Channels",
|
"channels": "Canali",
|
||||||
"hd": "HD"
|
"hd": "HD"
|
||||||
},
|
},
|
||||||
"ping": {
|
"ping": {
|
||||||
"error": "Error",
|
"error": "Errore",
|
||||||
"ping": "Ping"
|
"ping": "Ping"
|
||||||
},
|
},
|
||||||
"scrutiny": {
|
"scrutiny": {
|
||||||
"passed": "Passed",
|
"passed": "Passati",
|
||||||
"failed": "Failed",
|
"failed": "Falliti",
|
||||||
"unknown": "Unknown"
|
"unknown": "Sconosciuto"
|
||||||
},
|
},
|
||||||
"paperlessngx": {
|
"paperlessngx": {
|
||||||
"inbox": "Inbox",
|
"inbox": "In arrivo",
|
||||||
"total": "Total"
|
"total": "Totali"
|
||||||
},
|
},
|
||||||
"deluge": {
|
"deluge": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "In coda",
|
||||||
|
"processed": "Elaborati",
|
||||||
|
"errored": "Errori",
|
||||||
|
"saved": "Salvati"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"unread": "Non letti",
|
||||||
|
"read": "Letti"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Attendi",
|
||||||
|
"no_devices": "Nessun dato del dispositivo ricevuto"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "AP Connessi",
|
||||||
|
"activeUser": "Dispositivi attivi",
|
||||||
|
"alerts": "Allarmi",
|
||||||
|
"connectedGateway": "Gateway connessi",
|
||||||
|
"connectedSwitches": "Switch connessi"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "Carico della CPU",
|
||||||
|
"memoryUsed": "Memoria Utilizzata",
|
||||||
|
"uptime": "Tempo di attività",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"upload": "Upload",
|
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"leech": "Leech",
|
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases",
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
"pending": "Oczekiwane",
|
"pending": "Oczekiwane",
|
||||||
"approved": "Zaakceptowane",
|
"approved": "Zaakceptowane",
|
||||||
"available": "Dostępne",
|
"available": "Dostępne",
|
||||||
"processing": "Processing"
|
"processing": "Przetwarzane"
|
||||||
},
|
},
|
||||||
"pihole": {
|
"pihole": {
|
||||||
"queries": "Zapytania",
|
"queries": "Zapytania",
|
||||||
@@ -336,24 +336,72 @@
|
|||||||
"ping": "Ping"
|
"ping": "Ping"
|
||||||
},
|
},
|
||||||
"scrutiny": {
|
"scrutiny": {
|
||||||
"passed": "Passed",
|
"passed": "Powodzenie",
|
||||||
"failed": "Failed",
|
"failed": "Niepowodzenie",
|
||||||
"unknown": "Unknown"
|
"unknown": "Nieznane"
|
||||||
},
|
},
|
||||||
"paperlessngx": {
|
"paperlessngx": {
|
||||||
"inbox": "Inbox",
|
"inbox": "Skrzynka odbiorcza",
|
||||||
"total": "Total"
|
"total": "W sumie"
|
||||||
},
|
},
|
||||||
"deluge": {
|
"deluge": {
|
||||||
"download": "Download",
|
"download": "Pobieranie",
|
||||||
"upload": "Upload",
|
"upload": "Wysyłanie",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Pobieranie",
|
||||||
"upload": "Upload",
|
"upload": "Wysyłanie",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Kolejka",
|
||||||
|
"processed": "Przetworzone",
|
||||||
|
"errored": "Błędne",
|
||||||
|
"saved": "Zapisane"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Przeczytane",
|
||||||
|
"unread": "Nieprzeczytane"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Proszę czekać",
|
||||||
|
"no_devices": "Nie otrzymano danych urządzenia"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedSwitches": "Połączone przełączniki",
|
||||||
|
"connectedAp": "Połączone punkty dostępowe",
|
||||||
|
"activeUser": "Aktywne urządzenia",
|
||||||
|
"alerts": "Alarmy",
|
||||||
|
"connectedGateway": "Połączone bramy"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Pobieranie",
|
||||||
|
"upload": "Wysyłanie",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "Obciążenie procesora",
|
||||||
|
"memoryUsed": "Zuyżyta pamięć",
|
||||||
|
"uptime": "Czas działania",
|
||||||
|
"numberOfLeases": "Dzierżawy"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
"widget": {
|
"widget": {
|
||||||
"missing_type": "Widget ausente: {{type}}",
|
"missing_type": "Widget ausente: {{type}}",
|
||||||
"api_error": "Erro da API",
|
"api_error": "Erro da API",
|
||||||
"status": "Status",
|
"status": "Estado",
|
||||||
"information": "Information",
|
"information": "Informação",
|
||||||
"url": "URL",
|
"url": "Endereço URL",
|
||||||
"raw_error": "Raw Error",
|
"raw_error": "Erro",
|
||||||
"response_data": "Response Data"
|
"response_data": "Dados da Resposta"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"placeholder": "Pesquisar…"
|
"placeholder": "Pesquisar…"
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
"mem": "Mem",
|
"mem": "Mem",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"offline": "Desligado",
|
"offline": "Desligado",
|
||||||
"error": "Error",
|
"error": "Erro",
|
||||||
"unknown": "Unknown"
|
"unknown": "Desconhecido"
|
||||||
},
|
},
|
||||||
"emby": {
|
"emby": {
|
||||||
"playing": "A reproduzir",
|
"playing": "A reproduzir",
|
||||||
@@ -104,7 +104,9 @@
|
|||||||
"byterate": "{{value, bytes}}",
|
"byterate": "{{value, bytes}}",
|
||||||
"ms": "{{value, number}}",
|
"ms": "{{value, number}}",
|
||||||
"bitrate": "{{value, bytes(bits: true)}}",
|
"bitrate": "{{value, bytes(bits: true)}}",
|
||||||
"percent": "{{value, percent}}"
|
"percent": "{{value, percent}}",
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
},
|
},
|
||||||
"weather": {
|
"weather": {
|
||||||
"current": "Localização atual",
|
"current": "Localização atual",
|
||||||
@@ -150,7 +152,7 @@
|
|||||||
"transmission": {
|
"transmission": {
|
||||||
"download": "Baixando",
|
"download": "Baixando",
|
||||||
"upload": "Enviando",
|
"upload": "Enviando",
|
||||||
"leech": "Sanguessugas",
|
"leech": "Leech",
|
||||||
"seed": "Semeadores"
|
"seed": "Semeadores"
|
||||||
},
|
},
|
||||||
"jackett": {
|
"jackett": {
|
||||||
@@ -201,55 +203,55 @@
|
|||||||
"vms": "VMs"
|
"vms": "VMs"
|
||||||
},
|
},
|
||||||
"unifi": {
|
"unifi": {
|
||||||
"users": "Users",
|
"users": "Utilizadores",
|
||||||
"uptime": "System Uptime",
|
"uptime": "Tempo de Atividade do Sistema",
|
||||||
"days": "Days",
|
"days": "Dias",
|
||||||
"wan": "WAN",
|
"wan": "WAN",
|
||||||
"lan_users": "LAN Users",
|
"lan_users": "Utilizadores LAN",
|
||||||
"wlan_users": "WLAN Users",
|
"wlan_users": "Utilizadores WLAN",
|
||||||
"up": "UP",
|
"up": "Ligados",
|
||||||
"down": "DOWN",
|
"down": "Desligados",
|
||||||
"wait": "Please wait",
|
"wait": "Por favor, aguarde",
|
||||||
"lan": "LAN",
|
"lan": "LAN",
|
||||||
"wlan": "WLAN",
|
"wlan": "WLAN",
|
||||||
"devices": "Devices",
|
"devices": "Dispositivos",
|
||||||
"lan_devices": "LAN Devices",
|
"lan_devices": "Dispositivos LAN",
|
||||||
"wlan_devices": "WLAN Devices"
|
"wlan_devices": "Dispositivos WLAN"
|
||||||
},
|
},
|
||||||
"plex": {
|
"plex": {
|
||||||
"streams": "Active Streams",
|
"streams": "Streams Ativas",
|
||||||
"movies": "Movies",
|
"movies": "Filmes",
|
||||||
"tv": "TV Shows"
|
"tv": "Series de TV"
|
||||||
},
|
},
|
||||||
"glances": {
|
"glances": {
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"mem": "MEM",
|
"mem": "MEM",
|
||||||
"wait": "Please wait"
|
"wait": "Por favor, aguarde"
|
||||||
},
|
},
|
||||||
"changedetectionio": {
|
"changedetectionio": {
|
||||||
"totalObserved": "Total Observed",
|
"totalObserved": "Total Observado",
|
||||||
"diffsDetected": "Diffs Detected"
|
"diffsDetected": "Diferenças Detetadas"
|
||||||
},
|
},
|
||||||
"wmo": {
|
"wmo": {
|
||||||
"0-day": "Sunny",
|
"0-day": "Solarengo",
|
||||||
"0-night": "Clear",
|
"0-night": "Limpo",
|
||||||
"1-day": "Mainly Sunny",
|
"1-day": "Maioritariamente ensolarado",
|
||||||
"1-night": "Mainly Clear",
|
"1-night": "Maioritariamente Limpo",
|
||||||
"2-day": "Partly Cloudy",
|
"2-day": "Parcialmente Nublado",
|
||||||
"2-night": "Partly Cloudy",
|
"2-night": "Parcialmente nublado",
|
||||||
"3-day": "Cloudy",
|
"3-day": "Nublado",
|
||||||
"3-night": "Cloudy",
|
"3-night": "Nublado",
|
||||||
"99-night": "Thunderstorm With Hail",
|
"99-night": "Thunderstorm With Hail",
|
||||||
"45-day": "Foggy",
|
"45-day": "Nevoeiro",
|
||||||
"45-night": "Foggy",
|
"45-night": "Nevoeiro",
|
||||||
"48-day": "Foggy",
|
"48-day": "Nevoeiro",
|
||||||
"48-night": "Foggy",
|
"48-night": "Nevoeiro",
|
||||||
"51-day": "Light Drizzle",
|
"51-day": "Aguaceiros",
|
||||||
"51-night": "Light Drizzle",
|
"51-night": "Aguaceiros",
|
||||||
"53-day": "Drizzle",
|
"53-day": "Chuvisco",
|
||||||
"53-night": "Drizzle",
|
"53-night": "Chuvisco",
|
||||||
"55-day": "Heavy Drizzle",
|
"55-day": "Aguaceiro Forte",
|
||||||
"55-night": "Heavy Drizzle",
|
"55-night": "Aguaceiro Forte",
|
||||||
"56-day": "Light Freezing Drizzle",
|
"56-day": "Light Freezing Drizzle",
|
||||||
"56-night": "Light Freezing Drizzle",
|
"56-night": "Light Freezing Drizzle",
|
||||||
"57-day": "Freezing Drizzle",
|
"57-day": "Freezing Drizzle",
|
||||||
@@ -289,8 +291,8 @@
|
|||||||
"99-day": "Thunderstorm With Hail"
|
"99-day": "Thunderstorm With Hail"
|
||||||
},
|
},
|
||||||
"quicklaunch": {
|
"quicklaunch": {
|
||||||
"bookmark": "Bookmark",
|
"bookmark": "Marcador",
|
||||||
"service": "Service"
|
"service": "Serviço"
|
||||||
},
|
},
|
||||||
"homebridge": {
|
"homebridge": {
|
||||||
"available_update": "System",
|
"available_update": "System",
|
||||||
@@ -343,7 +345,7 @@
|
|||||||
"hd": "HD"
|
"hd": "HD"
|
||||||
},
|
},
|
||||||
"ping": {
|
"ping": {
|
||||||
"error": "Error",
|
"error": "Erro",
|
||||||
"ping": "Ping"
|
"ping": "Ping"
|
||||||
},
|
},
|
||||||
"scrutiny": {
|
"scrutiny": {
|
||||||
@@ -361,10 +363,54 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"download": "Descarregar",
|
||||||
|
"upload": "Carregar",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"numberOfLeases": "Leases",
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"upload": "Upload",
|
||||||
|
"download": "Download",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedSwitches": "Connected switches",
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"seed": "Seed",
|
"leech": "Leech",
|
||||||
"leech": "Leech"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"download": "Download",
|
||||||
|
"seed": "Seed",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech"
|
"leech": "Leech"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"leech": "Leech",
|
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases",
|
||||||
|
"memoryUsed": "Memory Used"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
407
public/locales/uk/common.json
Normal file
407
public/locales/uk/common.json
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
{
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"alerts": "Оповіщення",
|
||||||
|
"connectedGateway": "Підключені шлюзи",
|
||||||
|
"connectedSwitches": "Підключені перемикачі",
|
||||||
|
"connectedAp": "Підключені точки доступу",
|
||||||
|
"activeUser": "Активні пристрої"
|
||||||
|
},
|
||||||
|
"sabnzbd": {
|
||||||
|
"rate": "Швидкість",
|
||||||
|
"queue": "Черга",
|
||||||
|
"timeleft": "Залишилось"
|
||||||
|
},
|
||||||
|
"rutorrent": {
|
||||||
|
"active": "Активний",
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"download": "Завантаження"
|
||||||
|
},
|
||||||
|
"deluge": {
|
||||||
|
"download": "Завантаження",
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"readarr": {
|
||||||
|
"wanted": "Розшукується",
|
||||||
|
"queued": "У черзі",
|
||||||
|
"books": "Книжки"
|
||||||
|
},
|
||||||
|
"wmo": {
|
||||||
|
"55-day": "Heavy Drizzle",
|
||||||
|
"55-night": "Heavy Drizzle",
|
||||||
|
"56-day": "Light Freezing Drizzle",
|
||||||
|
"56-night": "Light Freezing Drizzle",
|
||||||
|
"0-day": "Sunny",
|
||||||
|
"0-night": "Clear",
|
||||||
|
"1-day": "Mainly Sunny",
|
||||||
|
"1-night": "Mainly Clear",
|
||||||
|
"2-day": "Partly Cloudy",
|
||||||
|
"2-night": "Partly Cloudy",
|
||||||
|
"3-day": "Cloudy",
|
||||||
|
"3-night": "Cloudy",
|
||||||
|
"53-day": "Drizzle",
|
||||||
|
"45-day": "Foggy",
|
||||||
|
"45-night": "Foggy",
|
||||||
|
"48-day": "Foggy",
|
||||||
|
"48-night": "Foggy",
|
||||||
|
"51-day": "Light Drizzle",
|
||||||
|
"51-night": "Light Drizzle",
|
||||||
|
"53-night": "Drizzle",
|
||||||
|
"57-day": "Freezing Drizzle",
|
||||||
|
"57-night": "Freezing Drizzle",
|
||||||
|
"61-day": "Light Rain",
|
||||||
|
"61-night": "Light Rain",
|
||||||
|
"63-day": "Rain",
|
||||||
|
"63-night": "Rain",
|
||||||
|
"65-day": "Heavy Rain",
|
||||||
|
"65-night": "Heavy Rain",
|
||||||
|
"66-day": "Freezing Rain",
|
||||||
|
"66-night": "Freezing Rain",
|
||||||
|
"67-day": "Freezing Rain",
|
||||||
|
"67-night": "Freezing Rain",
|
||||||
|
"71-day": "Light Snow",
|
||||||
|
"71-night": "Light Snow",
|
||||||
|
"73-day": "Snow",
|
||||||
|
"73-night": "Snow",
|
||||||
|
"75-day": "Heavy Snow",
|
||||||
|
"75-night": "Heavy Snow",
|
||||||
|
"77-day": "Snow Grains",
|
||||||
|
"77-night": "Snow Grains",
|
||||||
|
"80-day": "Light Showers",
|
||||||
|
"80-night": "Light Showers",
|
||||||
|
"81-day": "Showers",
|
||||||
|
"82-day": "Heavy Showers",
|
||||||
|
"82-night": "Heavy Showers",
|
||||||
|
"81-night": "Showers",
|
||||||
|
"85-day": "Snow Showers",
|
||||||
|
"85-night": "Snow Showers",
|
||||||
|
"86-day": "Snow Showers",
|
||||||
|
"86-night": "Snow Showers",
|
||||||
|
"95-day": "Thunderstorm",
|
||||||
|
"95-night": "Thunderstorm",
|
||||||
|
"96-day": "Thunderstorm With Hail",
|
||||||
|
"96-night": "Thunderstorm With Hail",
|
||||||
|
"99-day": "Thunderstorm With Hail",
|
||||||
|
"99-night": "Thunderstorm With Hail"
|
||||||
|
},
|
||||||
|
"pyload": {
|
||||||
|
"speed": "Speed",
|
||||||
|
"active": "Active",
|
||||||
|
"queue": "Queue",
|
||||||
|
"total": "Total"
|
||||||
|
},
|
||||||
|
"gluetun": {
|
||||||
|
"country": "Country",
|
||||||
|
"public_ip": "Public IP",
|
||||||
|
"region": "Region"
|
||||||
|
},
|
||||||
|
"hdhomerun": {
|
||||||
|
"channels": "Channels",
|
||||||
|
"hd": "HD"
|
||||||
|
},
|
||||||
|
"widget": {
|
||||||
|
"missing_type": "Відсутній тип віджета: {{type}}",
|
||||||
|
"api_error": "Помилка API",
|
||||||
|
"information": "Інформація",
|
||||||
|
"status": "Стан",
|
||||||
|
"url": "URL",
|
||||||
|
"raw_error": "Помилка Raw",
|
||||||
|
"response_data": "Дані відповіді"
|
||||||
|
},
|
||||||
|
"weather": {
|
||||||
|
"current": "Поточне розташування",
|
||||||
|
"allow": "Натисніть, щоб дозволити",
|
||||||
|
"updating": "Оновлення",
|
||||||
|
"wait": "Будь ласка, зачекайте"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"placeholder": "Пошук…"
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"cpu": "CPU",
|
||||||
|
"total": "Всього",
|
||||||
|
"free": "Вільно",
|
||||||
|
"used": "Використано",
|
||||||
|
"load": "Навантаження"
|
||||||
|
},
|
||||||
|
"unifi": {
|
||||||
|
"users": "Користувачі",
|
||||||
|
"uptime": "Час роботи системи",
|
||||||
|
"days": "Днів",
|
||||||
|
"wan": "WAN",
|
||||||
|
"lan": "LAN",
|
||||||
|
"wlan": "WLAN",
|
||||||
|
"devices": "Пристрої",
|
||||||
|
"lan_devices": "LAN пристрої",
|
||||||
|
"wlan_devices": "WLAN пристрої",
|
||||||
|
"lan_users": "LAN користувачі",
|
||||||
|
"wlan_users": "WLAN користувачі",
|
||||||
|
"up": "Відправка",
|
||||||
|
"down": "Завантаження",
|
||||||
|
"wait": "Будь ласка, зачекайте"
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"rx": "RX",
|
||||||
|
"tx": "TX",
|
||||||
|
"mem": "Пам'ять",
|
||||||
|
"cpu": "CPU",
|
||||||
|
"offline": "Офлайн",
|
||||||
|
"error": "Помилка",
|
||||||
|
"unknown": "Невідомий"
|
||||||
|
},
|
||||||
|
"ping": {
|
||||||
|
"error": "Помилка",
|
||||||
|
"ping": "Пінг"
|
||||||
|
},
|
||||||
|
"emby": {
|
||||||
|
"playing": "Відтворення",
|
||||||
|
"transcoding": "Перекодування",
|
||||||
|
"bitrate": "Бітрейт",
|
||||||
|
"no_active": "Немає активних потоків"
|
||||||
|
},
|
||||||
|
"flood": {
|
||||||
|
"download": "Завантаження",
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"changedetectionio": {
|
||||||
|
"totalObserved": "Всього спостережень",
|
||||||
|
"diffsDetected": "Виявлено відмінності"
|
||||||
|
},
|
||||||
|
"tautulli": {
|
||||||
|
"playing": "Відтворення",
|
||||||
|
"transcoding": "Перекодування",
|
||||||
|
"bitrate": "Бітрейт",
|
||||||
|
"no_active": "Немає активних потоків"
|
||||||
|
},
|
||||||
|
"nzbget": {
|
||||||
|
"rate": "Швидкість",
|
||||||
|
"downloaded": "Завантажено",
|
||||||
|
"remaining": "Залишилося"
|
||||||
|
},
|
||||||
|
"plex": {
|
||||||
|
"streams": "Активні потоки",
|
||||||
|
"movies": "Фільми",
|
||||||
|
"tv": "TБ шоу"
|
||||||
|
},
|
||||||
|
"transmission": {
|
||||||
|
"download": "Завантаження",
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"qbittorrent": {
|
||||||
|
"download": "Завантаження",
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Завантаження",
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"sonarr": {
|
||||||
|
"wanted": "Розшукується",
|
||||||
|
"queued": "У черзі",
|
||||||
|
"series": "Серії"
|
||||||
|
},
|
||||||
|
"radarr": {
|
||||||
|
"wanted": "Розшукується",
|
||||||
|
"missing": "Відсутній",
|
||||||
|
"queued": "У черзі",
|
||||||
|
"movies": "Фільми"
|
||||||
|
},
|
||||||
|
"lidarr": {
|
||||||
|
"wanted": "Розшукується",
|
||||||
|
"queued": "У черзі",
|
||||||
|
"albums": "Альбоми"
|
||||||
|
},
|
||||||
|
"traefik": {
|
||||||
|
"middleware": "Middleware",
|
||||||
|
"routers": "Роутери",
|
||||||
|
"services": "Сервіси"
|
||||||
|
},
|
||||||
|
"navidrome": {
|
||||||
|
"nothing_streaming": "No Active Streams",
|
||||||
|
"please_wait": "Please Wait"
|
||||||
|
},
|
||||||
|
"bazarr": {
|
||||||
|
"missingEpisodes": "Відсутні епізоди",
|
||||||
|
"missingMovies": "Відсутні фільми"
|
||||||
|
},
|
||||||
|
"ombi": {
|
||||||
|
"pending": "В очікуванні",
|
||||||
|
"approved": "Затверджено",
|
||||||
|
"available": "Доступно"
|
||||||
|
},
|
||||||
|
"jellyseerr": {
|
||||||
|
"pending": "В очікуванні",
|
||||||
|
"approved": "Затверджено",
|
||||||
|
"available": "Доступно"
|
||||||
|
},
|
||||||
|
"overseerr": {
|
||||||
|
"pending": "В очікуванні",
|
||||||
|
"processing": "Обробка",
|
||||||
|
"approved": "Затверджено",
|
||||||
|
"available": "Доступно"
|
||||||
|
},
|
||||||
|
"pihole": {
|
||||||
|
"queries": "Запити",
|
||||||
|
"blocked": "Заблоковано",
|
||||||
|
"gravity": "Гравітація"
|
||||||
|
},
|
||||||
|
"adguard": {
|
||||||
|
"queries": "Запити",
|
||||||
|
"blocked": "Заблоковано",
|
||||||
|
"filtered": "Відфільтровано",
|
||||||
|
"latency": "Затримка"
|
||||||
|
},
|
||||||
|
"speedtest": {
|
||||||
|
"upload": "Відправлення",
|
||||||
|
"download": "Завантаження",
|
||||||
|
"ping": "Пінг"
|
||||||
|
},
|
||||||
|
"portainer": {
|
||||||
|
"running": "Запущено",
|
||||||
|
"stopped": "Зупинено",
|
||||||
|
"total": "Всього"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Черга",
|
||||||
|
"processed": "Обробка",
|
||||||
|
"errored": "Помилка",
|
||||||
|
"saved": "Збережено"
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"enabled": "Enabled",
|
||||||
|
"disabled": "Disabled",
|
||||||
|
"total": "Total"
|
||||||
|
},
|
||||||
|
"coinmarketcap": {
|
||||||
|
"configure": "Configure one or more crypto currencies to track",
|
||||||
|
"1hour": "1 Hour",
|
||||||
|
"1day": "1 Day",
|
||||||
|
"7days": "7 Days",
|
||||||
|
"30days": "30 Days"
|
||||||
|
},
|
||||||
|
"mastodon": {
|
||||||
|
"domain_count": "Domains",
|
||||||
|
"user_count": "Users",
|
||||||
|
"status_count": "Posts"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"gotify": {
|
||||||
|
"apps": "Applications",
|
||||||
|
"clients": "Clients",
|
||||||
|
"messages": "Messages"
|
||||||
|
},
|
||||||
|
"prowlarr": {
|
||||||
|
"enableIndexers": "Indexers",
|
||||||
|
"numberOfGrabs": "Grabs",
|
||||||
|
"numberOfQueries": "Queries",
|
||||||
|
"numberOfFailGrabs": "Fail Grabs",
|
||||||
|
"numberOfFailQueries": "Fail Queries"
|
||||||
|
},
|
||||||
|
"jackett": {
|
||||||
|
"configured": "Configured",
|
||||||
|
"errored": "Errored"
|
||||||
|
},
|
||||||
|
"strelaysrv": {
|
||||||
|
"numActiveSessions": "Sessions",
|
||||||
|
"numConnections": "Connections",
|
||||||
|
"dataRelayed": "Relayed",
|
||||||
|
"transferRate": "Rate"
|
||||||
|
},
|
||||||
|
"authentik": {
|
||||||
|
"users": "Users",
|
||||||
|
"loginsLast24H": "Logins (24h)",
|
||||||
|
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||||
|
},
|
||||||
|
"proxmox": {
|
||||||
|
"mem": "MEM",
|
||||||
|
"cpu": "CPU",
|
||||||
|
"vms": "VMs",
|
||||||
|
"lxc": "LXC"
|
||||||
|
},
|
||||||
|
"glances": {
|
||||||
|
"cpu": "CPU",
|
||||||
|
"mem": "MEM",
|
||||||
|
"wait": "Please wait"
|
||||||
|
},
|
||||||
|
"quicklaunch": {
|
||||||
|
"bookmark": "Bookmark",
|
||||||
|
"service": "Service"
|
||||||
|
},
|
||||||
|
"homebridge": {
|
||||||
|
"available_update": "System",
|
||||||
|
"updates": "Updates",
|
||||||
|
"child_bridges_status": "{{ok}}/{{total}}",
|
||||||
|
"update_available": "Update Available",
|
||||||
|
"up_to_date": "Up to Date",
|
||||||
|
"child_bridges": "Child Bridges"
|
||||||
|
},
|
||||||
|
"watchtower": {
|
||||||
|
"containers_scanned": "Scanned",
|
||||||
|
"containers_updated": "Updated",
|
||||||
|
"containers_failed": "Failed"
|
||||||
|
},
|
||||||
|
"autobrr": {
|
||||||
|
"approvedPushes": "Approved",
|
||||||
|
"rejectedPushes": "Rejected",
|
||||||
|
"filters": "Filters",
|
||||||
|
"indexers": "Indexers"
|
||||||
|
},
|
||||||
|
"tubearchivist": {
|
||||||
|
"downloads": "Queue",
|
||||||
|
"videos": "Videos",
|
||||||
|
"channels": "Channels",
|
||||||
|
"playlists": "Playlists"
|
||||||
|
},
|
||||||
|
"truenas": {
|
||||||
|
"load": "System Load",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||||
|
},
|
||||||
|
"scrutiny": {
|
||||||
|
"passed": "Passed",
|
||||||
|
"failed": "Failed",
|
||||||
|
"unknown": "Unknown"
|
||||||
|
},
|
||||||
|
"paperlessngx": {
|
||||||
|
"inbox": "Inbox",
|
||||||
|
"total": "Total"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"seed": "Seed",
|
||||||
|
"leech": "Leech"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases",
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
|
"leech": "Leech",
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"saved": "Saved",
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,58 @@
|
|||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
},
|
},
|
||||||
"diskstation": {
|
"flood": {
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"leech": "Leech",
|
"leech": "Leech",
|
||||||
"seed": "Seed"
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"tdarr": {
|
||||||
|
"queue": "Queue",
|
||||||
|
"processed": "Processed",
|
||||||
|
"errored": "Errored",
|
||||||
|
"saved": "Saved"
|
||||||
|
},
|
||||||
|
"miniflux": {
|
||||||
|
"read": "Read",
|
||||||
|
"unread": "Unread"
|
||||||
|
},
|
||||||
|
"nextdns": {
|
||||||
|
"wait": "Please Wait",
|
||||||
|
"no_devices": "No Device Data Received"
|
||||||
|
},
|
||||||
|
"common": {
|
||||||
|
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||||
|
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||||
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
|
"downloadstation": {
|
||||||
|
"download": "Download",
|
||||||
|
"upload": "Upload",
|
||||||
|
"leech": "Leech",
|
||||||
|
"seed": "Seed"
|
||||||
|
},
|
||||||
|
"mikrotik": {
|
||||||
|
"cpuLoad": "CPU Load",
|
||||||
|
"memoryUsed": "Memory Used",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"numberOfLeases": "Leases"
|
||||||
|
},
|
||||||
|
"xteve": {
|
||||||
|
"streams_all": "All Streams",
|
||||||
|
"streams_active": "Active Streams",
|
||||||
|
"streams_xepg": "XEPG Channels"
|
||||||
|
},
|
||||||
|
"opnsense": {
|
||||||
|
"cpu": "CPU Load",
|
||||||
|
"memory": "Active Memory",
|
||||||
|
"wanUpload": "WAN Upload",
|
||||||
|
"wanDownload": "WAN Download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
|||||||
|
|
||||||
function highlightText(text) {
|
function highlightText(text) {
|
||||||
const parts = text.split(new RegExp(`(${searchString})`, 'gi'));
|
const parts = text.split(new RegExp(`(${searchString})`, 'gi'));
|
||||||
return <span>{parts.map(part => part.toLowerCase() === searchString.toLowerCase() ? <span className="bg-theme-300/10">{part}</span> : part)}</span>;
|
// eslint-disable-next-line react/no-array-index-key
|
||||||
|
return <span>{parts.map((part, i) => part.toLowerCase() === searchString.toLowerCase() ? <span key={`${searchString}_${i}`} className="bg-theme-300/10">{part}</span> : part)}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Image from "next/future/image";
|
import Image from "next/future/image";
|
||||||
|
|
||||||
export default function ResolvedIcon({ icon }) {
|
export default function ResolvedIcon({ icon, width = 32, height = 32 }) {
|
||||||
// direct or relative URLs
|
// direct or relative URLs
|
||||||
if (icon.startsWith("http") || icon.startsWith("/")) {
|
if (icon.startsWith("http") || icon.startsWith("/")) {
|
||||||
return <Image src={`${icon}`} width={32} height={32} alt="logo" />;
|
return <Image src={`${icon}`} width={width} height={height} alt="logo" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mdi- prefixed, material design icons
|
// mdi- prefixed, material design icons
|
||||||
@@ -12,8 +12,8 @@ export default function ResolvedIcon({ icon }) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: 32,
|
width,
|
||||||
height: 32,
|
height,
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
maxHeight: '100%',
|
maxHeight: '100%',
|
||||||
background: "linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))",
|
background: "linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))",
|
||||||
@@ -29,8 +29,8 @@ export default function ResolvedIcon({ icon }) {
|
|||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
||||||
width={32}
|
width={width}
|
||||||
height={32}
|
height={height}
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default function Version() {
|
|||||||
const revision = process.env.NEXT_PUBLIC_REVISION?.length ? process.env.NEXT_PUBLIC_REVISION : "dev";
|
const revision = process.env.NEXT_PUBLIC_REVISION?.length ? process.env.NEXT_PUBLIC_REVISION : "dev";
|
||||||
const version = process.env.NEXT_PUBLIC_VERSION?.length ? process.env.NEXT_PUBLIC_VERSION : "dev";
|
const version = process.env.NEXT_PUBLIC_VERSION?.length ? process.env.NEXT_PUBLIC_VERSION : "dev";
|
||||||
|
|
||||||
const cachedFetcher = (resource) => cachedFetch(resource, 5).then((res) => res.json());
|
const cachedFetcher = (resource) => cachedFetch(resource, 5);
|
||||||
|
|
||||||
const { data: releaseData } = useSWR("https://api.github.com/repos/benphelps/homepage/releases", cachedFetcher);
|
const { data: releaseData } = useSWR("https://api.github.com/repos/benphelps/homepage/releases", cachedFetcher);
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +1,62 @@
|
|||||||
export default function Logo() {
|
import ResolvedIcon from "components/resolvedicon"
|
||||||
|
|
||||||
|
export default function Logo({ options }) {
|
||||||
return (
|
return (
|
||||||
<div className="w-12 h-12 flex flex-row items-center align-middle mr-3 self-center">
|
<div className="w-12 h-12 flex flex-row items-center align-middle mr-3 self-center">
|
||||||
<svg
|
{options.icon ?
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<ResolvedIcon icon={options.icon} width={48} height={48} /> :
|
||||||
viewBox="0 0 1024 1024"
|
// fallback to homepage logo
|
||||||
style={{
|
<svg
|
||||||
enableBackground: "new 0 0 1024 1024",
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
}}
|
viewBox="0 0 1024 1024"
|
||||||
xmlSpace="preserve"
|
style={{
|
||||||
className="w-full h-full"
|
enableBackground: "new 0 0 1024 1024",
|
||||||
>
|
}}
|
||||||
<style>
|
xmlSpace="preserve"
|
||||||
{
|
className="w-full h-full"
|
||||||
".st0{display:none}.st3{stroke-linecap:square}.st3,.st4{fill:none;stroke:#fff;stroke-miterlimit:10}.st6{display:inline;fill:#333}.st7{fill:#fff}"
|
>
|
||||||
}
|
<style>
|
||||||
</style>
|
{
|
||||||
<g id="Icon">
|
".st0{display:none}.st3{stroke-linecap:square}.st3,.st4{fill:none;stroke:#fff;stroke-miterlimit:10}.st6{display:inline;fill:#333}.st7{fill:#fff}"
|
||||||
<path
|
}
|
||||||
d="M771.9 191c27.7 0 50.1 26.5 50.1 59.3v186.4l-100.2.3V250.3c0-32.8 22.4-59.3 50.1-59.3z"
|
</style>
|
||||||
style={{
|
<g id="Icon">
|
||||||
fill: "rgba(var(--color-logo-start))",
|
<path
|
||||||
}}
|
d="M771.9 191c27.7 0 50.1 26.5 50.1 59.3v186.4l-100.2.3V250.3c0-32.8 22.4-59.3 50.1-59.3z"
|
||||||
/>
|
|
||||||
<linearGradient
|
|
||||||
id="homepage_logo_gradient"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
x1={200.746}
|
|
||||||
y1={225.015}
|
|
||||||
x2={764.986}
|
|
||||||
y2={789.255}
|
|
||||||
>
|
|
||||||
<stop
|
|
||||||
offset={0}
|
|
||||||
style={{
|
style={{
|
||||||
stopColor: "rgba(var(--color-logo-start))",
|
fill: "rgba(var(--color-logo-start))",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<stop
|
<linearGradient
|
||||||
offset={1}
|
id="homepage_logo_gradient"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1={200.746}
|
||||||
|
y1={225.015}
|
||||||
|
x2={764.986}
|
||||||
|
y2={789.255}
|
||||||
|
>
|
||||||
|
<stop
|
||||||
|
offset={0}
|
||||||
|
style={{
|
||||||
|
stopColor: "rgba(var(--color-logo-start))",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<stop
|
||||||
|
offset={1}
|
||||||
|
style={{
|
||||||
|
stopColor: "rgba(var(--color-logo-stop))",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
d="M721.8 250.3c0-32.7 22.4-59.3 50.1-59.3H253.1c-27.7 0-50.1 26.5-50.1 59.3v582.2l90.2-75.7-.1-130.3H375v61.8l88-73.8 258.8 217.9V250.6"
|
||||||
style={{
|
style={{
|
||||||
stopColor: "rgba(var(--color-logo-stop))",
|
fill: "url(#homepage_logo_gradient)",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</linearGradient>
|
</g>
|
||||||
<path
|
</svg>
|
||||||
d="M721.8 250.3c0-32.7 22.4-59.3 50.1-59.3H253.1c-27.7 0-50.1 26.5-50.1 59.3v582.2l90.2-75.7-.1-130.3H375v61.8l88-73.8 258.8 217.9V250.6"
|
}
|
||||||
style={{
|
|
||||||
fill: "url(#homepage_logo_gradient)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import mapIcon from "utils/weather/owm-condition-map";
|
import mapIcon from "utils/weather/openmeteo-condition-map";
|
||||||
|
|
||||||
export default function Icon({ condition, timeOfDay }) {
|
export default function Icon({ condition, timeOfDay }) {
|
||||||
const IconComponent = mapIcon(condition, timeOfDay);
|
const IconComponent = mapIcon(condition, timeOfDay);
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ export default async function handler(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const docker = new Docker(getDockerArguments(containerServer));
|
const dockerArgs = getDockerArguments(containerServer);
|
||||||
|
const docker = new Docker(dockerArgs.conn);
|
||||||
const containers = await docker.listContainers({
|
const containers = await docker.listContainers({
|
||||||
all: true,
|
all: true,
|
||||||
});
|
});
|
||||||
@@ -31,18 +32,44 @@ export default async function handler(req, res) {
|
|||||||
const containerNames = containers.map((container) => container.Names[0].replace(/^\//, ""));
|
const containerNames = containers.map((container) => container.Names[0].replace(/^\//, ""));
|
||||||
const containerExists = containerNames.includes(containerName);
|
const containerExists = containerNames.includes(containerName);
|
||||||
|
|
||||||
if (!containerExists) {
|
if (containerExists) {
|
||||||
res.status(200).send({
|
const container = docker.getContainer(containerName);
|
||||||
error: "not found",
|
const stats = await container.stats({ stream: false });
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
stats,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const container = docker.getContainer(containerName);
|
// Try with a service deployed in Docker Swarm, if enabled
|
||||||
const stats = await container.stats({ stream: false });
|
if (dockerArgs.swarm) {
|
||||||
|
const tasks = await docker.listTasks({
|
||||||
|
filters: {
|
||||||
|
service: [containerName],
|
||||||
|
// A service can have several offline containers, so we only look for an active one.
|
||||||
|
"desired-state": ["running"],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch(() => []);
|
||||||
|
|
||||||
res.status(200).json({
|
// For now we are only interested in the first one (in case replicas > 1).
|
||||||
stats,
|
// TODO: Show the result for all replicas/containers?
|
||||||
|
const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID;
|
||||||
|
|
||||||
|
if (taskContainerId) {
|
||||||
|
const container = docker.getContainer(taskContainerId);
|
||||||
|
const stats = await container.stats({ stream: false });
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
stats,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send({
|
||||||
|
error: "not found",
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
res.status(500).send({
|
res.status(500).send({
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ export default async function handler(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const docker = new Docker(getDockerArguments(containerServer));
|
const dockerArgs = getDockerArguments(containerServer);
|
||||||
|
const docker = new Docker(dockerArgs.conn);
|
||||||
const containers = await docker.listContainers({
|
const containers = await docker.listContainers({
|
||||||
all: true,
|
all: true,
|
||||||
});
|
});
|
||||||
@@ -29,18 +30,43 @@ export default async function handler(req, res) {
|
|||||||
const containerNames = containers.map((container) => container.Names[0].replace(/^\//, ""));
|
const containerNames = containers.map((container) => container.Names[0].replace(/^\//, ""));
|
||||||
const containerExists = containerNames.includes(containerName);
|
const containerExists = containerNames.includes(containerName);
|
||||||
|
|
||||||
if (!containerExists) {
|
if (containerExists) {
|
||||||
return res.status(200).send({
|
const container = docker.getContainer(containerName);
|
||||||
error: "not found",
|
const info = await container.inspect();
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: info.State.Status,
|
||||||
|
health: info.State.Health?.Status,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const container = docker.getContainer(containerName);
|
if (dockerArgs.swarm) {
|
||||||
const info = await container.inspect();
|
const tasks = await docker.listTasks({
|
||||||
|
filters: {
|
||||||
|
service: [containerName],
|
||||||
|
// A service can have several offline containers, we only look for an active one.
|
||||||
|
"desired-state": ["running"],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.catch(() => []);
|
||||||
|
|
||||||
return res.status(200).json({
|
// For now we are only interested in the first one (in case replicas > 1).
|
||||||
status: info.State.Status,
|
// TODO: Show the result for all replicas/containers?
|
||||||
health: info.State.Health?.Status
|
const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID;
|
||||||
|
|
||||||
|
if (taskContainerId) {
|
||||||
|
const container = docker.getContainer(taskContainerId);
|
||||||
|
const info = await container.inspect();
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
status: info.State.Status,
|
||||||
|
health: info.State.Health?.Status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
error: "not found",
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
return res.status(500).send({
|
return res.status(500).send({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import cachedFetch from "utils/proxy/cached-fetch";
|
import cachedFetch from "utils/proxy/cached-fetch";
|
||||||
|
|
||||||
export default async function handler(req, res) {
|
export default async function handler(req, res) {
|
||||||
const { latitude, longitude, units, cache } = req.query;
|
const { latitude, longitude, units, cache, timezone } = req.query;
|
||||||
const degrees = units === "imperial" ? "fahrenheit" : "celsius";
|
const degrees = units === "imperial" ? "fahrenheit" : "celsius";
|
||||||
const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=sunrise,sunset¤t_weather=true&temperature_unit=${degrees}&timezone=auto`;
|
const timezeone = timezone ?? 'auto'
|
||||||
|
const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=sunrise,sunset¤t_weather=true&temperature_unit=${degrees}&timezone=${timezeone}`;
|
||||||
return res.send(await cachedFetch(apiUrl, cache));
|
return res.send(await cachedFetch(apiUrl, cache));
|
||||||
}
|
}
|
||||||
@@ -22,11 +22,14 @@ export default function getDockerArguments(server) {
|
|||||||
|
|
||||||
if (servers[server]) {
|
if (servers[server]) {
|
||||||
if (servers[server].socket) {
|
if (servers[server].socket) {
|
||||||
return { socketPath: servers[server].socket };
|
return { conn: { socketPath: servers[server].socket }, swarm: !!servers[server].swarm };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (servers[server].host) {
|
if (servers[server].host) {
|
||||||
return { host: servers[server].host, port: servers[server].port || null };
|
return {
|
||||||
|
conn: { host: servers[server].host, port: servers[server].port || null },
|
||||||
|
swarm: !!servers[server].swarm,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return servers[server];
|
return servers[server];
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export async function servicesFromDocker() {
|
|||||||
|
|
||||||
const serviceServers = await Promise.all(
|
const serviceServers = await Promise.all(
|
||||||
Object.keys(servers).map(async (serverName) => {
|
Object.keys(servers).map(async (serverName) => {
|
||||||
const docker = new Docker(getDockerArguments(serverName));
|
const docker = new Docker(getDockerArguments(serverName).conn);
|
||||||
const containers = await docker.listContainers({
|
const containers = await docker.listContainers({
|
||||||
all: true,
|
all: true,
|
||||||
});
|
});
|
||||||
@@ -118,6 +118,7 @@ export function cleanServiceGroups(groups) {
|
|||||||
container,
|
container,
|
||||||
currency, // coinmarketcap widget
|
currency, // coinmarketcap widget
|
||||||
symbols,
|
symbols,
|
||||||
|
defaultinterval
|
||||||
} = cleanedService.widget;
|
} = cleanedService.widget;
|
||||||
|
|
||||||
cleanedService.widget = {
|
cleanedService.widget = {
|
||||||
@@ -129,6 +130,7 @@ export function cleanServiceGroups(groups) {
|
|||||||
|
|
||||||
if (currency) cleanedService.widget.currency = currency;
|
if (currency) cleanedService.widget.currency = currency;
|
||||||
if (symbols) cleanedService.widget.symbols = symbols;
|
if (symbols) cleanedService.widget.symbols = symbols;
|
||||||
|
if (defaultinterval) cleanedService.widget.defaultinterval = defaultinterval;
|
||||||
|
|
||||||
if (type === "docker") {
|
if (type === "docker") {
|
||||||
if (server) cleanedService.widget.server = server;
|
if (server) cleanedService.widget.server = server;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import widgets from "widgets/widgets";
|
|||||||
|
|
||||||
const logger = createLogger("credentialedProxyHandler");
|
const logger = createLogger("credentialedProxyHandler");
|
||||||
|
|
||||||
export default async function credentialedProxyHandler(req, res) {
|
export default async function credentialedProxyHandler(req, res, map) {
|
||||||
const { group, service, endpoint } = req.query;
|
const { group, service, endpoint } = req.query;
|
||||||
|
|
||||||
if (group && service) {
|
if (group && service) {
|
||||||
@@ -36,6 +36,8 @@ export default async function credentialedProxyHandler(req, res) {
|
|||||||
headers["X-API-Token"] = `${widget.key}`;
|
headers["X-API-Token"] = `${widget.key}`;
|
||||||
} else if (widget.type === "tubearchivist") {
|
} else if (widget.type === "tubearchivist") {
|
||||||
headers.Authorization = `Token ${widget.key}`;
|
headers.Authorization = `Token ${widget.key}`;
|
||||||
|
} else if (widget.type === "miniflux") {
|
||||||
|
headers["X-Auth-Token"] = `${widget.key}`;
|
||||||
} else {
|
} else {
|
||||||
headers["X-API-Key"] = `${widget.key}`;
|
headers["X-API-Key"] = `${widget.key}`;
|
||||||
}
|
}
|
||||||
@@ -47,6 +49,8 @@ export default async function credentialedProxyHandler(req, res) {
|
|||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let resultData = data;
|
||||||
|
|
||||||
if (status === 204 || status === 304) {
|
if (status === 204 || status === 304) {
|
||||||
return res.status(status).end();
|
return res.status(status).end();
|
||||||
}
|
}
|
||||||
@@ -59,8 +63,12 @@ export default async function credentialedProxyHandler(req, res) {
|
|||||||
return res.status(500).json({error: {message: "Invalid data", url, data}});
|
return res.status(500).json({error: {message: "Invalid data", url, data}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status === 200 && map) {
|
||||||
|
resultData = map(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (contentType) res.setHeader("Content-Type", contentType);
|
if (contentType) res.setHeader("Content-Type", contentType);
|
||||||
return res.status(status).send(data);
|
return res.status(status).send(resultData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
211
src/utils/weather/openmeteo-condition-map.js
Normal file
211
src/utils/weather/openmeteo-condition-map.js
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
import * as Icons from "react-icons/wi";
|
||||||
|
|
||||||
|
// see https://open-meteo.com/en/docs
|
||||||
|
|
||||||
|
const conditions = [
|
||||||
|
{
|
||||||
|
code: 1,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayCloudy,
|
||||||
|
night: Icons.WiNightAltCloudy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 2,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayCloudy,
|
||||||
|
night: Icons.WiNightAltCloudy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 3,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayCloudy,
|
||||||
|
night: Icons.WiNightAltCloudy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 45,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayFog,
|
||||||
|
night: Icons.WiNightFog,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 48,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayFog,
|
||||||
|
night: Icons.WiNightFog,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 51,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySprinkle,
|
||||||
|
night: Icons.WiNightAltSprinkle,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 53,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySprinkle,
|
||||||
|
night: Icons.WiNightAltSprinkle,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 55,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySprinkle,
|
||||||
|
night: Icons.WiNightAltSprinkle,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 56,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySleet,
|
||||||
|
night: Icons.WiNightAltSleet,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 57,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySleet,
|
||||||
|
night: Icons.WiNightAltSleet,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 61,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayShowers,
|
||||||
|
night: Icons.WiNightAltShowers,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 63,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayShowers,
|
||||||
|
night: Icons.WiNightAltShowers,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 65,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayShowers,
|
||||||
|
night: Icons.WiNightAltShowers,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 66,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySleet,
|
||||||
|
night: Icons.WiNightAltSleet,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 67,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySleet,
|
||||||
|
night: Icons.WiNightAltSleet,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 71,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 73,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 75,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 77,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 80,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 81,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 82,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 85,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 86,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDaySnow,
|
||||||
|
night: Icons.WiNightAltSnow,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 95,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayThunderstorm,
|
||||||
|
night: Icons.WiNightAltThunderstorm,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 96,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayThunderstorm,
|
||||||
|
night: Icons.WiNightAltThunderstorm,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 99,
|
||||||
|
icon: {
|
||||||
|
day: Icons.WiDayThunderstorm,
|
||||||
|
night: Icons.WiNightAltThunderstorm,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function mapIcon(weatherStatusCode, timeOfDay) {
|
||||||
|
const mapping = conditions.find((condition) => condition.code === weatherStatusCode);
|
||||||
|
|
||||||
|
if (mapping) {
|
||||||
|
if (timeOfDay === "day") {
|
||||||
|
return mapping.icon.day;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeOfDay === "night") {
|
||||||
|
return mapping.icon.night;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Icons.WiDaySunny;
|
||||||
|
}
|
||||||
@@ -17,11 +17,12 @@ export default function Component({ service }) {
|
|||||||
{ label: t("coinmarketcap.30days"), value: "30d" },
|
{ label: t("coinmarketcap.30days"), value: "30d" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const [dateRange, setDateRange] = useState(dateRangeOptions[0].value);
|
|
||||||
|
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
const { symbols } = widget;
|
const { symbols } = widget;
|
||||||
const currencyCode = widget.currency ?? "USD";
|
const currencyCode = widget.currency ?? "USD";
|
||||||
|
const interval = widget.defaultinterval ?? dateRangeOptions[0].value;
|
||||||
|
|
||||||
|
const [dateRange, setDateRange] = useState(interval);
|
||||||
|
|
||||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "v1/cryptocurrency/quotes/latest", {
|
const { data: statsData, error: statsError } = useWidgetAPI(widget, "v1/cryptocurrency/quotes/latest", {
|
||||||
symbol: `${symbols.join(",")}`,
|
symbol: `${symbols.join(",")}`,
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ const components = {
|
|||||||
changedetectionio: dynamic(() => import("./changedetectionio/component")),
|
changedetectionio: dynamic(() => import("./changedetectionio/component")),
|
||||||
coinmarketcap: dynamic(() => import("./coinmarketcap/component")),
|
coinmarketcap: dynamic(() => import("./coinmarketcap/component")),
|
||||||
deluge: dynamic(() => import("./deluge/component")),
|
deluge: dynamic(() => import("./deluge/component")),
|
||||||
diskstation: dynamic(() => import("./diskstation/component")),
|
downloadstation: dynamic(() => import("./downloadstation/component")),
|
||||||
docker: dynamic(() => import("./docker/component")),
|
docker: dynamic(() => import("./docker/component")),
|
||||||
emby: dynamic(() => import("./emby/component")),
|
emby: dynamic(() => import("./emby/component")),
|
||||||
|
flood: dynamic(() => import("./flood/component")),
|
||||||
gluetun: dynamic(() => import("./gluetun/component")),
|
gluetun: dynamic(() => import("./gluetun/component")),
|
||||||
gotify: dynamic(() => import("./gotify/component")),
|
gotify: dynamic(() => import("./gotify/component")),
|
||||||
hdhomerun: dynamic(() => import("./hdhomerun/component")),
|
hdhomerun: dynamic(() => import("./hdhomerun/component")),
|
||||||
@@ -20,10 +21,15 @@ const components = {
|
|||||||
jellyseerr: dynamic(() => import("./jellyseerr/component")),
|
jellyseerr: dynamic(() => import("./jellyseerr/component")),
|
||||||
lidarr: dynamic(() => import("./lidarr/component")),
|
lidarr: dynamic(() => import("./lidarr/component")),
|
||||||
mastodon: dynamic(() => import("./mastodon/component")),
|
mastodon: dynamic(() => import("./mastodon/component")),
|
||||||
|
miniflux: dynamic(() => import("./miniflux/component")),
|
||||||
|
mikrotik: dynamic(() => import("./mikrotik/component")),
|
||||||
navidrome: dynamic(() => import("./navidrome/component")),
|
navidrome: dynamic(() => import("./navidrome/component")),
|
||||||
|
nextdns: dynamic(() => import("./nextdns/component")),
|
||||||
npm: dynamic(() => import("./npm/component")),
|
npm: dynamic(() => import("./npm/component")),
|
||||||
nzbget: dynamic(() => import("./nzbget/component")),
|
nzbget: dynamic(() => import("./nzbget/component")),
|
||||||
|
omada: dynamic(() => import("./omada/component")),
|
||||||
ombi: dynamic(() => import("./ombi/component")),
|
ombi: dynamic(() => import("./ombi/component")),
|
||||||
|
opnsense: dynamic(() => import("./opnsense/component")),
|
||||||
overseerr: dynamic(() => import("./overseerr/component")),
|
overseerr: dynamic(() => import("./overseerr/component")),
|
||||||
paperlessngx: dynamic(() => import("./paperlessngx/component")),
|
paperlessngx: dynamic(() => import("./paperlessngx/component")),
|
||||||
pihole: dynamic(() => import("./pihole/component")),
|
pihole: dynamic(() => import("./pihole/component")),
|
||||||
@@ -42,12 +48,14 @@ const components = {
|
|||||||
speedtest: dynamic(() => import("./speedtest/component")),
|
speedtest: dynamic(() => import("./speedtest/component")),
|
||||||
strelaysrv: dynamic(() => import("./strelaysrv/component")),
|
strelaysrv: dynamic(() => import("./strelaysrv/component")),
|
||||||
tautulli: dynamic(() => import("./tautulli/component")),
|
tautulli: dynamic(() => import("./tautulli/component")),
|
||||||
|
tdarr: dynamic(() => import("./tdarr/component")),
|
||||||
traefik: dynamic(() => import("./traefik/component")),
|
traefik: dynamic(() => import("./traefik/component")),
|
||||||
transmission: dynamic(() => import("./transmission/component")),
|
transmission: dynamic(() => import("./transmission/component")),
|
||||||
tubearchivist: dynamic(() => import("./tubearchivist/component")),
|
tubearchivist: dynamic(() => import("./tubearchivist/component")),
|
||||||
truenas: dynamic(() => import("./truenas/component")),
|
truenas: dynamic(() => import("./truenas/component")),
|
||||||
unifi: dynamic(() => import("./unifi/component")),
|
unifi: dynamic(() => import("./unifi/component")),
|
||||||
watchtower: dynamic(() => import("./watchtower/component")),
|
watchtower: dynamic(() => import("./watchtower/component")),
|
||||||
|
xteve: dynamic(() => import("./xteve/component")),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default components;
|
export default components;
|
||||||
|
|||||||
@@ -46,7 +46,9 @@ export default function Component({ service }) {
|
|||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="docker.cpu" value={t("common.percent", { value: calculateCPUPercent(statsData.stats) })} />
|
<Block label="docker.cpu" value={t("common.percent", { value: calculateCPUPercent(statsData.stats) })} />
|
||||||
<Block label="docker.mem" value={t("common.bytes", { value: statsData.stats.memory_stats.usage })} />
|
{statsData.stats.memory_stats.usage &&
|
||||||
|
<Block label="docker.mem" value={t("common.bytes", { value: statsData.stats.memory_stats.usage })} />
|
||||||
|
}
|
||||||
{network && (
|
{network && (
|
||||||
<>
|
<>
|
||||||
<Block label="docker.rx" value={t("common.bytes", { value: network.rx_bytes })} />
|
<Block label="docker.rx" value={t("common.bytes", { value: network.rx_bytes })} />
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ export default function Component({ service }) {
|
|||||||
if (!tasks) {
|
if (!tasks) {
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="diskstation.leech" />
|
<Block label="downloadstation.leech" />
|
||||||
<Block label="diskstation.download" />
|
<Block label="downloadstation.download" />
|
||||||
<Block label="diskstation.seed" />
|
<Block label="downloadstation.seed" />
|
||||||
<Block label="diskstation.upload" />
|
<Block label="downloadstation.upload" />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -32,10 +32,10 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="diskstation.leech" value={t("common.number", { value: leech })} />
|
<Block label="downloadstation.leech" value={t("common.number", { value: leech })} />
|
||||||
<Block label="diskstation.download" value={t("common.bitrate", { value: rateDl })} />
|
<Block label="downloadstation.download" value={t("common.bitrate", { value: rateDl })} />
|
||||||
<Block label="diskstation.seed" value={t("common.number", { value: completed })} />
|
<Block label="downloadstation.seed" value={t("common.number", { value: completed })} />
|
||||||
<Block label="diskstation.upload" value={t("common.bitrate", { value: rateUl })} />
|
<Block label="downloadstation.upload" value={t("common.bitrate", { value: rateUl })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import createLogger from "utils/logger";
|
|||||||
import widgets from "widgets/widgets";
|
import widgets from "widgets/widgets";
|
||||||
import getServiceWidget from "utils/config/service-helpers";
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
|
|
||||||
const logger = createLogger("diskstationProxyHandler");
|
const logger = createLogger("downloadstationProxyHandler");
|
||||||
const authApi = "{url}/webapi/auth.cgi?api=SYNO.API.Auth&version=2&method=login&account={username}&passwd={password}&session=DownloadStation&format=cookie"
|
const authApi = "{url}/webapi/auth.cgi?api=SYNO.API.Auth&version=2&method=login&account={username}&passwd={password}&session=DownloadStation&format=cookie"
|
||||||
|
|
||||||
async function login(widget) {
|
async function login(widget) {
|
||||||
@@ -34,7 +34,7 @@ async function login(widget) {
|
|||||||
return [status, contentType, data];
|
return [status, contentType, data];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function diskstationProxyHandler(req, res) {
|
export default async function downloadstationProxyHandler(req, res) {
|
||||||
const { group, service, endpoint } = req.query;
|
const { group, service, endpoint } = req.query;
|
||||||
|
|
||||||
if (!group || !service) {
|
if (!group || !service) {
|
||||||
@@ -56,7 +56,7 @@ export default async function diskstationProxyHandler(req, res) {
|
|||||||
|
|
||||||
const json = JSON.parse(data.toString());
|
const json = JSON.parse(data.toString());
|
||||||
if (json?.success !== true) {
|
if (json?.success !== true) {
|
||||||
logger.debug("Logging in to DiskStation");
|
logger.debug("Logging in to DownloadStation");
|
||||||
[status, contentType, data] = await login(widget);
|
[status, contentType, data] = await login(widget);
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
return res.status(status).end(data)
|
return res.status(status).end(data)
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import diskstationProxyHandler from "./proxy";
|
import downloadstationProxyHandler from "./proxy";
|
||||||
|
|
||||||
const widget = {
|
const widget = {
|
||||||
api: "{url}/webapi/DownloadStation/task.cgi?api=SYNO.DownloadStation.Task&version=1&method={endpoint}",
|
api: "{url}/webapi/DownloadStation/task.cgi?api=SYNO.DownloadStation.Task&version=1&method={endpoint}",
|
||||||
proxyHandler: diskstationProxyHandler,
|
proxyHandler: downloadstationProxyHandler,
|
||||||
|
|
||||||
mappings: {
|
mappings: {
|
||||||
"list": {
|
"list": {
|
||||||
53
src/widgets/flood/component.jsx
Normal file
53
src/widgets/flood/component.jsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
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: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents");
|
||||||
|
|
||||||
|
if (torrentError || !torrentData?.torrents) {
|
||||||
|
return <Container error={torrentError ?? {message: "No torrent data returned"}} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!torrentData || !torrentData.torrents) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="flood.leech" />
|
||||||
|
<Block label="flood.download" />
|
||||||
|
<Block label="flood.seed" />
|
||||||
|
<Block label="flood.upload" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rateDl = 0;
|
||||||
|
let rateUl = 0;
|
||||||
|
let completed = 0;
|
||||||
|
let leech = 0;
|
||||||
|
|
||||||
|
Object.values(torrentData.torrents).forEach(torrent => {
|
||||||
|
rateDl += torrent.downRate;
|
||||||
|
rateUl += torrent.upRate;
|
||||||
|
if(torrent.status.includes('complete')){
|
||||||
|
completed += 1;
|
||||||
|
}
|
||||||
|
if(torrent.status.includes('downloading')){
|
||||||
|
leech += 1;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="flood.leech" value={t("common.number", { value: leech })} />
|
||||||
|
<Block label="flood.download" value={t("common.bitrate", { value: rateDl })} />
|
||||||
|
<Block label="flood.seed" value={t("common.number", { value: completed })} />
|
||||||
|
<Block label="flood.upload" value={t("common.bitrate", { value: rateUl })} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
66
src/widgets/flood/proxy.js
Normal file
66
src/widgets/flood/proxy.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { formatApiCall } from "utils/proxy/api-helpers";
|
||||||
|
import { httpProxy } from "utils/proxy/http";
|
||||||
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
|
import createLogger from "utils/logger";
|
||||||
|
|
||||||
|
const logger = createLogger("floodProxyHandler");
|
||||||
|
|
||||||
|
async function login(widget) {
|
||||||
|
logger.debug("flood is rejecting the request, logging in.");
|
||||||
|
const loginUrl = new URL(`${widget.url}/api/auth/authenticate`).toString();
|
||||||
|
|
||||||
|
const loginParams = {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (widget.username && widget.password) {
|
||||||
|
loginParams.body = JSON.stringify({
|
||||||
|
"username": widget.username,
|
||||||
|
"password": widget.password
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [status, contentType, data] = await httpProxy(loginUrl, loginParams);
|
||||||
|
return [status, data];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function floodProxyHandler(req, res) {
|
||||||
|
const { group, service, endpoint } = req.query;
|
||||||
|
|
||||||
|
if (!group || !service) {
|
||||||
|
logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const widget = await getServiceWidget(group, service);
|
||||||
|
|
||||||
|
if (!widget) {
|
||||||
|
logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(formatApiCall("{url}/api/{endpoint}", { endpoint, ...widget }));
|
||||||
|
const params = { method: "GET", headers: {} };
|
||||||
|
|
||||||
|
let [status, contentType, data] = await httpProxy(url, params);
|
||||||
|
if (status === 401) {
|
||||||
|
[status, data] = await login(widget);
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.error("HTTP %d logging in to flood. Data: %s", status, data);
|
||||||
|
return res.status(status).end(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(url, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.error("HTTP %d getting data from flood. Data: %s", status, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentType) res.setHeader("Content-Type", contentType);
|
||||||
|
return res.status(status).send(data);
|
||||||
|
}
|
||||||
7
src/widgets/flood/widget.js
Normal file
7
src/widgets/flood/widget.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import floodProxyHandler from "./proxy";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
proxyHandler: floodProxyHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
@@ -10,7 +10,7 @@ const proxyName = "homebridgeProxyHandler";
|
|||||||
const sessionTokenCacheKey = `${proxyName}__sessionToken`;
|
const sessionTokenCacheKey = `${proxyName}__sessionToken`;
|
||||||
const logger = createLogger(proxyName);
|
const logger = createLogger(proxyName);
|
||||||
|
|
||||||
async function login(widget) {
|
async function login(widget, service) {
|
||||||
const endpoint = "auth/login";
|
const endpoint = "auth/login";
|
||||||
const api = widgets?.[widget.type]?.api
|
const api = widgets?.[widget.type]?.api
|
||||||
const loginUrl = new URL(formatApiCall(api, { endpoint, ...widget }));
|
const loginUrl = new URL(formatApiCall(api, { endpoint, ...widget }));
|
||||||
@@ -26,7 +26,7 @@ async function login(widget) {
|
|||||||
try {
|
try {
|
||||||
const { access_token: accessToken, expires_in: expiresIn } = JSON.parse(data.toString());
|
const { access_token: accessToken, expires_in: expiresIn } = JSON.parse(data.toString());
|
||||||
|
|
||||||
cache.put(sessionTokenCacheKey, accessToken, (expiresIn * 1000) - 5 * 60 * 1000); // expiresIn (s) - 5m
|
cache.put(`${sessionTokenCacheKey}.${service}`, accessToken, (expiresIn * 1000) - 5 * 60 * 1000); // expiresIn (s) - 5m
|
||||||
return { accessToken };
|
return { accessToken };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("Unable to login to Homebridge API: %s", e);
|
logger.error("Unable to login to Homebridge API: %s", e);
|
||||||
@@ -35,10 +35,11 @@ async function login(widget) {
|
|||||||
return { accessToken: false };
|
return { accessToken: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function apiCall(widget, endpoint) {
|
async function apiCall(widget, endpoint, service) {
|
||||||
|
const key = `${sessionTokenCacheKey}.${service}`;
|
||||||
const headers = {
|
const headers = {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
"Authorization": `Bearer ${cache.get(sessionTokenCacheKey)}`,
|
"Authorization": `Bearer ${cache.get(key)}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||||
@@ -51,7 +52,7 @@ async function apiCall(widget, endpoint) {
|
|||||||
|
|
||||||
if (status === 401) {
|
if (status === 401) {
|
||||||
logger.debug("Homebridge API rejected the request, attempting to obtain new session token");
|
logger.debug("Homebridge API rejected the request, attempting to obtain new session token");
|
||||||
const { accessToken } = login(widget);
|
const { accessToken } = login(widget, service);
|
||||||
headers.Authorization = `Bearer ${accessToken}`;
|
headers.Authorization = `Bearer ${accessToken}`;
|
||||||
|
|
||||||
// retry the request, now with the new session token
|
// retry the request, now with the new session token
|
||||||
@@ -83,14 +84,14 @@ export default async function homebridgeProxyHandler(req, res) {
|
|||||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cache.get(sessionTokenCacheKey)) {
|
if (!cache.get(`${sessionTokenCacheKey}.${service}`)) {
|
||||||
await login(widget);
|
await login(widget, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: statusData } = await apiCall(widget, "status/homebridge");
|
const { data: statusData } = await apiCall(widget, "status/homebridge", service);
|
||||||
const { data: versionData } = await apiCall(widget, "status/homebridge-version");
|
const { data: versionData } = await apiCall(widget, "status/homebridge-version", service);
|
||||||
const { data: childBridgeData } = await apiCall(widget, "status/homebridge/child-bridges");
|
const { data: childBridgeData } = await apiCall(widget, "status/homebridge/child-bridges", service);
|
||||||
const { data: pluginsData } = await apiCall(widget, "plugins");
|
const { data: pluginsData } = await apiCall(widget, "plugins", service);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
status: statusData?.status,
|
status: statusData?.status,
|
||||||
|
|||||||
43
src/widgets/mikrotik/component.jsx
Normal file
43
src/widgets/mikrotik/component.jsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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: statsData, error: statsError } = useWidgetAPI(widget, "system");
|
||||||
|
const { data: leasesData, error: leasesError } = useWidgetAPI(widget, "leases");
|
||||||
|
|
||||||
|
if (statsError || leasesError) {
|
||||||
|
const finalError = statsError ?? leasesError;
|
||||||
|
return <Container error={ finalError } />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!statsData || !leasesData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="mikrotik.uptime" />
|
||||||
|
<Block label="mikrotik.cpuLoad" />
|
||||||
|
<Block label="mikrotik.memoryUsed" />
|
||||||
|
<Block label="mikrotik.numberOfLeases" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const memoryUsed = 100 - (statsData['free-memory'] / statsData['total-memory'])*100
|
||||||
|
|
||||||
|
const numberOfLeases = leasesData.length
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="mikrotik.uptime" value={ statsData.uptime } />
|
||||||
|
<Block label="mikrotik.cpuLoad" value={t("common.percent", { value: statsData['cpu-load'] })} />
|
||||||
|
<Block label="mikrotik.memoryUsed" value={t("common.percent", { value: memoryUsed })} />
|
||||||
|
<Block label="mikrotik.numberOfLeases" value={t("common.number", { value: numberOfLeases })} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
24
src/widgets/mikrotik/widget.js
Normal file
24
src/widgets/mikrotik/widget.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "{url}/rest/{endpoint}",
|
||||||
|
proxyHandler: genericProxyHandler,
|
||||||
|
|
||||||
|
mappings: {
|
||||||
|
system: {
|
||||||
|
endpoint: "system/resource",
|
||||||
|
validate: [
|
||||||
|
"cpu-load",
|
||||||
|
"free-memory",
|
||||||
|
"total-memory",
|
||||||
|
"uptime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
leases: {
|
||||||
|
endpoint: "ip/dhcp-server/lease",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
33
src/widgets/miniflux/component.jsx
Normal file
33
src/widgets/miniflux/component.jsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
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: minifluxData, error: minifluxError } = useWidgetAPI(widget, "counters");
|
||||||
|
|
||||||
|
if (minifluxError) {
|
||||||
|
return <Container error={minifluxError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!minifluxData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="miniflux.unread" />
|
||||||
|
<Block label="miniflux.read" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="miniflux.unread" value={t("common.number", { value: minifluxData.unread })} />
|
||||||
|
<Block label="miniflux.read" value={t("common.number", { value: minifluxData.read })} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
19
src/widgets/miniflux/widget.js
Normal file
19
src/widgets/miniflux/widget.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { asJson } from "utils/proxy/api-helpers";
|
||||||
|
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "{url}/v1/{endpoint}",
|
||||||
|
proxyHandler: credentialedProxyHandler,
|
||||||
|
|
||||||
|
mappings: {
|
||||||
|
counters: {
|
||||||
|
endpoint: "feeds/counters",
|
||||||
|
map: (data) => ({
|
||||||
|
read: Object.values(asJson(data).reads).reduce((acc, i) => acc + i, 0),
|
||||||
|
unread: Object.values(asJson(data).unreads).reduce((acc, i) => acc + i, 0)
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
39
src/widgets/nextdns/component.jsx
Normal file
39
src/widgets/nextdns/component.jsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
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: nextdnsData, error: nextdnsError } = useWidgetAPI(widget, "analytics/status");
|
||||||
|
|
||||||
|
if (nextdnsError) {
|
||||||
|
return <Container error={nextdnsError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nextdnsData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block key="status" label="widget.status" value={t("nextdns.wait")} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nextdnsData?.data?.length) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block key="status" label="widget.status" value={t("nextdns.no_devices")} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
{nextdnsData.data.map(d => <Block key={d.status} label={d.status} value={t("common.number", { value: d.queries })} />)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
17
src/widgets/nextdns/widget.js
Normal file
17
src/widgets/nextdns/widget.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "https://api.nextdns.io/profiles/{profile}/{endpoint}",
|
||||||
|
proxyHandler: credentialedProxyHandler,
|
||||||
|
|
||||||
|
mappings: {
|
||||||
|
"analytics/status": {
|
||||||
|
endpoint: "analytics/status",
|
||||||
|
validate: [
|
||||||
|
"data",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
@@ -10,7 +10,7 @@ const proxyName = "npmProxyHandler";
|
|||||||
const tokenCacheKey = `${proxyName}__token`;
|
const tokenCacheKey = `${proxyName}__token`;
|
||||||
const logger = createLogger(proxyName);
|
const logger = createLogger(proxyName);
|
||||||
|
|
||||||
async function login(loginUrl, username, password) {
|
async function login(loginUrl, username, password, service) {
|
||||||
const authResponse = await httpProxy(loginUrl, {
|
const authResponse = await httpProxy(loginUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({ identity: username, secret: password }),
|
body: JSON.stringify({ identity: username, secret: password }),
|
||||||
@@ -27,7 +27,7 @@ async function login(loginUrl, username, password) {
|
|||||||
|
|
||||||
if (status === 200) {
|
if (status === 200) {
|
||||||
const expiration = new Date(data.expires) - Date.now();
|
const expiration = new Date(data.expires) - Date.now();
|
||||||
cache.put(tokenCacheKey, data.token, expiration - (5 * 60 * 1000)); // expiration -5 minutes
|
cache.put(`${tokenCacheKey}.${service}`, data.token, expiration - (5 * 60 * 1000)); // expiration -5 minutes
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`Error ${status} logging into npm`, authResponse[2]);
|
logger.error(`Error ${status} logging into npm`, authResponse[2]);
|
||||||
@@ -53,9 +53,9 @@ export default async function npmProxyHandler(req, res) {
|
|||||||
let contentType;
|
let contentType;
|
||||||
let data;
|
let data;
|
||||||
|
|
||||||
let token = cache.get(tokenCacheKey);
|
let token = cache.get(`${tokenCacheKey}.${service}`);
|
||||||
if (!token) {
|
if (!token) {
|
||||||
[status, token] = await login(loginUrl, widget.username, widget.password);
|
[status, token] = await login(loginUrl, widget.username, widget.password, service);
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
logger.debug(`HTTTP ${status} logging into npm api: ${token}`);
|
logger.debug(`HTTTP ${status} logging into npm api: ${token}`);
|
||||||
return res.status(status).send(token);
|
return res.status(status).send(token);
|
||||||
@@ -72,8 +72,8 @@ export default async function npmProxyHandler(req, res) {
|
|||||||
|
|
||||||
if (status === 403) {
|
if (status === 403) {
|
||||||
logger.debug(`HTTTP ${status} retrieving data from npm api, logging in and trying again.`);
|
logger.debug(`HTTTP ${status} retrieving data from npm api, logging in and trying again.`);
|
||||||
cache.del(tokenCacheKey);
|
cache.del(`${tokenCacheKey}.${service}`);
|
||||||
[status, token] = await login(loginUrl, widget.username, widget.password);
|
[status, token] = await login(loginUrl, widget.username, widget.password, service);
|
||||||
|
|
||||||
if (status !== 200) {
|
if (status !== 200) {
|
||||||
logger.debug(`HTTTP ${status} logging into npm api: ${data}`);
|
logger.debug(`HTTTP ${status} logging into npm api: ${data}`);
|
||||||
|
|||||||
39
src/widgets/omada/component.jsx
Normal file
39
src/widgets/omada/component.jsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
|
import useWidgetAPI from "../../utils/proxy/use-widget-api";
|
||||||
|
import Container from "../../components/services/widget/container";
|
||||||
|
import Block from "../../components/services/widget/block";
|
||||||
|
|
||||||
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { widget } = service;
|
||||||
|
|
||||||
|
const { data: omadaData, error: omadaAPIError } = useWidgetAPI(widget, {
|
||||||
|
refreshInterval: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (omadaAPIError) {
|
||||||
|
return <Container error={omadaAPIError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!omadaData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="omada.connectedAp" />
|
||||||
|
<Block label="omada.activeUser" />
|
||||||
|
<Block label="omada.alerts" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="omada.connectedAp" value={t( "common.number", { value: omadaData.connectedAp})} />
|
||||||
|
<Block label="omada.activeUser" value={t( "common.number", { value: omadaData.activeUser })} />
|
||||||
|
<Block label="omada.alerts" value={t( "common.number", { value: omadaData.alerts })} />
|
||||||
|
{ omadaData.connectedGateways > 0 && <Block label="omada.connectedGateway" value={t("common.number", { value: omadaData.connectedGateways})} /> }
|
||||||
|
{ omadaData.connectedSwitches > 0 && <Block label="omada.connectedSwitches" value={t("common.number", { value: omadaData.connectedSwitches})} /> }
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
252
src/widgets/omada/proxy.js
Normal file
252
src/widgets/omada/proxy.js
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
|
||||||
|
import { httpProxy } from "utils/proxy/http";
|
||||||
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
|
import createLogger from "utils/logger";
|
||||||
|
|
||||||
|
const proxyName = "omadaProxyHandler";
|
||||||
|
|
||||||
|
const logger = createLogger(proxyName);
|
||||||
|
|
||||||
|
async function login(loginUrl, username, password, controllerVersionMajor) {
|
||||||
|
const params = {
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controllerVersionMajor === 3) {
|
||||||
|
params.method = "login";
|
||||||
|
params.params = {
|
||||||
|
name: username,
|
||||||
|
password
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [status, contentType, data] = await httpProxy(loginUrl, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return [status, JSON.parse(data.toString())];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default async function omadaProxyHandler(req, res) {
|
||||||
|
const { group, service } = req.query;
|
||||||
|
|
||||||
|
if (group && service) {
|
||||||
|
const widget = await getServiceWidget(group, service);
|
||||||
|
|
||||||
|
if (widget) {
|
||||||
|
|
||||||
|
const {url} = widget;
|
||||||
|
|
||||||
|
const controllerInfoURL = `${widget.url}/api/info`;
|
||||||
|
|
||||||
|
let [status, contentType, data] = await httpProxy(controllerInfoURL, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.error("Unable to retrieve Omada controller info");
|
||||||
|
return res.status(status).json({error: {message: `HTTP Error ${status}`, url: controllerInfoURL, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
let cId;
|
||||||
|
let controllerVersion;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cId = JSON.parse(data).result.omadacId;
|
||||||
|
controllerVersion = JSON.parse(data).result.controllerVer;
|
||||||
|
} catch (e) {
|
||||||
|
controllerVersion = "3.2.x"
|
||||||
|
}
|
||||||
|
|
||||||
|
const controllerVersionMajor = parseInt(controllerVersion.split('.')[0], 10)
|
||||||
|
|
||||||
|
if (![3,4,5].includes(controllerVersionMajor)) {
|
||||||
|
return res.status(500).json({error: {message: "Error determining controller version", data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
let loginUrl;
|
||||||
|
|
||||||
|
switch (controllerVersionMajor) {
|
||||||
|
case 3:
|
||||||
|
loginUrl = `${widget.url}/api/user/login?ajax`;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
loginUrl = `${widget.url}/api/v2/login`;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
loginUrl = `${widget.url}/${cId}/api/v2/login`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [loginStatus, loginResponseData] = await login(loginUrl, widget.username, widget.password, controllerVersionMajor);
|
||||||
|
|
||||||
|
if (loginStatus !== 200 || loginResponseData.errorCode > 0) {
|
||||||
|
return res.status(status).json({error: {message: "Error logging in to Oamda controller", url: loginUrl, data: loginResponseData}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { token } = loginResponseData.result;
|
||||||
|
|
||||||
|
let sitesUrl;
|
||||||
|
let body = {};
|
||||||
|
let params = { token };
|
||||||
|
let headers = { "Csrf-Token": token };
|
||||||
|
let method = "GET";
|
||||||
|
|
||||||
|
switch (controllerVersionMajor) {
|
||||||
|
case 3:
|
||||||
|
sitesUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`;
|
||||||
|
body = {
|
||||||
|
"method": "getUserSites",
|
||||||
|
"params": {
|
||||||
|
"userName": widget.username
|
||||||
|
}
|
||||||
|
};
|
||||||
|
method = "POST";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
sitesUrl = `${widget.url}/api/v2/sites?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
sitesUrl = `${widget.url}/${cId}/api/v2/sites?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(sitesUrl, {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const sitesResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
if (sitesResponseData.errorCode > 0) {
|
||||||
|
logger.debug(`HTTTP ${status} getting sites list: ${sitesResponseData.msg}`);
|
||||||
|
return res.status(status).json({error: {message: "Error getting sites list", url, data: sitesResponseData}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const site = (controllerVersionMajor === 3) ?
|
||||||
|
sitesResponseData.result.siteList.find(s => s.name === widget.site):
|
||||||
|
sitesResponseData.result.data.find(s => s.name === widget.site);
|
||||||
|
|
||||||
|
if (!site) {
|
||||||
|
return res.status(status).json({error: {message: `Site ${widget.site} is not found`, url, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
let siteResponseData;
|
||||||
|
|
||||||
|
let connectedAp;
|
||||||
|
let activeUser;
|
||||||
|
let connectedSwitches;
|
||||||
|
let connectedGateways;
|
||||||
|
let alerts;
|
||||||
|
|
||||||
|
if (controllerVersionMajor === 3) {
|
||||||
|
// Omada v3 controller requires switching site
|
||||||
|
const switchUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`;
|
||||||
|
method = "POST";
|
||||||
|
body = {
|
||||||
|
method: "switchSite",
|
||||||
|
params: {
|
||||||
|
siteName: site.siteName,
|
||||||
|
userName: widget.username
|
||||||
|
}
|
||||||
|
};
|
||||||
|
headers = { "Content-Type": "application/json" };
|
||||||
|
params = { token };
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(switchUrl, {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const switchResponseData = JSON.parse(data);
|
||||||
|
if (status !== 200 || switchResponseData.errorCode > 0) {
|
||||||
|
logger.error(`HTTP ${status} getting sites list: ${data}`);
|
||||||
|
return res.status(status).json({error: {message: "Error switching site", url: switchUrl, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const statsUrl = `${widget.url}/web/v1/controller?getGlobalStat=&token=${token}`;
|
||||||
|
[status, contentType, data] = await httpProxy(statsUrl, {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
body: JSON.stringify({
|
||||||
|
"method": "getGlobalStat",
|
||||||
|
}),
|
||||||
|
headers
|
||||||
|
});
|
||||||
|
|
||||||
|
siteResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
if (status !== 200 || siteResponseData.errorCode > 0) {
|
||||||
|
return res.status(status).json({error: {message: "Error getting stats", url: statsUrl, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedAp = siteResponseData.result.connectedAp;
|
||||||
|
activeUser = siteResponseData.result.activeUser;
|
||||||
|
alerts = siteResponseData.result.alerts;
|
||||||
|
} else if (controllerVersionMajor === 4 || controllerVersionMajor === 5) {
|
||||||
|
const siteName = (controllerVersionMajor === 5) ? site.id : site.key;
|
||||||
|
const siteStatsUrl = (controllerVersionMajor === 4) ?
|
||||||
|
`${url}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}¤tPage=1¤tPageSize=1000` :
|
||||||
|
`${url}/${cId}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(siteStatsUrl, {
|
||||||
|
headers: {
|
||||||
|
"Csrf-Token": token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
siteResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
if (status !== 200 || siteResponseData.errorCode > 0) {
|
||||||
|
logger.debug(`HTTP ${status} getting stats for site ${widget.site} with message ${siteResponseData.msg}`);
|
||||||
|
return res.status(500).send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const alertUrl = (controllerVersionMajor === 4) ?
|
||||||
|
`${url}/api/v2/sites/${siteName}/alerts/num?token=${token}¤tPage=1¤tPageSize=1000` :
|
||||||
|
`${url}/${cId}/api/v2/sites/${siteName}/alerts/num?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
[status, contentType, data] = await httpProxy(alertUrl, {
|
||||||
|
headers: {
|
||||||
|
"Csrf-Token": token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const alertResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
activeUser = siteResponseData.result.totalClientNum;
|
||||||
|
connectedAp = siteResponseData.result.connectedApNum;
|
||||||
|
connectedGateways = siteResponseData.result.connectedGatewayNum;
|
||||||
|
connectedSwitches = siteResponseData.result.connectedSwitchNum;
|
||||||
|
alerts = alertResponseData.result.alertNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.send(JSON.stringify({
|
||||||
|
connectedAp,
|
||||||
|
activeUser,
|
||||||
|
alerts,
|
||||||
|
connectedGateways,
|
||||||
|
connectedSwitches,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
||||||
7
src/widgets/omada/widget.js
Normal file
7
src/widgets/omada/widget.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import omadaProxyHandler from "./proxy";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
proxyHandler: omadaProxyHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
48
src/widgets/opnsense/component.jsx
Normal file
48
src/widgets/opnsense/component.jsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
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: activityData, error: activityError } = useWidgetAPI(widget, "activity");
|
||||||
|
const { data: interfaceData, error: interfaceError } = useWidgetAPI(widget, "interface");
|
||||||
|
|
||||||
|
if (activityError || interfaceError) {
|
||||||
|
const finalError = activityError ?? interfaceError;
|
||||||
|
return <Container error={ finalError } />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activityData || !interfaceData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="opnsense.cpu" />
|
||||||
|
<Block label="opnsense.memory" />
|
||||||
|
<Block label="opnsense.wanUpload" />
|
||||||
|
<Block label="opnsense.wanDownload" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const cpuIdle = activityData.headers[2].match(/ ([0-9.]+)% idle/)[1];
|
||||||
|
const cpu = 100 - parseFloat(cpuIdle);
|
||||||
|
const memory = activityData.headers[3].match(/Mem: (.+) Active,/)[1];
|
||||||
|
|
||||||
|
const wanUpload = interfaceData.interfaces.wan['bytes transmitted'];
|
||||||
|
const wanDownload = interfaceData.interfaces.wan['bytes received'];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="opnsense.cpu" value={t("common.percent", { value: cpu.toFixed(2) })} />
|
||||||
|
<Block label="opnsense.memory" value={memory} />
|
||||||
|
<Block label="opnsense.wanUpload" value={t("common.bytes", { value: wanUpload })} />
|
||||||
|
<Block label="opnsense.wanDownload" value={t("common.bytes", { value: wanDownload })} />
|
||||||
|
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
24
src/widgets/opnsense/widget.js
Normal file
24
src/widgets/opnsense/widget.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "{url}/api/{endpoint}",
|
||||||
|
proxyHandler: genericProxyHandler,
|
||||||
|
|
||||||
|
mappings: {
|
||||||
|
activity: {
|
||||||
|
endpoint: "diagnostics/activity/getActivity",
|
||||||
|
validate: [
|
||||||
|
"headers"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
interface: {
|
||||||
|
endpoint: "diagnostics/traffic/interface",
|
||||||
|
validate: [
|
||||||
|
"interfaces"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "request/count");
|
const { data: statsData, error: statsError } = useWidgetAPI(widget, "request/count");
|
||||||
@@ -24,10 +27,10 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="overseerr.pending" value={statsData.pending} />
|
<Block label="overseerr.pending" value={t("common.number", { value: statsData.pending })} />
|
||||||
<Block label="overseerr.processing" value={statsData.processing} />
|
<Block label="overseerr.processing" value={t("common.number", { value: statsData.processing })} />
|
||||||
<Block label="overseerr.approved" value={statsData.approved} />
|
<Block label="overseerr.approved" value={t("common.number", { value: statsData.approved })} />
|
||||||
<Block label="overseerr.available" value={statsData.available} />
|
<Block label="overseerr.available" value={t("common.number", { value: statsData.available })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
const { data: piholeData, error: piholeError } = useWidgetAPI(widget, "api.php");
|
const { data: piholeData, error: piholeError } = useWidgetAPI(widget, "summaryRaw");
|
||||||
|
|
||||||
if (piholeError) {
|
if (piholeError) {
|
||||||
return <Container error={piholeError} />;
|
return <Container error={piholeError} />;
|
||||||
@@ -27,9 +27,9 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="pihole.queries" value={t("common.number", { value: piholeData.dns_queries_today })} />
|
<Block label="pihole.queries" value={t("common.number", { value: parseInt(piholeData.dns_queries_today, 10) })} />
|
||||||
<Block label="pihole.blocked" value={t("common.number", { value: piholeData.ads_blocked_today })} />
|
<Block label="pihole.blocked" value={t("common.number", { value: parseInt(piholeData.ads_blocked_today, 10) })} />
|
||||||
<Block label="pihole.gravity" value={t("common.number", { value: piholeData.domains_being_blocked })} />
|
<Block label="pihole.gravity" value={t("common.number", { value: parseInt(piholeData.domains_being_blocked, 10) })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||||
|
|
||||||
const widget = {
|
const widget = {
|
||||||
api: "{url}/admin/{endpoint}",
|
api: "{url}/admin/api.php?{endpoint}&auth={key}",
|
||||||
proxyHandler: genericProxyHandler,
|
proxyHandler: genericProxyHandler,
|
||||||
|
|
||||||
mappings: {
|
mappings: {
|
||||||
"api.php": {
|
"summaryRaw": {
|
||||||
endpoint: "api.php",
|
endpoint: "summaryRaw",
|
||||||
validate: [
|
validate: [
|
||||||
"dns_queries_today",
|
"dns_queries_today",
|
||||||
"ads_blocked_today",
|
"ads_blocked_today",
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ async function fetchFromPlexAPI(endpoint, widget) {
|
|||||||
|
|
||||||
export default async function plexProxyHandler(req, res) {
|
export default async function plexProxyHandler(req, res) {
|
||||||
const widget = await getWidget(req);
|
const widget = await getWidget(req);
|
||||||
|
|
||||||
|
const { service } = req.query;
|
||||||
|
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
}
|
}
|
||||||
@@ -74,23 +77,24 @@ export default async function plexProxyHandler(req, res) {
|
|||||||
streams = apiData.MediaContainer._attributes.size;
|
streams = apiData.MediaContainer._attributes.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
let libraries = cache.get(librariesCacheKey);
|
let libraries = cache.get(`${librariesCacheKey}.${service}`);
|
||||||
if (libraries === null) {
|
if (libraries === null) {
|
||||||
logger.debug("Getting libraries from Plex API");
|
logger.debug("Getting libraries from Plex API");
|
||||||
[status, apiData] = await fetchFromPlexAPI("/library/sections", widget);
|
[status, apiData] = await fetchFromPlexAPI("/library/sections", widget);
|
||||||
if (apiData && apiData.MediaContainer) {
|
if (apiData && apiData.MediaContainer) {
|
||||||
libraries = apiData.MediaContainer.Directory;
|
libraries = [].concat(apiData.MediaContainer.Directory);
|
||||||
cache.put(librariesCacheKey, libraries, 1000 * 60 * 60 * 6);
|
cache.put(`${librariesCacheKey}.${service}`, libraries, 1000 * 60 * 60 * 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let movies = cache.get(moviesCacheKey);
|
let movies = cache.get(`${moviesCacheKey}.${service}`);
|
||||||
let tv = cache.get(tvCacheKey);
|
let tv = cache.get(`${tvCacheKey}.${service}`);
|
||||||
if (movies === null || tv === null) {
|
if (movies === null || tv === null) {
|
||||||
movies = 0;
|
movies = 0;
|
||||||
tv = 0;
|
tv = 0;
|
||||||
logger.debug("Getting movie + tv counts from Plex API");
|
logger.debug("Getting movie + tv counts from Plex API");
|
||||||
libraries.filter(l => ["movie", "show"].includes(l._attributes.type)).forEach(async (library) => {
|
const movieTVLibraries = libraries.filter(l => ["movie", "show"].includes(l._attributes.type));
|
||||||
|
await Promise.all(movieTVLibraries.map(async (library) => {
|
||||||
[status, apiData] = await fetchFromPlexAPI(`/library/sections/${library._attributes.key}/all`, widget);
|
[status, apiData] = await fetchFromPlexAPI(`/library/sections/${library._attributes.key}/all`, widget);
|
||||||
if (apiData && apiData.MediaContainer) {
|
if (apiData && apiData.MediaContainer) {
|
||||||
const size = parseInt(apiData.MediaContainer._attributes.size, 10);
|
const size = parseInt(apiData.MediaContainer._attributes.size, 10);
|
||||||
@@ -100,9 +104,9 @@ export default async function plexProxyHandler(req, res) {
|
|||||||
tv += size;
|
tv += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache.put(tvCacheKey, tv, 1000 * 60 * 10);
|
}));
|
||||||
cache.put(moviesCacheKey, movies, 1000 * 60 * 10);
|
cache.put(`${tvCacheKey}.${service}`, tv, 1000 * 60 * 10);
|
||||||
});
|
cache.put(`${moviesCacheKey}.${service}`, movies, 1000 * 60 * 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
const { data: indexersData, error: indexersError } = useWidgetAPI(widget, "indexer");
|
const { data: indexersData, error: indexersError } = useWidgetAPI(widget, "indexer");
|
||||||
@@ -40,11 +43,11 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="prowlarr.enableIndexers" value={indexers.length} />
|
<Block label="prowlarr.enableIndexers" value={t("common.number", { value: indexers.length })} />
|
||||||
<Block label="prowlarr.numberOfGrabs" value={numberOfGrabs} />
|
<Block label="prowlarr.numberOfGrabs" value={t("common.number", { value: numberOfGrabs })} />
|
||||||
<Block label="prowlarr.numberOfQueries" value={numberOfQueries} />
|
<Block label="prowlarr.numberOfQueries" value={t("common.number", { value: numberOfQueries })} />
|
||||||
<Block label="prowlarr.numberOfFailGrabs" value={numberOfFailedGrabs} />
|
<Block label="prowlarr.numberOfFailGrabs" value={t("common.number", { value: numberOfFailedGrabs })} />
|
||||||
<Block label="prowlarr.numberOfFailQueries" value={numberOfFailedQueries} />
|
<Block label="prowlarr.numberOfFailQueries" value={t("common.number", { value: numberOfFailedQueries })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const logger = createLogger(proxyName);
|
|||||||
const sessionCacheKey = `${proxyName}__sessionId`;
|
const sessionCacheKey = `${proxyName}__sessionId`;
|
||||||
const isNgCacheKey = `${proxyName}__isNg`;
|
const isNgCacheKey = `${proxyName}__isNg`;
|
||||||
|
|
||||||
async function fetchFromPyloadAPI(url, sessionId, params) {
|
async function fetchFromPyloadAPI(url, sessionId, params, service) {
|
||||||
const options = {
|
const options = {
|
||||||
body: params
|
body: params
|
||||||
? Object.keys(params)
|
? Object.keys(params)
|
||||||
@@ -25,10 +25,10 @@ async function fetchFromPyloadAPI(url, sessionId, params) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// see https://github.com/benphelps/homepage/issues/517
|
// see https://github.com/benphelps/homepage/issues/517
|
||||||
const isNg = cache.get(isNgCacheKey);
|
const isNg = cache.get(`${isNgCacheKey}.${service}`);
|
||||||
if (isNg && !params) {
|
if (isNg && !params) {
|
||||||
delete options.body;
|
delete options.body;
|
||||||
options.headers.Cookie = cache.get(sessionCacheKey);
|
options.headers.Cookie = cache.get(`${sessionCacheKey}.${service}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
@@ -43,19 +43,19 @@ async function fetchFromPyloadAPI(url, sessionId, params) {
|
|||||||
return [status, returnData, responseHeaders];
|
return [status, returnData, responseHeaders];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function login(loginUrl, username, password = '') {
|
async function login(loginUrl, service, username, password = '') {
|
||||||
const [status, sessionId, responseHeaders] = await fetchFromPyloadAPI(loginUrl, null, { username, password });
|
const [status, sessionId, responseHeaders] = await fetchFromPyloadAPI(loginUrl, null, { username, password }, service);
|
||||||
|
|
||||||
// this API actually returns status 200 even on login failure
|
// this API actually returns status 200 even on login failure
|
||||||
if (status !== 200 || sessionId === false) {
|
if (status !== 200 || sessionId === false) {
|
||||||
logger.error(`HTTP ${status} logging into Pyload API, returned: ${JSON.stringify(sessionId)}`);
|
logger.error(`HTTP ${status} logging into Pyload API, returned: ${JSON.stringify(sessionId)}`);
|
||||||
} else if (responseHeaders['set-cookie']?.join().includes('pyload_session')) {
|
} else if (responseHeaders['set-cookie']?.join().includes('pyload_session')) {
|
||||||
// Support pyload-ng, see https://github.com/benphelps/homepage/issues/517
|
// Support pyload-ng, see https://github.com/benphelps/homepage/issues/517
|
||||||
cache.put(isNgCacheKey, true);
|
cache.put(`${isNgCacheKey}.${service}`, true);
|
||||||
const sessionCookie = responseHeaders['set-cookie'][0];
|
const sessionCookie = responseHeaders['set-cookie'][0];
|
||||||
cache.put(sessionCacheKey, sessionCookie, 60 * 60 * 23 * 1000); // cache for 23h
|
cache.put(`${sessionCacheKey}.${service}`, sessionCookie, 60 * 60 * 23 * 1000); // cache for 23h
|
||||||
} else {
|
} else {
|
||||||
cache.put(sessionCacheKey, sessionId);
|
cache.put(`${sessionCacheKey}.${service}`, sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionId;
|
return sessionId;
|
||||||
@@ -72,14 +72,14 @@ export default async function pyloadProxyHandler(req, res) {
|
|||||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||||
const loginUrl = `${widget.url}/api/login`;
|
const loginUrl = `${widget.url}/api/login`;
|
||||||
|
|
||||||
let sessionId = cache.get(sessionCacheKey) ?? await login(loginUrl, widget.username, widget.password);
|
let sessionId = cache.get(`${sessionCacheKey}.${service}`) ?? await login(loginUrl, service, widget.username, widget.password);
|
||||||
let [status, data] = await fetchFromPyloadAPI(url, sessionId);
|
let [status, data] = await fetchFromPyloadAPI(url, sessionId, null, service);
|
||||||
|
|
||||||
if (status === 403 || status === 401) {
|
if (status === 403 || status === 401) {
|
||||||
logger.info('Failed to retrieve data from Pyload API, trying to login again...');
|
logger.info('Failed to retrieve data from Pyload API, trying to login again...');
|
||||||
cache.del(sessionCacheKey);
|
cache.del(`${sessionCacheKey}.${service}`);
|
||||||
sessionId = await login(loginUrl, widget.username, widget.password);
|
sessionId = await login(loginUrl, service, widget.username, widget.password);
|
||||||
[status, data] = await fetchFromPyloadAPI(url, sessionId);
|
[status, data] = await fetchFromPyloadAPI(url, sessionId, null, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.error || status !== 200) {
|
if (data?.error || status !== 200) {
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ export default function Component({ service }) {
|
|||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="qbittorrent.leech" value={t("common.number", { value: leech })} />
|
<Block label="qbittorrent.leech" value={t("common.number", { value: leech })} />
|
||||||
<Block label="qbittorrent.download" value={t("common.bitrate", { value: rateDl })} />
|
<Block label="qbittorrent.download" value={t("common.bibyterate", { value: rateDl, decimals: 1 })} />
|
||||||
<Block label="qbittorrent.seed" value={t("common.number", { value: completed })} />
|
<Block label="qbittorrent.seed" value={t("common.number", { value: completed })} />
|
||||||
<Block label="qbittorrent.upload" value={t("common.bitrate", { value: rateUl })} />
|
<Block label="qbittorrent.upload" value={t("common.bibyterate", { value: rateUl, decimals: 1 })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
const { data: moviesData, error: moviesError } = useWidgetAPI(widget, "movie");
|
const { data: moviesData, error: moviesError } = useWidgetAPI(widget, "movie");
|
||||||
@@ -26,10 +29,10 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="radarr.wanted" value={moviesData.wanted} />
|
<Block label="radarr.wanted" value={t("common.number", { value: moviesData.wanted })} />
|
||||||
<Block label="radarr.missing" value={moviesData.missing} />
|
<Block label="radarr.missing" value={t("common.number", { value: moviesData.missing })} />
|
||||||
<Block label="radarr.queued" value={queuedData.totalCount} />
|
<Block label="radarr.queued" value={t("common.number", { value: queuedData.totalCount })} />
|
||||||
<Block label="radarr.movies" value={moviesData.have} />
|
<Block label="radarr.movies" value={t("common.number", { value: moviesData.have })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,37 @@ import Container from "components/services/widget/container";
|
|||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
|
||||||
|
// @see https://github.com/AnalogJ/scrutiny/blob/d8d56f77f9e868127c4849dac74d65512db658e8/webapp/frontend/src/app/shared/device-status.pipe.ts
|
||||||
|
const DeviceStatus = {
|
||||||
|
passed: 0,
|
||||||
|
failed_smart: 1,
|
||||||
|
failed_scrutiny: 2,
|
||||||
|
failed_both: 3,
|
||||||
|
|
||||||
|
isFailed(s){ return s > this.passed && s <= this.failed_both},
|
||||||
|
isUnknown(s){ return s < this.passed || s > this.failed_both}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @see https://github.com/AnalogJ/scrutiny/blob/d8d56f77f9e868127c4849dac74d65512db658e8/webapp/frontend/src/app/core/config/app.config.ts
|
||||||
|
const DeviceStatusThreshold = {
|
||||||
|
smart: 1,
|
||||||
|
scrutiny: 2,
|
||||||
|
both: 3
|
||||||
|
}
|
||||||
|
|
||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
|
const { data: scrutinySettings, error: scrutinySettingsError } = useWidgetAPI(widget, "settings");
|
||||||
const { data: scrutinyData, error: scrutinyError } = useWidgetAPI(widget, "summary");
|
const { data: scrutinyData, error: scrutinyError } = useWidgetAPI(widget, "summary");
|
||||||
|
|
||||||
if (scrutinyError) {
|
if (scrutinyError || scrutinySettingsError) {
|
||||||
return <Container error={scrutinyError} />;
|
const finalError = scrutinyError ?? scrutinySettingsError;
|
||||||
|
return <Container error={finalError} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scrutinyData) {
|
if (!scrutinyData || !scrutinySettings) {
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="scrutiny.passed" />
|
<Block label="scrutiny.passed" />
|
||||||
@@ -19,13 +40,14 @@ export default function Component({ service }) {
|
|||||||
<Block label="scrutiny.unknown" />
|
<Block label="scrutiny.unknown" />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const deviceIds = Object.values(scrutinyData.data.summary);
|
const deviceIds = Object.values(scrutinyData.data.summary);
|
||||||
|
const statusThreshold = scrutinySettings.settings.metrics.status_threshold;
|
||||||
const passed = deviceIds.filter(deviceId => deviceId.device.device_status === 0)?.length || 0;
|
|
||||||
const failed = deviceIds.filter(deviceId => deviceId.device.device_status > 0 && deviceId.device.device_status <= 3)?.length || 0;
|
const failed = deviceIds.filter(deviceId => (DeviceStatus.isFailed(deviceId.device.device_status) && statusThreshold === DeviceStatusThreshold.both) || [statusThreshold, DeviceStatus.failed_both].includes(deviceId.device.device_status))?.length || 0;
|
||||||
const unknown = deviceIds.length - (passed + failed) || 0;
|
const unknown = deviceIds.filter(deviceId => DeviceStatus.isUnknown(deviceId.device.device_status))?.length || 0;
|
||||||
|
const passed = deviceIds.length - (failed + unknown);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
@@ -33,5 +55,8 @@ export default function Component({ service }) {
|
|||||||
<Block label="scrutiny.failed" value={failed} />
|
<Block label="scrutiny.failed" value={failed} />
|
||||||
<Block label="scrutiny.unknown" value={unknown} />
|
<Block label="scrutiny.unknown" value={unknown} />
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ const widget = {
|
|||||||
"data",
|
"data",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
settings: {
|
||||||
|
endpoint: "settings",
|
||||||
|
validate: [
|
||||||
|
"settings",
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
import Container from "components/services/widget/container";
|
import Container from "components/services/widget/container";
|
||||||
import Block from "components/services/widget/block";
|
import Block from "components/services/widget/block";
|
||||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
export default function Component({ service }) {
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { widget } = service;
|
const { widget } = service;
|
||||||
|
|
||||||
const { data: wantedData, error: wantedError } = useWidgetAPI(widget, "wanted/missing");
|
const { data: wantedData, error: wantedError } = useWidgetAPI(widget, "wanted/missing");
|
||||||
@@ -26,9 +29,9 @@ export default function Component({ service }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block label="sonarr.wanted" value={wantedData.totalRecords} />
|
<Block label="sonarr.wanted" value={t("common.number", { value: wantedData.totalRecords })} />
|
||||||
<Block label="sonarr.queued" value={queuedData.totalRecords} />
|
<Block label="sonarr.queued" value={t("common.number", { value: queuedData.totalRecords })} />
|
||||||
<Block label="sonarr.series" value={seriesData.total} />
|
<Block label="sonarr.series" value={t("common.number", { value: seriesData.total })} />
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ export default function Component({ service }) {
|
|||||||
<Container service={service}>
|
<Container service={service}>
|
||||||
<Block
|
<Block
|
||||||
label="speedtest.download"
|
label="speedtest.download"
|
||||||
value={t("common.bitrate", { value: speedtestData.data.download * 1024 * 1024 })}
|
value={t("common.bitrate", { value: speedtestData.data.download * 1000 * 1000 })}
|
||||||
/>
|
/>
|
||||||
<Block label="speedtest.upload" value={t("common.bitrate", { value: speedtestData.data.upload * 1024 * 1024 })} />
|
<Block label="speedtest.upload" value={t("common.bitrate", { value: speedtestData.data.upload * 1000 * 1000 })} />
|
||||||
<Block
|
<Block
|
||||||
label="speedtest.ping"
|
label="speedtest.ping"
|
||||||
value={t("common.ms", {
|
value={t("common.ms", {
|
||||||
|
|||||||
42
src/widgets/tdarr/component.jsx
Normal file
42
src/widgets/tdarr/component.jsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
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: tdarrData, error: tdarrError } = useWidgetAPI(widget);
|
||||||
|
|
||||||
|
if (tdarrError) {
|
||||||
|
return <Container error={tdarrError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tdarrData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="tdarr.queue" />
|
||||||
|
<Block label="tdarr.processed" />
|
||||||
|
<Block label="tdarr.errored" />
|
||||||
|
<Block label="tdarr.saved" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const queue = parseInt(tdarrData.table1Count, 10) + parseInt(tdarrData.table4Count, 10);
|
||||||
|
const processed = parseInt(tdarrData.table2Count, 10) + parseInt(tdarrData.table5Count, 10);
|
||||||
|
const errored = parseInt(tdarrData.table3Count, 10) + parseInt(tdarrData.table6Count, 10);
|
||||||
|
const saved = parseFloat(tdarrData.sizeDiff, 10) * 1000000000;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="tdarr.queue" value={t("common.number", { value: queue })} />
|
||||||
|
<Block label="tdarr.processed" value={t("common.number", { value: processed })} />
|
||||||
|
<Block label="tdarr.errored" value={t("common.number", { value: errored })} />
|
||||||
|
<Block label="tdarr.saved" value={t("common.bytes", { value: saved })} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
48
src/widgets/tdarr/proxy.js
Normal file
48
src/widgets/tdarr/proxy.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { httpProxy } from "utils/proxy/http";
|
||||||
|
import { formatApiCall } from "utils/proxy/api-helpers";
|
||||||
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
|
import createLogger from "utils/logger";
|
||||||
|
import widgets from "widgets/widgets";
|
||||||
|
|
||||||
|
const proxyName = "tdarrProxyHandler";
|
||||||
|
const logger = createLogger(proxyName);
|
||||||
|
|
||||||
|
export default async function tdarrProxyHandler(req, res) {
|
||||||
|
const { group, service, endpoint } = req.query;
|
||||||
|
|
||||||
|
if (!group || !service) {
|
||||||
|
logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const widget = await getServiceWidget(group, service);
|
||||||
|
|
||||||
|
if (!widget) {
|
||||||
|
logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||||
|
|
||||||
|
const [status, contentType, data] = await httpProxy(url, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"data": {
|
||||||
|
"collection": "StatisticsJSONDB",
|
||||||
|
"mode": "getById",
|
||||||
|
"docID": "statistics"
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
"content-type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.error("Error getting data from Tdarr: %d. Data: %s", status, data);
|
||||||
|
return res.status(500).send({error: {message:"Error getting data from Tdarr", url, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentType) res.setHeader("Content-Type", contentType);
|
||||||
|
return res.status(status).send(data);
|
||||||
|
}
|
||||||
8
src/widgets/tdarr/widget.js
Normal file
8
src/widgets/tdarr/widget.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import tdarrProxyHandler from "./proxy";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "{url}/api/v2/cruddb",
|
||||||
|
proxyHandler: tdarrProxyHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
@@ -25,12 +25,12 @@ export default async function transmissionProxyHandler(req, res) {
|
|||||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = cache.get(headerCacheKey);
|
let headers = cache.get(`${headerCacheKey}.${service}`);
|
||||||
if (!headers) {
|
if (!headers) {
|
||||||
headers = {
|
headers = {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
}
|
}
|
||||||
cache.put(headerCacheKey, headers);
|
cache.put(`${headerCacheKey}.${service}`, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
|
||||||
@@ -55,7 +55,7 @@ export default async function transmissionProxyHandler(req, res) {
|
|||||||
if (status === 409) {
|
if (status === 409) {
|
||||||
logger.debug("Transmission is rejecting the request, but returning a CSRF token");
|
logger.debug("Transmission is rejecting the request, but returning a CSRF token");
|
||||||
headers[csrfHeaderName] = responseHeaders[csrfHeaderName];
|
headers[csrfHeaderName] = responseHeaders[csrfHeaderName];
|
||||||
cache.put(headerCacheKey, headers);
|
cache.put(`${headerCacheKey}.${service}`, headers);
|
||||||
|
|
||||||
// retry the request, now with the CSRF token
|
// retry the request, now with the CSRF token
|
||||||
[status, contentType, data, responseHeaders] = await httpProxy(url, {
|
[status, contentType, data, responseHeaders] = await httpProxy(url, {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ async function login(widget) {
|
|||||||
|
|
||||||
export default async function unifiProxyHandler(req, res) {
|
export default async function unifiProxyHandler(req, res) {
|
||||||
const widget = await getWidget(req);
|
const widget = await getWidget(req);
|
||||||
|
const { service } = req.query;
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
return res.status(400).json({ error: "Invalid proxy service type" });
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
}
|
}
|
||||||
@@ -68,7 +69,7 @@ export default async function unifiProxyHandler(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let [status, contentType, data, responseHeaders] = [];
|
let [status, contentType, data, responseHeaders] = [];
|
||||||
let prefix = cache.get(prefixCacheKey);
|
let prefix = cache.get(`${prefixCacheKey}.${service}`);
|
||||||
if (prefix === null) {
|
if (prefix === null) {
|
||||||
// auto detect if we're talking to a UDM Pro, and cache the result so that we
|
// auto detect if we're talking to a UDM Pro, and cache the result so that we
|
||||||
// don't make two requests each time data from Unifi is required
|
// don't make two requests each time data from Unifi is required
|
||||||
@@ -77,7 +78,7 @@ export default async function unifiProxyHandler(req, res) {
|
|||||||
if (responseHeaders?.["x-csrf-token"]) {
|
if (responseHeaders?.["x-csrf-token"]) {
|
||||||
prefix = udmpPrefix;
|
prefix = udmpPrefix;
|
||||||
}
|
}
|
||||||
cache.put(prefixCacheKey, prefix);
|
cache.put(`${prefixCacheKey}.${service}`, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.prefix = prefix;
|
widget.prefix = prefix;
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import bazarr from "./bazarr/widget";
|
|||||||
import changedetectionio from "./changedetectionio/widget";
|
import changedetectionio from "./changedetectionio/widget";
|
||||||
import coinmarketcap from "./coinmarketcap/widget";
|
import coinmarketcap from "./coinmarketcap/widget";
|
||||||
import deluge from "./deluge/widget";
|
import deluge from "./deluge/widget";
|
||||||
import diskstation from "./diskstation/widget";
|
import downloadstation from "./downloadstation/widget";
|
||||||
import emby from "./emby/widget";
|
import emby from "./emby/widget";
|
||||||
|
import flood from "./flood/widget";
|
||||||
import gluetun from "./gluetun/widget";
|
import gluetun from "./gluetun/widget";
|
||||||
import gotify from "./gotify/widget";
|
import gotify from "./gotify/widget";
|
||||||
import hdhomerun from "./hdhomerun/widget";
|
import hdhomerun from "./hdhomerun/widget";
|
||||||
@@ -15,10 +16,15 @@ import jackett from "./jackett/widget";
|
|||||||
import jellyseerr from "./jellyseerr/widget";
|
import jellyseerr from "./jellyseerr/widget";
|
||||||
import lidarr from "./lidarr/widget";
|
import lidarr from "./lidarr/widget";
|
||||||
import mastodon from "./mastodon/widget";
|
import mastodon from "./mastodon/widget";
|
||||||
|
import miniflux from "./miniflux/widget";
|
||||||
|
import mikrotik from "./mikrotik/widget";
|
||||||
import navidrome from "./navidrome/widget";
|
import navidrome from "./navidrome/widget";
|
||||||
|
import nextdns from "./nextdns/widget";
|
||||||
import npm from "./npm/widget";
|
import npm from "./npm/widget";
|
||||||
import nzbget from "./nzbget/widget";
|
import nzbget from "./nzbget/widget";
|
||||||
|
import omada from "./omada/widget";
|
||||||
import ombi from "./ombi/widget";
|
import ombi from "./ombi/widget";
|
||||||
|
import opnsense from "./opnsense/widget";
|
||||||
import overseerr from "./overseerr/widget";
|
import overseerr from "./overseerr/widget";
|
||||||
import paperlessngx from "./paperlessngx/widget";
|
import paperlessngx from "./paperlessngx/widget";
|
||||||
import pihole from "./pihole/widget";
|
import pihole from "./pihole/widget";
|
||||||
@@ -37,12 +43,14 @@ import sonarr from "./sonarr/widget";
|
|||||||
import speedtest from "./speedtest/widget";
|
import speedtest from "./speedtest/widget";
|
||||||
import strelaysrv from "./strelaysrv/widget";
|
import strelaysrv from "./strelaysrv/widget";
|
||||||
import tautulli from "./tautulli/widget";
|
import tautulli from "./tautulli/widget";
|
||||||
|
import tdarr from "./tdarr/widget";
|
||||||
import traefik from "./traefik/widget";
|
import traefik from "./traefik/widget";
|
||||||
import transmission from "./transmission/widget";
|
import transmission from "./transmission/widget";
|
||||||
import tubearchivist from "./tubearchivist/widget";
|
import tubearchivist from "./tubearchivist/widget";
|
||||||
import truenas from "./truenas/widget";
|
import truenas from "./truenas/widget";
|
||||||
import unifi from "./unifi/widget";
|
import unifi from "./unifi/widget";
|
||||||
import watchtower from './watchtower/widget'
|
import watchtower from './watchtower/widget'
|
||||||
|
import xteve from './xteve/widget'
|
||||||
|
|
||||||
const widgets = {
|
const widgets = {
|
||||||
adguard,
|
adguard,
|
||||||
@@ -52,8 +60,10 @@ const widgets = {
|
|||||||
changedetectionio,
|
changedetectionio,
|
||||||
coinmarketcap,
|
coinmarketcap,
|
||||||
deluge,
|
deluge,
|
||||||
diskstation,
|
diskstation: downloadstation,
|
||||||
|
downloadstation,
|
||||||
emby,
|
emby,
|
||||||
|
flood,
|
||||||
gluetun,
|
gluetun,
|
||||||
gotify,
|
gotify,
|
||||||
hdhomerun,
|
hdhomerun,
|
||||||
@@ -63,10 +73,15 @@ const widgets = {
|
|||||||
jellyseerr,
|
jellyseerr,
|
||||||
lidarr,
|
lidarr,
|
||||||
mastodon,
|
mastodon,
|
||||||
|
miniflux,
|
||||||
|
mikrotik,
|
||||||
navidrome,
|
navidrome,
|
||||||
|
nextdns,
|
||||||
npm,
|
npm,
|
||||||
nzbget,
|
nzbget,
|
||||||
|
omada,
|
||||||
ombi,
|
ombi,
|
||||||
|
opnsense,
|
||||||
overseerr,
|
overseerr,
|
||||||
paperlessngx,
|
paperlessngx,
|
||||||
pihole,
|
pihole,
|
||||||
@@ -85,6 +100,7 @@ const widgets = {
|
|||||||
speedtest,
|
speedtest,
|
||||||
strelaysrv,
|
strelaysrv,
|
||||||
tautulli,
|
tautulli,
|
||||||
|
tdarr,
|
||||||
traefik,
|
traefik,
|
||||||
transmission,
|
transmission,
|
||||||
tubearchivist,
|
tubearchivist,
|
||||||
@@ -92,6 +108,7 @@ const widgets = {
|
|||||||
unifi,
|
unifi,
|
||||||
unifi_console: unifi,
|
unifi_console: unifi,
|
||||||
watchtower,
|
watchtower,
|
||||||
|
xteve,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default widgets;
|
export default widgets;
|
||||||
|
|||||||
35
src/widgets/xteve/component.jsx
Normal file
35
src/widgets/xteve/component.jsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
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: xteveData, error: xteveError } = useWidgetAPI(widget, "api");
|
||||||
|
|
||||||
|
if (xteveError) {
|
||||||
|
return <Container error={xteveError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xteveData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="xteve.streams_all" />
|
||||||
|
<Block label="xteve.streams_active " />
|
||||||
|
<Block label="xteve.streams_xepg" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="xteve.streams_all" value={t("common.number", { value: xteveData["streams.all"] ?? 0 })} />
|
||||||
|
<Block label="xteve.streams_active" value={t("common.number", { value: xteveData["streams.active"] ?? 0 })} />
|
||||||
|
<Block label="xteve.streams_xepg" value={t("common.number", { value: xteveData["streams.xepg"] ?? 0 })} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
63
src/widgets/xteve/proxy.js
Normal file
63
src/widgets/xteve/proxy.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { formatApiCall } from "utils/proxy/api-helpers";
|
||||||
|
import { httpProxy } from "utils/proxy/http";
|
||||||
|
import createLogger from "utils/logger";
|
||||||
|
import widgets from "widgets/widgets";
|
||||||
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
|
|
||||||
|
const logger = createLogger("xteveProxyHandler");
|
||||||
|
|
||||||
|
export default async function xteveProxyHandler(req, res) {
|
||||||
|
const { group, service, endpoint } = req.query;
|
||||||
|
|
||||||
|
if (!group || !service) {
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const widget = await getServiceWidget(group, service);
|
||||||
|
const api = widgets?.[widget.type]?.api;
|
||||||
|
if (!api) {
|
||||||
|
return res.status(403).json({ error: "Service does not support API calls" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = formatApiCall(api, { endpoint, ...widget });
|
||||||
|
const method = "POST";
|
||||||
|
const payload = { cmd: "status" };
|
||||||
|
|
||||||
|
if (widget.username && widget.password) {
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [status, contentType, data] = await httpProxy(url, {
|
||||||
|
method,
|
||||||
|
body: JSON.stringify({
|
||||||
|
cmd: "login",
|
||||||
|
username: widget.username,
|
||||||
|
password: widget.password,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.debug("Error logging into xteve", status, url);
|
||||||
|
return res.status(status).json({error: {message: `HTTP Error ${status} logging into xteve`, url, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = JSON.parse(data.toString());
|
||||||
|
|
||||||
|
if (json?.status !== true) {
|
||||||
|
return res.status(401).json({error: {message: "Authentication failed", url, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.token = json.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [status, contentType, data] = await httpProxy(url, {
|
||||||
|
method,
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.debug("Error %d calling xteve endpoint %s", status, url);
|
||||||
|
return res.status(status).json({error: {message: `HTTP Error ${status}`, url, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentType) res.setHeader("Content-Type", contentType);
|
||||||
|
return res.status(status).send(data);
|
||||||
|
}
|
||||||
14
src/widgets/xteve/widget.js
Normal file
14
src/widgets/xteve/widget.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import xteveProxyHandler from "./proxy";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "{url}/{endpoint}",
|
||||||
|
proxyHandler: xteveProxyHandler,
|
||||||
|
|
||||||
|
mappings: {
|
||||||
|
"api": {
|
||||||
|
endpoint: "api/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
||||||
Reference in New Issue
Block a user