Compare commits

..

185 Commits

Author SHA1 Message Date
Daniel Li
69ee459e8a Fix: SMART result of OMV should always from monitored devices (#2025) 2023-09-19 08:46:16 -07:00
shamoon
ed0527a3da Fix custom.js not working (#2023) 2023-09-18 21:41:31 -07:00
shamoon
04a1c68ba0 Fix k3d memory specification 2023-09-18 14:35:42 -07:00
Pysta
b74faea449 Translated using Weblate (Slovak)
Currently translated at 24.1% (129 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sk/
2023-09-18 14:23:36 +02:00
avb15621
0c9b6480c5 Translated using Weblate (Dutch)
Currently translated at 53.9% (288 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2023-09-18 14:23:35 +02:00
Roel van de Wiel
6fbb3bfbb1 Translated using Weblate (Dutch)
Currently translated at 53.9% (288 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2023-09-18 14:23:35 +02:00
A Warmerdam
53355561a8 Translated using Weblate (Dutch)
Currently translated at 53.9% (288 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2023-09-18 14:23:35 +02:00
Jan-Philipp Fischer
6e43194f71 Fix: Kubernetes discovery & Check for Custom Resource Definitions (#2003)
* Implement a CRD existence check

* test adding patch
2023-09-17 16:49:03 -07:00
shamoon
a72a27a8b5 Maybe handle k8s traefik ingress routes returns nothing 2023-09-17 10:05:45 -07:00
Ben Phelps
6c682cb648 Update README.md 2023-09-17 11:00:15 +03:00
Ben Phelps
e7587b8308 update readme image 2023-09-17 10:57:37 +03:00
shamoon
e663994c9b Allow tab name 0 2023-09-16 15:24:32 -07:00
shamoon
898fb88d86 Allow numbers in tab name (#2004) 2023-09-16 14:37:06 -07:00
Ben Phelps
6f5c2a8c1e update readme 2023-09-16 22:16:34 +03:00
shamoon
2908bfcb7c Update service-helpers.js 2023-09-16 08:59:36 -07:00
shamoon
34589f0514 reduce k8s traefik discovery log noise 2023-09-16 08:28:58 -07:00
shamoon
3cd441a45e Maybe handle no traefik ingress routes
See #1998
2023-09-16 08:06:24 -07:00
shamoon
816a2a5106 Fix ping stats not clickable in 0.6.30
Closes #1997
2023-09-16 07:37:31 -07:00
shamoon
38079badc8 Pixel-perfect aligned edges 2023-09-16 02:37:24 -07:00
Denis Papec
5109facf1c Fix layouts for initial tab (#1996) 2023-09-15 09:55:23 -07:00
shamoon
ee0afaa638 Fix activeTab with no layout settings
Closes #1995
2023-09-15 09:22:37 -07:00
shamoon
42b69e44a2 replace spaces in tab slugify 2023-09-15 08:35:24 -07:00
shamoon
6dc3be6029 Fix: slugify tab names (#1994) 2023-09-15 08:17:57 -07:00
shamoon
ec1cf2f3ca Resolve bad setState warning in tabprovider (#1993) 2023-09-15 08:00:08 -07:00
shamoon
cde8c658ae Fix duplicate keys on customapi widget 2023-09-15 07:47:10 -07:00
Denis Papec
8a520e07a5 Fix for broken layout when layout is not defined (#1989)
* Fix for broken layout when layout is not defined

* code style

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-09-15 07:41:56 -07:00
Greg Look
eb2b37063f Enhancement: add remap, scale, and suffx to customapi fields (#1958) 2023-09-14 23:50:54 -07:00
Denis Papec
2d8160512f Feature: tabbed layouts (#1981) 2023-09-14 14:55:14 -07:00
shamoon
768107cde8 Update index.jsx 2023-09-14 00:18:43 -07:00
Gino Cicatiello
9fb0917054 Translated using Weblate (Italian)
Currently translated at 100.0% (534 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2023-09-13 05:57:42 +02:00
shamoon
1895899839 Merge pull request #1974 from benphelps/dependabot/github_actions/docker/setup-buildx-action-3
Bump docker/setup-buildx-action from 2 to 3
2023-09-12 11:02:08 -07:00
shamoon
ec25af781c Merge pull request #1973 from benphelps/dependabot/github_actions/docker/build-push-action-5
Bump docker/build-push-action from 4 to 5
2023-09-12 11:01:54 -07:00
dependabot[bot]
bda567e961 Bump docker/build-push-action from 4 to 5
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 17:29:15 +00:00
shamoon
c525dda77d Merge pull request #1972 from benphelps/dependabot/github_actions/docker/setup-qemu-action-3
Bump docker/setup-qemu-action from 2 to 3
2023-09-12 10:28:27 -07:00
shamoon
65a0b9f905 Merge pull request #1971 from benphelps/dependabot/github_actions/docker/metadata-action-5
Bump docker/metadata-action from 4 to 5
2023-09-12 10:12:52 -07:00
shamoon
74e3a3f09c Merge pull request #1970 from benphelps/dependabot/github_actions/docker/login-action-3
Bump docker/login-action from 2 to 3
2023-09-12 10:02:08 -07:00
dependabot[bot]
d610d379f8 Bump docker/setup-buildx-action from 2 to 3
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 16:46:19 +00:00
dependabot[bot]
e3acc444d8 Bump docker/setup-qemu-action from 2 to 3
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 16:46:03 +00:00
dependabot[bot]
16299ced66 Bump docker/metadata-action from 4 to 5
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4 to 5.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md)
- [Commits](https://github.com/docker/metadata-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 16:45:55 +00:00
dependabot[bot]
3a018d5a63 Bump docker/login-action from 2 to 3
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 16:45:50 +00:00
TheRolf
b39c79bea1 Custom JS and CSS (#1950)
* First commit for custom styles and JS

* Adjusted classes

* Added ids and classes for services and bookmarks

* Apply suggestions from code review

* Remove mime dependency

* Update settings.json

* Detect custom css / js changes, no refresh

* Added preload to custom scripts and styles so they can load earlier

* Added data attribute name for bookmarks too

* Update [path].js

* code style, revert some pointer changes

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-09-10 14:36:54 -07:00
Vojislav
0741ef0427 Added start_url in manifest.json to fulfill requirements for installable app (#1955)
Co-authored-by: Vojislav Zelić <vodzo@Vojislavs-MacBook-Air.local>
2023-09-09 11:25:29 -07:00
Alex Tzonkov
bce43c28d6 Translated using Weblate (Bulgarian)
Currently translated at 15.1% (81 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/bg/
2023-09-09 15:52:35 +02:00
gallegonovato
e94796f878 Translated using Weblate (Spanish)
Currently translated at 100.0% (534 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-09-09 15:52:34 +02:00
CosminPerRam
2ee6881376 Update GameDig dependency to 4.1.0 and revert compressjs fix. (#1939)
* Update GD to 4.1.0 and revert compressjs fix

* Update package-lock
2023-09-09 06:18:38 -07:00
shamoon
95635fca04 Revert "Enhancement: forward cookies from request (#1804)" (#1946)
This reverts commit d4edd432d8.
2023-09-09 06:07:04 -07:00
Nils Gereke
4f1cde97ec fix: total servers only representing last node (#1936) 2023-09-09 06:04:41 -07:00
James Waters
d4edd432d8 Enhancement: forward cookies from request (#1804) 2023-09-08 16:50:32 -07:00
shamoon
63f952509e Support disable glances cpu + mem (#1931) 2023-09-08 08:59:04 -07:00
shamoon
89f2e9739d Fix error glances cpu data not available yet (#1932) 2023-09-08 08:58:56 -07:00
Ben Phelps
9569f56aa5 attempt a fix (#1929) 2023-09-08 08:58:39 -07:00
shamoon
ae3634e9d4 Change crossorigin to crossOrigin
Co-Authored-By: Shagon94 <9140783+shagon94@users.noreply.github.com>
2023-09-08 07:16:36 -07:00
Gino Cicatiello
f96154189b Translated using Weblate (Italian)
Currently translated at 99.8% (533 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2023-09-08 04:31:23 +02:00
BluePhi09
402f86fc1b Translated using Weblate (German)
Currently translated at 97.9% (523 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2023-09-08 04:31:23 +02:00
shamoon
3f71bff13f fix blur on bookmark items 2023-09-06 21:27:24 -07:00
shamoon
a061eccef5 Merge pull request #1920 from benphelps/fix/ping-blocks-link
Fix: remove pointer events on ping div
2023-09-06 12:46:06 -07:00
shamoon
957bd9491b remove pointer events on ping div 2023-09-06 12:45:03 -07:00
Ben Phelps
7a1f8850b8 pass chart to all containers 2023-09-06 15:28:37 +03:00
Anonymous
ef3da08d93 Translated using Weblate (Basque)
Currently translated at 6.3% (34 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/eu/
2023-09-06 13:08:39 +02:00
Anonymous
5a67bcd14d Translated using Weblate (Indonesian)
Currently translated at 4.4% (24 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/id/
2023-09-06 13:08:39 +02:00
Anonymous
864f4ef6cc Translated using Weblate (Slovenian)
Currently translated at 97.5% (521 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sl/
2023-09-06 13:08:38 +02:00
Anonymous
cc88bf21a9 Translated using Weblate (Greek)
Currently translated at 33.8% (181 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/el/
2023-09-06 13:08:38 +02:00
Anonymous
a6eba9bcde Translated using Weblate (Korean)
Currently translated at 32.3% (173 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ko/
2023-09-06 13:08:38 +02:00
Anonymous
8bf3b3e217 Translated using Weblate (Slovak)
Currently translated at 1.8% (10 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sk/
2023-09-06 13:08:37 +02:00
Anonymous
97c3d7c513 Translated using Weblate (Thai)
Currently translated at 8.9% (48 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/th/
2023-09-06 13:08:37 +02:00
Anonymous
13ee73f178 Translated using Weblate (Latvian)
Currently translated at 22.0% (118 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/lv/
2023-09-06 13:08:37 +02:00
Anonymous
eedc47e091 Translated using Weblate (Japanese)
Currently translated at 94.7% (506 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ja/
2023-09-06 13:08:37 +02:00
Anonymous
dc8d0f6ca9 Translated using Weblate (Ukrainian)
Currently translated at 94.7% (506 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/uk/
2023-09-06 13:08:36 +02:00
Anonymous
9811a4d5ee Translated using Weblate (Esperanto)
Currently translated at 27.1% (145 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/eo/
2023-09-06 13:08:36 +02:00
Anonymous
27f52fd981 Translated using Weblate (Hindi)
Currently translated at 1.8% (10 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hi/
2023-09-06 13:08:36 +02:00
Anonymous
7adcd6c242 Translated using Weblate (Malay)
Currently translated at 47.1% (252 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ms/
2023-09-06 13:08:36 +02:00
Anonymous
74b73f99b7 Translated using Weblate (Danish)
Currently translated at 97.5% (521 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/da/
2023-09-06 13:08:35 +02:00
Anonymous
1841a794a4 Translated using Weblate (Czech)
Currently translated at 83.1% (444 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/cs/
2023-09-06 13:08:35 +02:00
Anonymous
bca024e3c2 Translated using Weblate (Arabic)
Currently translated at 49.0% (262 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ar/
2023-09-06 13:08:34 +02:00
Anonymous
7cb4780a9c Translated using Weblate (Serbian)
Currently translated at 1.8% (10 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sr/
2023-09-06 13:08:34 +02:00
Anonymous
b0d68b3c0e Translated using Weblate (Turkish)
Currently translated at 73.5% (393 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/tr/
2023-09-06 13:08:34 +02:00
Anonymous
9a060b3db1 Translated using Weblate (Bulgarian)
Currently translated at 8.8% (47 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/bg/
2023-09-06 13:08:34 +02:00
Anonymous
0ffa5b8ace Translated using Weblate (Telugu)
Currently translated at 40.4% (216 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/te/
2023-09-06 13:08:33 +02:00
Anonymous
2ec96a6457 Translated using Weblate (Finnish)
Currently translated at 33.1% (177 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fi/
2023-09-06 13:08:33 +02:00
Anonymous
1098b0d4f9 Translated using Weblate (Yue (Traditional))
Currently translated at 22.0% (118 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/yue_Hant/
2023-09-06 13:08:33 +02:00
Anonymous
1ecfa382bc Translated using Weblate (Portuguese (Brazil))
Currently translated at 86.3% (461 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt_BR/
2023-09-06 13:08:32 +02:00
Anonymous
2f83906244 Translated using Weblate (Romanian)
Currently translated at 29.2% (156 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/
2023-09-06 13:08:32 +02:00
Anonymous
6eacff4638 Translated using Weblate (Hebrew)
Currently translated at 18.9% (101 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2023-09-06 13:08:32 +02:00
Anonymous
e1c615de14 Translated using Weblate (Hungarian)
Currently translated at 88.2% (471 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/
2023-09-06 13:08:31 +02:00
Anonymous
dd842ee7a8 Translated using Weblate (Croatian)
Currently translated at 88.0% (470 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/
2023-09-06 13:08:31 +02:00
Anonymous
2681930b2e Translated using Weblate (Swedish)
Currently translated at 24.7% (132 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/
2023-09-06 13:08:31 +02:00
Anonymous
4bfad4d27e Translated using Weblate (Polish)
Currently translated at 70.0% (374 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/
2023-09-06 13:08:31 +02:00
Anonymous
c13567bcb7 Translated using Weblate (Catalan)
Currently translated at 48.8% (261 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2023-09-06 13:08:30 +02:00
Anonymous
eb77e42264 Translated using Weblate (Chinese (Traditional))
Currently translated at 93.4% (499 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/
2023-09-06 13:08:30 +02:00
Anonymous
75b46509c1 Translated using Weblate (Dutch)
Currently translated at 45.5% (243 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2023-09-06 13:08:30 +02:00
Anonymous
e433d75372 Translated using Weblate (Vietnamese)
Currently translated at 8.4% (45 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/
2023-09-06 13:08:29 +02:00
Anonymous
5d76ac4c7f Translated using Weblate (Norwegian Bokmål)
Currently translated at 15.1% (81 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/
2023-09-06 13:08:29 +02:00
Anonymous
95b91b953a Translated using Weblate (Italian)
Currently translated at 99.8% (533 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2023-09-06 13:08:29 +02:00
Anonymous
63e65d721b Translated using Weblate (Chinese (Simplified))
Currently translated at 84.2% (450 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2023-09-06 13:08:29 +02:00
Anonymous
ec6deb5ac9 Translated using Weblate (Russian)
Currently translated at 80.5% (430 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2023-09-06 13:08:28 +02:00
Anonymous
b4c7faf178 Translated using Weblate (Portuguese)
Currently translated at 77.7% (415 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2023-09-06 13:08:28 +02:00
Anonymous
132ec69f29 Translated using Weblate (French)
Currently translated at 99.8% (533 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2023-09-06 13:08:28 +02:00
Anonymous
673404e441 Translated using Weblate (Spanish)
Currently translated at 99.8% (533 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-09-06 13:08:28 +02:00
Anonymous
e267717898 Translated using Weblate (German)
Currently translated at 97.5% (521 of 534 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2023-09-06 13:08:27 +02:00
Ben Phelps
99f60eab29 Merge pull request #1917 from benphelps/non-graphs
mini-non-chart charts
2023-09-06 14:06:37 +03:00
Ben Phelps
17b0f635d8 mini-non-chart charts 2023-09-06 13:53:39 +03:00
fenix_vd
c2058f353d Translated using Weblate (Russian)
Currently translated at 80.6% (430 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2023-09-05 14:56:10 +02:00
shamoon
3a10214a45 Merge pull request #1903 from benphelps/feature-mixed-layout
Enhancement: mixed bookmarks / services layout
2023-09-04 20:27:04 -07:00
shamoon
9713a16e1f Merge pull request #1910 from benphelps/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2023-09-04 12:21:49 -07:00
dependabot[bot]
0e57547824 Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 16:51:58 +00:00
Anonymous
80eb03194f Translated using Weblate (German)
Currently translated at 97.7% (521 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2023-09-04 05:46:39 +02:00
Ettore Atalan
a0019d832e Translated using Weblate (German)
Currently translated at 97.7% (521 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2023-09-04 05:46:37 +02:00
shamoon
4517409dbd Support mixing services & bookmarks layout 2023-09-03 07:50:04 -07:00
Ben Phelps
61b969cced Merge pull request #1906 from benphelps/glances-fs
fix linting
2023-09-03 17:49:11 +03:00
shamoon
ed293071b4 Update fs.jsx 2023-09-03 07:49:05 -07:00
Ben Phelps
5d0a793195 fix linting 2023-09-03 17:47:54 +03:00
Ben Phelps
b2908cdd97 Merge pull request #1905 from benphelps/glances-fs
Add glances filesystem graph
2023-09-03 17:28:50 +03:00
Ben Phelps
108ca23212 Merge branch 'main' into glances-fs 2023-09-03 17:23:08 +03:00
Georges-Antoine Assi
9529553102 Enhancement: apply layout settings to bookmarks (#1902)
* Apply layout settings to bookmarks

* merge columnMap const

* Remove bookmarksOnTop setting

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-09-03 07:05:25 -07:00
Gino Cicatiello
4d55f1fba4 Translated using Weblate (Italian)
Currently translated at 100.0% (533 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2023-09-03 09:52:24 +02:00
gallegonovato
257ab91ffb Translated using Weblate (Spanish)
Currently translated at 100.0% (533 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-09-03 09:52:23 +02:00
shamoon
96e8882fb5 Merge pull request #1896 from benphelps/fix/issue-1894
Fix: cardBlur with boxedWidgets shrinks search widget
2023-08-31 10:45:54 -07:00
shamoon
864eb8cfbb Fix duplicate additionalClassNames 2023-08-31 10:43:57 -07:00
shamoon
147ed30b09 Merge pull request #1893 from Spideramn/fix/manifest-credentials
Add crossorigin="use-credentials" to manifest link tag.
2023-08-31 10:41:14 -07:00
CosminPerRam
14aebf9e41 Translated using Weblate (Romanian)
Currently translated at 29.2% (156 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/
2023-08-31 17:55:38 +02:00
Spideramn
76013b32b3 Add crossorigin="use-credentials" to manifest link tag. 2023-08-31 11:58:51 +02:00
CosminPerRam
f0a4ab645c Update GameDig dependency to 4.0.7 (#1886) 2023-08-30 08:19:45 -07:00
Azurite
eedb728025 Translated using Weblate (Japanese)
Currently translated at 94.9% (506 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ja/
2023-08-30 15:55:21 +02:00
Nonoss117
419e930456 Translated using Weblate (French)
Currently translated at 100.0% (533 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2023-08-30 15:55:21 +02:00
shamoon
494a1c50d5 Update index.jsx 2023-08-29 09:48:32 -07:00
shamoon
3b05655fb0 Merge pull request #1881 from benphelps/fix/issue-1878
Fix location of quicklaunch, some focus issues
2023-08-29 09:37:58 -07:00
shamoon
98baf0507b Fix location of quicklaunch, some focus issues 2023-08-29 09:33:58 -07:00
shamoon
36760caff9 Update component.jsx 2023-08-28 17:48:44 -07:00
Anonymous
2363f96f1b Translated using Weblate (Basque)
Currently translated at 6.3% (34 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/eu/
2023-08-29 02:04:35 +02:00
Anonymous
c0c14b0233 Translated using Weblate (Indonesian)
Currently translated at 4.5% (24 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/id/
2023-08-29 02:04:34 +02:00
Anonymous
5c28b501f6 Translated using Weblate (Slovenian)
Currently translated at 97.7% (521 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sl/
2023-08-29 02:04:34 +02:00
Anonymous
5d9155ab22 Translated using Weblate (Greek)
Currently translated at 33.9% (181 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/el/
2023-08-29 02:04:33 +02:00
Anonymous
2d13c38d38 Translated using Weblate (Korean)
Currently translated at 32.4% (173 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ko/
2023-08-29 02:04:33 +02:00
Anonymous
d5891793dd Translated using Weblate (Slovak)
Currently translated at 1.8% (10 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sk/
2023-08-29 02:04:33 +02:00
Anonymous
7c8ab99df6 Translated using Weblate (Thai)
Currently translated at 9.0% (48 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/th/
2023-08-29 02:04:32 +02:00
Anonymous
c09785b4f5 Translated using Weblate (Latvian)
Currently translated at 22.1% (118 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/lv/
2023-08-29 02:04:32 +02:00
Anonymous
31d7b56fb6 Translated using Weblate (Japanese)
Currently translated at 94.9% (506 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ja/
2023-08-29 02:04:32 +02:00
Anonymous
d5fd904e55 Translated using Weblate (Ukrainian)
Currently translated at 94.9% (506 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/uk/
2023-08-29 02:04:32 +02:00
Anonymous
67b1ca6251 Translated using Weblate (Esperanto)
Currently translated at 27.2% (145 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/eo/
2023-08-29 02:04:31 +02:00
Anonymous
3d13d9311d Translated using Weblate (Hindi)
Currently translated at 1.8% (10 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hi/
2023-08-29 02:04:31 +02:00
Anonymous
1b81942549 Translated using Weblate (Malay)
Currently translated at 47.2% (252 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ms/
2023-08-29 02:04:31 +02:00
Anonymous
2013fc8193 Translated using Weblate (Danish)
Currently translated at 97.7% (521 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/da/
2023-08-29 02:04:30 +02:00
Anonymous
a8415ab40f Translated using Weblate (Czech)
Currently translated at 83.3% (444 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/cs/
2023-08-29 02:04:30 +02:00
Anonymous
4ce941a781 Translated using Weblate (Arabic)
Currently translated at 49.1% (262 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ar/
2023-08-29 02:04:29 +02:00
Anonymous
2bf5830ca8 Translated using Weblate (Serbian)
Currently translated at 1.8% (10 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sr/
2023-08-29 02:04:29 +02:00
Anonymous
b554683eca Translated using Weblate (Turkish)
Currently translated at 73.7% (393 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/tr/
2023-08-29 02:04:29 +02:00
Anonymous
9612a76bce Translated using Weblate (Bulgarian)
Currently translated at 8.8% (47 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/bg/
2023-08-29 02:04:28 +02:00
Anonymous
4a2cf8764d Translated using Weblate (Telugu)
Currently translated at 40.5% (216 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/te/
2023-08-29 02:04:28 +02:00
Anonymous
1d99f2ebf1 Translated using Weblate (Finnish)
Currently translated at 33.2% (177 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fi/
2023-08-29 02:04:27 +02:00
Anonymous
3d32c129c0 Translated using Weblate (Yue (Traditional))
Currently translated at 22.1% (118 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/yue_Hant/
2023-08-29 02:04:27 +02:00
Anonymous
5e42da6e53 Translated using Weblate (Portuguese (Brazil))
Currently translated at 86.4% (461 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt_BR/
2023-08-29 02:04:27 +02:00
Anonymous
61190f6e49 Translated using Weblate (Romanian)
Currently translated at 28.3% (151 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/
2023-08-29 02:04:26 +02:00
Anonymous
dcb3ca52e3 Translated using Weblate (Hebrew)
Currently translated at 18.9% (101 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2023-08-29 02:04:26 +02:00
Anonymous
41aea0166e Translated using Weblate (Hungarian)
Currently translated at 88.3% (471 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/
2023-08-29 02:04:25 +02:00
Anonymous
5c9d2ba04c Translated using Weblate (Croatian)
Currently translated at 88.1% (470 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/
2023-08-29 02:04:25 +02:00
Anonymous
4ad13625be Translated using Weblate (Swedish)
Currently translated at 24.7% (132 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/
2023-08-29 02:04:24 +02:00
Anonymous
acb28389f4 Translated using Weblate (Polish)
Currently translated at 70.1% (374 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/
2023-08-29 02:04:23 +02:00
Anonymous
117930a6f5 Translated using Weblate (Catalan)
Currently translated at 48.9% (261 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2023-08-29 02:04:23 +02:00
Anonymous
d4db335d3d Translated using Weblate (Chinese (Traditional))
Currently translated at 93.6% (499 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/
2023-08-29 02:04:22 +02:00
Anonymous
7b1ac03e3a Translated using Weblate (Dutch)
Currently translated at 45.5% (243 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2023-08-29 02:04:22 +02:00
Anonymous
2405e8afbd Translated using Weblate (Vietnamese)
Currently translated at 8.4% (45 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/
2023-08-29 02:04:21 +02:00
Anonymous
bccf83467b Translated using Weblate (Norwegian Bokmål)
Currently translated at 15.1% (81 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/
2023-08-29 02:04:21 +02:00
Anonymous
374e8873ce Translated using Weblate (Italian)
Currently translated at 88.1% (470 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2023-08-29 02:04:21 +02:00
Anonymous
313211f756 Translated using Weblate (Chinese (Simplified))
Currently translated at 84.4% (450 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2023-08-29 02:04:20 +02:00
Anonymous
49a68488b4 Translated using Weblate (Russian)
Currently translated at 80.1% (427 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2023-08-29 02:04:20 +02:00
Anonymous
5d66323edd Translated using Weblate (Portuguese)
Currently translated at 77.8% (415 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2023-08-29 02:04:19 +02:00
Anonymous
7d7964bfa8 Translated using Weblate (French)
Currently translated at 97.7% (521 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2023-08-29 02:04:19 +02:00
Anonymous
34bf5da16f Translated using Weblate (Spanish)
Currently translated at 97.7% (521 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-08-29 02:04:19 +02:00
Anonymous
0aefe4e327 Translated using Weblate (German)
Currently translated at 85.7% (457 of 533 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2023-08-29 02:04:18 +02:00
Andrej Kralj
15d36f74d3 Translated using Weblate (Slovenian)
Currently translated at 100.0% (521 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sl/
2023-08-29 02:02:58 +02:00
AwesomeClips
0ee1656872 Translated using Weblate (Greek)
Currently translated at 34.7% (181 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/el/
2023-08-29 02:02:58 +02:00
Azurite
0e3d05ffe2 Translated using Weblate (Japanese)
Currently translated at 97.1% (506 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ja/
2023-08-29 02:02:58 +02:00
Allan Grauengaard Hedelain
843f624655 Translated using Weblate (Danish)
Currently translated at 100.0% (521 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/da/
2023-08-29 02:02:58 +02:00
oxygen44k
ba77e0e0f7 Translated using Weblate (Chinese (Simplified))
Currently translated at 86.3% (450 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2023-08-29 02:02:58 +02:00
gallegonovato
b7198d1d52 Translated using Weblate (Spanish)
Currently translated at 100.0% (521 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-08-29 02:02:58 +02:00
shamoon
e990ba3394 Merge pull request #1876 from tomhoover/uptimerobot-widget
Add UptimeRobot widget

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-08-28 17:02:46 -07:00
Tom Hoover
e19dab3c5d Add UptimeRobot widget 2023-08-28 17:02:00 -07:00
Atropos
82d2f08e8b Enhancement: support silmultaneous traefik .containio.us and .io ingress routes for k8s (#1875) 2023-08-28 11:00:39 -07:00
shamoon
43b32fd1fb Merge pull request #1869 from rauenzi/widget-options
Allow widgets to add headers or set method
2023-08-27 16:12:22 -07:00
Zack Rauen
d6448763e0 Allow widgets to add header or set methods 2023-08-27 18:46:50 -04:00
shamoon
51ea4ea405 Merge pull request #1868 from benphelps/fix/issue-1866
Fix: support streaming media from jellyfin
2023-08-27 13:56:33 -07:00
shamoon
713cb217e4 Support streaming media from jellyfin 2023-08-27 13:55:47 -07:00
Nonoss117
8ef88f2153 Translated using Weblate (French)
Currently translated at 100.0% (521 of 521 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2023-08-26 13:27:32 +02:00
shamoon
6bfc98daf8 Collapse should rotate 180 degrees 2023-08-26 00:25:24 -07:00
Ben Phelps
d90a038884 fs widget? 2023-08-22 10:49:14 +03:00
129 changed files with 2753 additions and 1426 deletions

View File

@@ -16,7 +16,6 @@
**/compose*
**/Dockerfile*
**/node_modules
!**/node_modules/.pnpm/compressjs@*/**
**/npm-debug.log
**/obj
**/secrets.dev.yaml

View File

@@ -35,7 +35,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
@@ -48,11 +48,11 @@ jobs:
# Setup QEMU
# https://github.com/marketplace/actions/docker-setup-buildx#with-qemu
- name: Setup QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
# This step is being disabled because the runner is on a self-hosted machine
# where the cache will stick between runs.
@@ -68,7 +68,7 @@ jobs:
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -78,7 +78,7 @@ jobs:
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
@@ -88,7 +88,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}

2
.vscode/launch.json vendored
View File

@@ -16,4 +16,4 @@
}
}
]
}
}

View File

@@ -52,8 +52,6 @@ COPY --link --chown=1000:1000 /public ./public/
# Copy files from builder
COPY --link --from=builder --chown=1000:1000 /app/.next/standalone ./
COPY --link --from=builder --chown=1000:1000 /app/.next/static/ ./.next/static/
# see https://github.com/benphelps/homepage/issues/1795
COPY --link --from=builder /app/node_modules/.pnpm/compressjs@1.0.3/node_modules/compressjs/lib/ ./node_modules/.pnpm/compressjs@1.0.3/node_modules/compressjs/lib/
COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache su-exec

134
README.md
View File

@@ -6,71 +6,58 @@
</p>
<p align="center">
A modern <em>(fully static, fast)</em>, secure <em>(fully proxied)</em>, highly customizable application dashboard with integrations for more than 25 services and translations for over 15 languages. Easily configured via YAML files (or discovery via docker labels).
A modern, <em>fully static, fast</em>, secure <em>fully proxied</em>, highly customizable application dashboard with integrations for over 100 services and translations into multiple languages. Easily configured via YAML files or through docker label discovery.
</p>
<p align="center">
<img src="images/1.png" />
<img src="images/1.png?v=2" />
</p>
<p align="center">
<img src="images/2.png" width="19%" />
<img src="images/3.png" width="19%" />
<img src="images/4.png" width="19%" />
<img src="images/5.png" width="19%" />
<img src="images/6.png" width="19%" />
</p>
<p align="center">
<a href="https://discord.gg/k4ruYNrudu"><img src="https://img.shields.io/badge/Discord - Chat-blue?logo=discord&logoColor=white" /></a>
<a href="https://paypal.me/phelpsben" title="Donate"><img src="https://img.shields.io/badge/PayPal - Donate-blue?logo=paypal&logoColor=white" alt="Linkedin - phelpsben"></a>
</p>
<p align="center">
<a href="https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml"><img src="https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml/badge.svg" alt="Docker"></a>
<a href="https://github.com/benphelps/homepage/actions/workflows/docker-publish.yml"><img alt="GitHub Workflow Status (with event)" src="https://img.shields.io/github/actions/workflow/status/benphelps/homepage/docker-publish.yml"></a>
&nbsp;
<a href="https://hosted.weblate.org/engage/homepage/"><img src="https://hosted.weblate.org/widgets/homepage/-/homepage/svg-badge.svg" alt="Weblate"></a>
&nbsp;
<a href="https://discord.gg/k4ruYNrudu"><img alt="Discord" src="https://img.shields.io/discord/1019316731635834932"></a>
&nbsp;
<a href="https://paypal.me/phelpsben" title="Donate"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/benphelps"></a>
</p>
## Features
# Features
- **Fast!** The entire site is statically generated at build time, so you can expect instant load times
- **Secure!** Every API request to backend services goes through a proxy server, so your API keys are never exposed to the frontend client.
- Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6
- Supports all Raspberry Pi's, most SBCs & Apple Silicon
- Full i18n support with translations for Catalan, Chinese, Dutch, Finnish, French, German, Hebrew, Hungarian, Malay, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romanian, Russian, Spanish, Swedish and Yue
- Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/)
- Service & Web Bookmarks
- Docker Integration
- Container status (Running / Stopped) & statistics (CPU, Memory, Network)
- Automatic service discovery (via labels)
- Service Integration
- Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli, Plex and more
- Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent and more
- Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server, Authentik, Proxmox and more
- Information Providers
- Coin Market Cap, Mastodon and more
- Information & Utility Widgets
- System Stats (Disk, CPU, Memory)
- Weather via [OpenWeatherMap](https://openweathermap.org/) or [Open-Meteo](https://open-meteo.com/)
- Web Search Bar
- UniFi Console, Glances and more
- Instant "Quick-launch" search
- Customizable
- 21 theme colors with light and dark mode support
- Background image support
- Column and Row layout options
With features like quick search, bookmarks, weather support, a wide range of integrations and widgets, an elegant and modern design, and a focus on performance, Homepage is your ideal start to the day and a handy companion throughout it.
## Support & Suggestions
- **Fast** - The site is statically generated at build time for instant load times.
- **Secure** - All API requests to backend services are proxied, keeping your API keys hidden. Constantly reviewed for security by the community.
- **For Everyone** - Images built for AMD64, ARM64, ARMv7, and ARMv6.
- **Full i18n** - Support for over 40 languages.
- **Service & Web Bookmarks** - Add custom links to the homepage.
- **Docker Integration** - Container status and stats. Automatic service discovery via labels.
- **Service Integration** - Over 100 service integrations, including popular starr and self-hosted apps.
- **Information & Utility Widgets** - Weather, time, date, search, and more.
- **And much more...**
If you have any questions, suggestions, or general issues, please start a discussion on the [Discussions](https://github.com/benphelps/homepage/discussions) page.
## Docker Integration
For bug reports, please open an issue on the [Issues](https://github.com/benphelps/homepage/issues) page.
Homepage has built-in support for Docker, and can automatically discover and add services to the homepage based on labels. See the [Docker](https://gethomepage.dev/en/installation/docker/) page for more information.
## Getting Started
## Service Widgets
For configuration options, examples and more, [please check out the homepage site](http://gethomepage.dev).
Homepage also has support for over 100 3rd party services, including all popular starr apps, and most popular self-hosted apps. Some examples include: Radarr, Sonarr, Lidarr, Bazarr, Ombi, Tautulli, Plex, Jellyfin, Emby, Transmission, qBittorrent, Deluge, Jackett, NZBGet, SABnzbd, etc. As well as service integrations, Homepage also has a number of information providers, sourcing information from a variety of external 3rd party APIs. See the [Service](https://gethomepage.dev/en/configs/service-widgets/) page for more information.
### With Docker
## Information Widgets
Homepage has built-in support for a number of information providers, including weather, time, date, search, glances and more. System and status information presented at the top of the page. See the [Information Providers](https://gethomepage.dev/en/configs/widgets/) page for more information.
## Customization
Homepage is highly customizable, with support for custom themes, custom CSS & JS, custom layouts, formatting, localization and more. See the [Settings](https://gethomepage.dev/en/configs/settings/) page for more information.
# Getting Started
For configuration options, examples and more, [please check out the homepage documentation](http://gethomepage.dev).
## With Docker
Using docker compose:
@@ -80,22 +67,31 @@ services:
homepage:
image: ghcr.io/benphelps/homepage:latest
container_name: homepage
environment:
PUID: 1000 -- optional, your user id
PGID: 1000 -- optional, your group id
ports:
- 3000:3000
volumes:
- /path/to/config:/app/config # Make sure your local config directory exists
- /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations
# user: 1000:1000 optional, not compatibile with direct socket see https://gethomepage.dev/en/configs/docker/#using-socket-directly
- /var/run/docker.sock:/var/run/docker.sock:ro # optional, for docker integrations
restart: unless-stopped
```
or docker run:
```bash
docker run -p 3000:3000 -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/benphelps/homepage:latest
docker run --name homepage \
-e PUID=1000 \
-e PGID=1000 \
-p 3000:3000 \
-v /path/to/config:/app/config \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--restart unless-stopped \
ghcr.io/benphelps/homepage:latest
```
### With Node
## With Node
First, clone the repository:
@@ -112,22 +108,23 @@ pnpm build
If this is your first time starting, copy the `src/skeleton` directory to `config/` to populate initial example config files.
Finally, run the server:
Finally, run the server in production mode:
```bash
pnpm start
```
## Configuration
or development mode:
Configuration files will be generated and placed on the first request.
```bash
pnpm dev
```
Configuration is done in the /config directory using .yaml files. Refer to each config for
the specific configuration options.
# Configuration
You may also check [the homepage site](http://gethomepage.dev) for detailed configuration instructions, examples and more.
Please refere to the [homepage documentation](https://gethomepage.dev/) website for more information. Everything you need to know about configuring Homepage is there. Please read everything carefully before asking for help, as most questions are answered there or are simple YAML configuration issues.
## Development
# Development
Install NPM packages, this project uses [pnpm](https://pnpm.io/) (and so should you!):
@@ -145,19 +142,14 @@ Open [http://localhost:3000](http://localhost:3000) to start.
This is a [Next.js](https://nextjs.org/) application, see their documentation for more information:
## Contributors
# Support & Suggestions
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
If you have any questions, suggestions, or general issues, please start a discussion on the [Discussions](https://github.com/benphelps/homepage/discussions) page.
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
For bug reports, please open an issue on the [Issues](https://github.com/benphelps/homepage/issues) page.
<!-- ALL-CONTRIBUTORS-LIST:END -->
## Contributing & Contributers
Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information.
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
Thanks to the over 200 contributors who have helped make this project what it is today!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

After

Width:  |  Height:  |  Size: 734 KiB

View File

@@ -36,8 +36,8 @@ options:
switchCurrentContext: false
runtime:
gpuRequest: ""
serversMemory: "1024Mi"
agentsMemory: "1024Mi"
serversMemory: "1024MiB"
agentsMemory: "1024MiB"
labels:
- label: foo=bar
nodeFilters:

68
package-lock.json generated
View File

@@ -14,7 +14,7 @@
"compare-versions": "^5.0.1",
"dockerode": "^3.3.4",
"follow-redirects": "^1.15.2",
"gamedig": "^4.0.6",
"gamedig": "^4.1.0",
"i18next": "^21.9.2",
"js-yaml": "^4.1.0",
"json-rpc-2.0": "^1.4.1",
@@ -769,14 +769,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
"engines": {
"node": ">=0.4.2"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -1503,29 +1495,6 @@
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.3.tgz",
"integrity": "sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A=="
},
"node_modules/compressjs": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/compressjs/-/compressjs-1.0.3.tgz",
"integrity": "sha512-jpKJjBTretQACTGLNuvnozP1JdP2ZLrjdGdBgk/tz1VfXlUcBhhSZW6vEsuThmeot/yjvSrPQKEgfF3X2Lpi8Q==",
"dependencies": {
"amdefine": "~1.0.0",
"commander": "~2.8.1"
},
"bin": {
"compressjs": "bin/compressjs"
}
},
"node_modules/compressjs/node_modules/commander": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
"integrity": "sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ==",
"dependencies": {
"graceful-readlink": ">= 1.0.0"
},
"engines": {
"node": ">= 0.6.x"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2977,18 +2946,18 @@
}
},
"node_modules/gamedig": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/gamedig/-/gamedig-4.0.6.tgz",
"integrity": "sha512-h0k9n/e5vNrd9Mh2wyFUp2Vo7ABWbDkdBxKC6FNJLOZiU5d9Z29bntGeYbXtOkcRWoV6Q63wSAJ3jLWxYQkpZw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/gamedig/-/gamedig-4.1.0.tgz",
"integrity": "sha512-jvLUEakihJgpiw9t9yQRsbcemeALeTNlnaWY1gvYdwI63ZlkxznTaLqX5K/eluRTTCtAWNW3YceT6NVjyAZIwA==",
"dependencies": {
"cheerio": "^1.0.0-rc.10",
"compressjs": "^1.0.2",
"gbxremote": "^0.2.1",
"got": "^12.0.3",
"got": "^12.1.0",
"iconv-lite": "^0.6.3",
"long": "^5.2.0",
"minimist": "^1.2.6",
"punycode": "^2.1.1",
"seek-bzip": "^2.0.0",
"varint": "^6.0.0"
},
"bin": {
@@ -3190,11 +3159,6 @@
"url": "https://github.com/sindresorhus/got?sponsor=1"
}
},
"node_modules/graceful-readlink": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
"integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w=="
},
"node_modules/grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
@@ -5586,6 +5550,26 @@
"loose-envify": "^1.1.0"
}
},
"node_modules/seek-bzip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-2.0.0.tgz",
"integrity": "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==",
"dependencies": {
"commander": "^6.0.0"
},
"bin": {
"seek-bunzip": "bin/seek-bunzip",
"seek-table": "bin/seek-bzip-table"
}
},
"node_modules/seek-bzip/node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"engines": {
"node": ">= 6"
}
},
"node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",

View File

@@ -16,7 +16,7 @@
"compare-versions": "^5.0.1",
"dockerode": "^3.3.4",
"follow-redirects": "^1.15.2",
"gamedig": "^4.0.6",
"gamedig": "^4.1.0",
"i18next": "^21.9.2",
"js-yaml": "^4.1.0",
"json-rpc-2.0": "^1.4.1",

46
pnpm-lock.yaml generated
View File

@@ -24,8 +24,8 @@ dependencies:
specifier: ^1.15.2
version: 1.15.2
gamedig:
specifier: ^4.0.6
version: 4.0.6
specifier: ^4.1.0
version: 4.1.0
i18next:
specifier: ^21.9.2
version: 21.10.0
@@ -602,11 +602,6 @@ packages:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
/amdefine@1.0.1:
resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==}
engines: {node: '>=0.4.2'}
dev: false
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -1002,28 +997,18 @@ packages:
delayed-stream: 1.0.0
dev: false
/commander@2.8.1:
resolution: {integrity: sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ==}
engines: {node: '>= 0.6.x'}
dependencies:
graceful-readlink: 1.0.1
dev: false
/commander@4.1.1:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
dev: true
/compare-versions@5.0.3:
resolution: {integrity: sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==}
/commander@6.2.1:
resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==}
engines: {node: '>= 6'}
dev: false
/compressjs@1.0.3:
resolution: {integrity: sha512-jpKJjBTretQACTGLNuvnozP1JdP2ZLrjdGdBgk/tz1VfXlUcBhhSZW6vEsuThmeot/yjvSrPQKEgfF3X2Lpi8Q==}
hasBin: true
dependencies:
amdefine: 1.0.1
commander: 2.8.1
/compare-versions@5.0.3:
resolution: {integrity: sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==}
dev: false
/concat-map@0.0.1:
@@ -1972,19 +1957,19 @@ packages:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
dev: true
/gamedig@4.0.6:
resolution: {integrity: sha512-h0k9n/e5vNrd9Mh2wyFUp2Vo7ABWbDkdBxKC6FNJLOZiU5d9Z29bntGeYbXtOkcRWoV6Q63wSAJ3jLWxYQkpZw==}
/gamedig@4.1.0:
resolution: {integrity: sha512-jvLUEakihJgpiw9t9yQRsbcemeALeTNlnaWY1gvYdwI63ZlkxznTaLqX5K/eluRTTCtAWNW3YceT6NVjyAZIwA==}
engines: {node: '>=14.0.0'}
hasBin: true
dependencies:
cheerio: 1.0.0-rc.12
compressjs: 1.0.3
gbxremote: 0.2.1
got: 12.6.1
iconv-lite: 0.6.3
long: 5.2.3
minimist: 1.2.8
punycode: 2.3.0
seek-bzip: 2.0.0
varint: 6.0.0
dev: false
@@ -2121,10 +2106,6 @@ packages:
responselike: 3.0.0
dev: false
/graceful-readlink@1.0.1:
resolution: {integrity: sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==}
dev: false
/grapheme-splitter@1.0.4:
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
dev: true
@@ -3584,6 +3565,13 @@ packages:
loose-envify: 1.4.0
dev: false
/seek-bzip@2.0.0:
resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==}
hasBin: true
dependencies:
commander: 6.2.1
dev: false
/semver@6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
dev: true

View File

@@ -316,7 +316,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "مفضلة",
@@ -718,5 +719,19 @@
"series": "Series",
"books": "Books",
"authors": "Authors"
},
"uptimerobot": {
"seemsdown": "Seems Down",
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -13,7 +13,7 @@
"missing_type": "Липсваща приставка: {{type}}",
"api_error": "API Грешка",
"status": "Статус",
"information": "Information",
"information": "Информация",
"url": "URL",
"raw_error": "Raw Error",
"response_data": "Response Data"
@@ -28,7 +28,7 @@
"placeholder": "Търсене…"
},
"resources": {
"cpu": "CPU",
"cpu": "Процесор",
"total": "Общо",
"free": "Свободни",
"used": "Заети",
@@ -54,9 +54,9 @@
"wait": "Моля изчакайте",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Devices",
"lan_devices": "LAN Devices",
"wlan_devices": "WLAN Devices",
"devices": "Устройства",
"lan_devices": "LAN Устройства",
"wlan_devices": "WLAN Устройства",
"empty_data": "Subsystem status unknown"
},
"docker": {
@@ -64,8 +64,8 @@
"rx": "RX",
"tx": "TX",
"mem": "MEM",
"cpu": "CPU",
"error": "Error",
"cpu": "Процесор",
"error": "Грешка",
"unknown": "Unknown",
"partial": "Partial",
"running": "Running",
@@ -125,7 +125,7 @@
"radarr": {
"wanted": "Wanted",
"queued": "Queued",
"movies": "Movies",
"movies": "Филми",
"missing": "Missing",
"queue": "Queue",
"unknown": "Unknown"
@@ -138,38 +138,38 @@
"readarr": {
"wanted": "Wanted",
"queued": "Queued",
"books": "Books"
"books": "Книги"
},
"bazarr": {
"missingEpisodes": "Missing Episodes",
"missingMovies": "Missing Movies"
"missingEpisodes": "Липсващи Епизоди",
"missingMovies": "Липсващи Филми"
},
"ombi": {
"pending": "Pending",
"approved": "Approved",
"available": "Available"
"approved": "Одобрен",
"available": "Наличен"
},
"jellyseerr": {
"pending": "Pending",
"approved": "Approved",
"available": "Available"
"approved": "Одобрен",
"available": "Наличен"
},
"overseerr": {
"pending": "Pending",
"approved": "Approved",
"available": "Available",
"approved": "Одобрен",
"available": "Наличен",
"processing": "Processing"
},
"pihole": {
"queries": "Queries",
"blocked": "Blocked",
"queries": "Заявки",
"blocked": "Блокирани",
"gravity": "Gravity",
"blocked_percent": "Blocked %"
},
"adguard": {
"queries": "Queries",
"blocked": "Blocked",
"filtered": "Filtered",
"blocked": "Блокирани",
"filtered": "Филтрирани",
"latency": "Latency"
},
"speedtest": {
@@ -179,7 +179,7 @@
},
"portainer": {
"running": "Running",
"stopped": "Stopped",
"stopped": "Спрян",
"total": "Total"
},
"traefik": {
@@ -188,15 +188,15 @@
"middleware": "Middleware"
},
"npm": {
"enabled": "Enabled",
"disabled": "Disabled",
"enabled": "Активирано",
"disabled": "Деактивирано",
"total": "Total"
},
"coinmarketcap": {
"configure": "Configure one or more crypto currencies to track",
"1hour": "1 Hour",
"1day": "1 Day",
"7days": "7 Days",
"1hour": "1 Час",
"1day": "1 Ден",
"7days": "7 Дена",
"30days": "30 Days"
},
"gotify": {
@@ -254,22 +254,23 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
"diffsDetected": "Diffs Detected"
},
"wmo": {
"0-day": "Sunny",
"0-day": "Слънчево",
"57-day": "Freezing Drizzle",
"57-night": "Freezing Drizzle",
"96-day": "Thunderstorm With Hail",
"96-night": "Thunderstorm With Hail",
"0-night": "Clear",
"1-day": "Mainly Sunny",
"1-night": "Mainly Clear",
"2-day": "Partly Cloudy",
"0-night": "Ясно",
"1-day": "Предимно Слънчево",
"1-night": "Предимно Ясно",
"2-day": "Частична Облачност",
"2-night": "Partly Cloudy",
"3-day": "Cloudy",
"3-night": "Cloudy",
@@ -362,7 +363,7 @@
},
"navidrome": {
"nothing_streaming": "No Active Streams",
"please_wait": "Please Wait"
"please_wait": "Моля Изчакайте"
},
"pyload": {
"speed": "Speed",
@@ -381,7 +382,7 @@
},
"ping": {
"ping": "Ping",
"error": "Error"
"error": "Грешка"
},
"scrutiny": {
"passed": "Passed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total d'observats",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -328,7 +328,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Záložka",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -10,13 +10,13 @@
"movies": "Film",
"wanted": "Ønskede",
"missing": "Mangler",
"queue": "Queue",
"unknown": "Unknown"
"queue": "",
"unknown": "Ukendt"
},
"lidarr": {
"wanted": "Ønsket",
"queued": "I Kø",
"artists": "Artists"
"artists": "Artister"
},
"jellyseerr": {
"available": "Tilgængelig",
@@ -27,13 +27,13 @@
"pending": "Afventer",
"approved": "Godkendt",
"available": "Tilgængelig",
"processing": "Processing"
"processing": "Behandler"
},
"adguard": {
"queries": "Forespørgsler",
"blocked": "Blokerede",
"filtered": "Filtreret",
"latency": "Latency"
"latency": "Latenstid"
},
"speedtest": {
"upload": "Upload",
@@ -48,7 +48,7 @@
"coinmarketcap": {
"30days": "30 Dage",
"1day": "1 Dag",
"configure": "Konfigurer en eller flere crypto valutaer til tracking",
"configure": "Konfigurer en eller flere crypto valutaer til tracking",
"7days": "7 Dage",
"1hour": "1 time"
},
@@ -73,67 +73,68 @@
"wait": "Vent venligst",
"uptime": "UP",
"days": "d",
"hours": "h",
"hours": "t",
"temp": "TEMP",
"load": "Load",
"warn": "Warn",
"warn": "Advar",
"total": "Total",
"free": "Free",
"used": "Used",
"free": "Ledig",
"used": "Brugt",
"crit": "Crit",
"read": "Read",
"write": "Write",
"read": "Læs",
"write": "Skriv",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"mem": "Ram",
"swap": "Swap",
"_temp": "Temp"
},
"wmo": {
"1-day": "Hovedsageligt solrigt",
"1-day": "Overvejende Solrigt",
"48-day": "Tåget",
"48-night": "Tåget",
"51-day": "Let støvregn",
"51-night": "Let støvregn",
"66-night": "Frysende regn",
"67-day": "Frysende regn",
"67-night": "Frysende regn",
"51-day": "Let Støvregn",
"51-night": "Let Støvregn",
"66-night": "Frysende Regn",
"67-day": "Frysende Regn",
"67-night": "Frysende Regn",
"71-day": "Let Sne",
"75-night": "Kraftig Sne",
"86-day": "Snebyger",
"86-night": "Snebyger",
"95-day": "Tordenvejr",
"99-day": "Tordenvejr med hagl",
"99-night": "Tordenvejr med hagl",
"99-day": "Tordenvejr Med Hagl",
"99-night": "Tordenvejr Med Hagl",
"0-day": "Solrig",
"0-night": "Klart",
"1-night": "Hovedsageligt klart",
"2-day": "Delvist skyet",
"2-night": "Delvist skyet",
"1-night": "Overvejende Skyfrit",
"2-day": "Delvist Overskyet",
"2-night": "Delvist Overskyet",
"3-day": "Skyet",
"3-night": "Skyet",
"45-day": "Tåget",
"65-day": "Kraftig regn",
"65-night": "Kraftig regn",
"65-day": "Kraftig Regn",
"65-night": "Kraftig Regn",
"45-night": "Tåget",
"53-day": "Støvregn",
"53-night": "Støvregn",
"55-day": "Kraftig støvregn",
"55-night": "Kraftig støvregn",
"56-day": "Let frysende støvregn",
"56-night": "Let frysende støvregn",
"57-day": "Frysende støvregn",
"57-night": "Frysende støvregn",
"55-day": "Kraftig Støvregn",
"55-night": "Kraftig Støvregn",
"56-day": "Let Frysende Støvregn",
"56-night": "Let Frysende Støvregn",
"57-day": "Frysende Støvregn",
"57-night": "Frysende Støvregn",
"61-day": "Let Regn",
"61-night": "Let Regn",
"63-day": "Regn",
"63-night": "Regn",
"66-day": "Frysende regn",
"66-day": "Frysende Regn",
"71-night": "Let Sne",
"73-day": "Sne",
"73-night": "Sne",
"75-day": "Kraftig Sne",
"77-day": "Snekorn",
"80-day": "Lette byger",
"80-night": "Lette byger",
"80-day": "Lette Byger",
"80-night": "Lette Byger",
"81-day": "Byger",
"77-night": "Snekorn",
"81-night": "Byger",
@@ -142,19 +143,19 @@
"85-day": "Snebyger",
"85-night": "Snebyger",
"95-night": "Tordenvejr",
"96-day": "Tordenvejr med hagl",
"96-night": "Tordenvejr med hagl"
"96-day": "Tordenvejr Med Hagl",
"96-night": "Tordenvejr Med Hagl"
},
"homebridge": {
"available_update": "System",
"updates": "Opdateringer",
"update_available": "Opdateringer tilgængelige",
"update_available": "Opdateringer Tilgængelige",
"up_to_date": "Opdateret",
"child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}",
"up": "Up",
"pending": "Pending",
"down": "Down"
"up": "Oppe",
"pending": "Afventer",
"down": "Nede"
},
"widget": {
"missing_type": "Manglende Widget Type: {{type}}",
@@ -162,8 +163,8 @@
"status": "Status",
"information": "Information",
"url": "URL",
"raw_error": "Raw Error",
"response_data": "Response Data"
"raw_error": "Rå Fejl",
"response_data": "Svardata"
},
"weather": {
"current": "Nuværende lokation",
@@ -180,13 +181,13 @@
"free": "Fri",
"used": "Brugt",
"load": "Belastning",
"mem": "MEM",
"hours": "h",
"mem": "RAM",
"hours": "t",
"minutes": "m",
"temp": "TEMP",
"max": "Max",
"uptime": "UP",
"months": "mo",
"months": "mdr",
"days": "d"
},
"unifi": {
@@ -204,7 +205,7 @@
"up": "Oppe",
"down": "NED",
"wait": "Vent venligst",
"empty_data": "Subsystem status unknown"
"empty_data": "Subsystem status ukendt"
},
"docker": {
"cpu": "CPU",
@@ -213,24 +214,24 @@
"mem": "RAM",
"offline": "Offline",
"error": "Error",
"unknown": "Unknown",
"running": "Running",
"starting": "Starting",
"unhealthy": "Unhealthy",
"not_found": "Not Found",
"exited": "Exited",
"partial": "Partial",
"healthy": "Healthy"
"unknown": "Ukendt",
"running": "Kører",
"starting": "Starter",
"unhealthy": "Usund",
"not_found": "Ikke Fundet",
"exited": "Forladt",
"partial": "Delvis",
"healthy": "Sund"
},
"emby": {
"playing": "Afspiller",
"transcoding": "Transcoder",
"bitrate": "Bitrate",
"no_active": "Ingen Aktive Streams",
"movies": "Movies",
"series": "Series",
"episodes": "Episodes",
"songs": "Songs"
"movies": "Film",
"series": "Serier",
"episodes": "Episoder",
"songs": "Sange"
},
"changedetectionio": {
"totalObserved": "Total Observeret",
@@ -241,7 +242,7 @@
"transcoding": "Transcoder",
"bitrate": "Bitrate",
"no_active": "Ingen Aktive Streams",
"plex_connection_error": "Check Plex Connection"
"plex_connection_error": "Tjek Plex-forbindelse"
},
"nzbget": {
"rate": "Rate",
@@ -274,8 +275,8 @@
"wanted": "Ønsket",
"queued": "I Kø",
"series": "Serier",
"queue": "Queue",
"unknown": "Unknown"
"queue": "",
"unknown": "Ukendt"
},
"readarr": {
"wanted": "Ønskede",
@@ -295,7 +296,7 @@
"blocked": "Blokerede",
"gravity": "Gravity",
"queries": "Forespørgsler",
"blocked_percent": "Blocked %"
"blocked_percent": "Blokeret %"
},
"portainer": {
"running": "Kørende",
@@ -316,8 +317,8 @@
"enableIndexers": "Indeksører",
"numberOfGrabs": "Grabs",
"numberOfQueries": "Forespørgsler",
"numberOfFailGrabs": "Fail Grabs",
"numberOfFailQueries": "Fejl forespørgsler"
"numberOfFailGrabs": "Fejl Grabs",
"numberOfFailQueries": "Fejl Forespørgsler"
},
"jackett": {
"configured": "Konfigureret",
@@ -332,9 +333,9 @@
"quicklaunch": {
"bookmark": "Bogmærker",
"service": "Service",
"search": "Search",
"custom": "Custom",
"visit": "Visit",
"search": "Søg",
"custom": "Brugerdefinerede",
"visit": "Besøg",
"url": "URL"
},
"watchtower": {
@@ -371,25 +372,25 @@
"total": "Total"
},
"gluetun": {
"public_ip": "Public IP",
"public_ip": "Offentlig IP",
"region": "Region",
"country": "Country"
"country": "Land"
},
"hdhomerun": {
"channels": "Channels",
"channels": "Kanaler",
"hd": "HD"
},
"ping": {
"error": "Error",
"error": "Fejl",
"ping": "Ping"
},
"scrutiny": {
"passed": "Passed",
"failed": "Failed",
"unknown": "Unknown"
"passed": "Bestået",
"failed": "Mislykket",
"unknown": "Ukendt"
},
"paperlessngx": {
"inbox": "Inbox",
"inbox": "Indbakke",
"total": "Total"
},
"deluge": {
@@ -405,29 +406,29 @@
"seed": "Seed"
},
"tdarr": {
"queue": "Queue",
"processed": "Processed",
"errored": "Errored",
"saved": "Saved"
"queue": "",
"processed": "Behandlet",
"errored": "Fejlet",
"saved": "Gemt"
},
"miniflux": {
"read": "Read",
"unread": "Unread"
"read": "Læst",
"unread": "Ulæst"
},
"nextdns": {
"wait": "Please Wait",
"no_devices": "No Device Data Received"
"wait": "Vent Venligst",
"no_devices": "Ingen Enhedsdata Modtaget"
},
"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"
"connectedAp": "Forbundne APs",
"activeUser": "Aktive enheder",
"alerts": "Advarsler",
"connectedGateway": "Forbundne gateways",
"connectedSwitches": "Forbundne switches"
},
"downloadstation": {
"download": "Download",
@@ -436,238 +437,238 @@
"seed": "Seed"
},
"mikrotik": {
"cpuLoad": "CPU Load",
"memoryUsed": "Memory Used",
"uptime": "Uptime",
"cpuLoad": "CPU Belastning",
"memoryUsed": "Hukommelse Brugt",
"uptime": "Oppetid",
"numberOfLeases": "Leases"
},
"xteve": {
"streams_all": "All Streams",
"streams_active": "Active Streams",
"streams_xepg": "XEPG Channels"
"streams_all": "Alle Streams",
"streams_active": "Aktive Streams",
"streams_xepg": "XEPG Kanaler"
},
"opnsense": {
"cpu": "CPU Load",
"memory": "Active Memory",
"cpu": "CPU Belastning",
"memory": "Aktiv Hukommelse",
"wanUpload": "WAN Upload",
"wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"printer_state": "Printer Tilstand",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
"print_progress": "Fremskridt",
"layers": "Lag"
},
"medusa": {
"wanted": "Wanted",
"queued": "Queued",
"series": "Series"
"wanted": "Ønskede",
"queued": "I Kø",
"series": "Serier"
},
"octoprint": {
"printer_state": "Status",
"temp_tool": "Tool temp",
"temp_bed": "Bed temp",
"job_completion": "Completion"
"job_completion": "Færdiggørelse"
},
"cloudflared": {
"origin_ip": "Origin IP",
"origin_ip": "Oprindelses-IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"datastore_usage": "Datalager",
"failed_tasks_24h": "Mislykkede Opgaver 24t",
"cpu_usage": "CPU",
"memory_usage": "Memory"
"memory_usage": "Hukommelse"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
"users": "Brugere",
"photos": "Billeder",
"videos": "Videoer",
"storage": "Lager"
},
"uptimekuma": {
"up": "Sites Up",
"down": "Sites Down",
"uptime": "Uptime",
"incident": "Incident",
"up": "Sider Oppe",
"down": "Sider Nede",
"uptime": "Oppetid",
"incident": "Hændelse",
"m": "m"
},
"komga": {
"libraries": "Libraries",
"series": "Series",
"books": "Books"
"libraries": "Biblioteker",
"series": "Serier",
"books": "Bøger"
},
"mylar": {
"series": "Series",
"issues": "Issues",
"wanted": "Wanted"
"series": "Serier",
"issues": "Problemer",
"wanted": "Ønskede"
},
"photoprism": {
"albums": "Albums",
"photos": "Photos",
"videos": "Videos",
"people": "People"
"photos": "Billeder",
"videos": "Videoer",
"people": "Mennesker"
},
"diskstation": {
"days": "Days",
"uptime": "Uptime",
"volumeAvailable": "Available"
"days": "Dage",
"uptime": "Oppetid",
"volumeAvailable": "Tilgængelig"
},
"fileflows": {
"queue": "Queue",
"processing": "Processing",
"processed": "Processed",
"time": "Time"
"queue": "",
"processing": "Behandler",
"processed": "Behandlet",
"time": "Tid"
},
"grafana": {
"totalalerts": "Total Alerts",
"totalalerts": "Totale Advarsler",
"dashboards": "Dashboards",
"datasources": "Data Sources",
"alertstriggered": "Alerts Triggered"
"datasources": "Data Kilder",
"alertstriggered": "Advarsler Udløst"
},
"nextcloud": {
"memoryusage": "Memory Usage",
"cpuload": "Cpu Load",
"freespace": "Free Space",
"activeusers": "Active Users",
"numfiles": "Files",
"numshares": "Shared Items"
"memoryusage": "Hukommelse Forbrug",
"cpuload": "Cpu Belastning",
"freespace": "Ledig Plads",
"activeusers": "Aktive Brugere",
"numfiles": "Filer",
"numshares": "Delte Genstande"
},
"kopia": {
"status": "Status",
"size": "Size",
"lastrun": "Last Run",
"nextrun": "Next Run",
"failed": "Failed"
"size": "Størrelse",
"lastrun": "Sidst Kørt",
"nextrun": "Næste Kørsel",
"failed": "Mislykket"
},
"unmanic": {
"active_workers": "Active Workers",
"total_workers": "Total Workers",
"records_total": "Queue Length"
"active_workers": "Aktive Arbejdere",
"total_workers": "Totale Arbejdere",
"records_total": " Længde"
},
"healthchecks": {
"new": "New",
"new": "Ny",
"up": "Online",
"grace": "In Grace Period",
"down": "Offline",
"paused": "Paused",
"paused": "Pause",
"status": "Status",
"last_ping": "Last Ping",
"never": "No pings yet"
"last_ping": "Sidste Ping",
"never": "Ingen Pings Endnu"
},
"pterodactyl": {
"servers": "Servers",
"nodes": "Nodes"
"servers": "Servere",
"nodes": "Noder"
},
"prometheus": {
"targets_up": "Targets Up",
"targets_down": "Targets Down",
"targets_total": "Total Targets"
"targets_up": "Mål Oppe",
"targets_down": "Mål Nede",
"targets_total": "Totale Mål"
},
"minecraft": {
"players": "Players",
"players": "Afspillere",
"version": "Version",
"status": "Status",
"up": "Online",
"down": "Offline"
},
"ghostfolio": {
"gross_percent_today": "Today",
"gross_percent_1y": "One year",
"gross_percent_max": "All time"
"gross_percent_today": "I Dag",
"gross_percent_1y": "Et År",
"gross_percent_max": "Altid"
},
"audiobookshelf": {
"booksDuration": "Duration",
"booksDuration": "Varighed",
"podcasts": "Podcasts",
"books": "Books",
"podcastsDuration": "Duration"
"books": "Bøger",
"podcastsDuration": "Varighed"
},
"homeassistant": {
"people_home": "People Home",
"lights_on": "Lights On",
"switches_on": "Switches On"
"people_home": "Personer Hjemme",
"lights_on": "Lys Tændt",
"switches_on": "Kontakter Tændt"
},
"freshrss": {
"subscriptions": "Subscriptions",
"unread": "Unread"
"subscriptions": "Abonnementer",
"unread": "Ulæst"
},
"channelsdvrserver": {
"shows": "Shows",
"recordings": "Recordings",
"scheduled": "Scheduled",
"recordings": "Optagelser",
"scheduled": "Planlagt",
"passes": "Passes"
},
"whatsupdocker": {
"monitoring": "Monitoring",
"updates": "Updates"
"monitoring": "Overvåger",
"updates": "Opdateringer"
},
"tailscale": {
"address": "Address",
"expires": "Expires",
"now": "Now",
"address": "Adresse",
"expires": "Udløber",
"now": "Nu",
"years": "{{number}}y",
"weeks": "{{number}}w",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"never": "Never",
"last_seen": "Last Seen",
"ago": "{{value}} Ago"
"never": "Aldrig",
"last_seen": "Sidst Set",
"ago": "{{value}} Siden"
},
"qnap": {
"cpuUsage": "CPU Usage",
"memUsage": "MEM Usage",
"cpuUsage": "CPU Forbrug",
"memUsage": "MEM Forbrug",
"systemTempC": "System Temp",
"poolUsage": "Pool Usage",
"volumeUsage": "Volume Usage",
"invalid": "Invalid"
"poolUsage": "Pool Forbrug",
"volumeUsage": "Volume Forbrug",
"invalid": "Ugyldig"
},
"pfsense": {
"load": "Load Avg",
"memory": "Mem Usage",
"load": "Belastning Gns",
"memory": "Hukommelse Forbrug",
"wanStatus": "WAN Status",
"up": "Up",
"down": "Down",
"up": "Op",
"down": "Ned",
"temp": "Temp",
"disk": "Disk Usage",
"disk": "Disk Forbrug",
"wanIP": "WAN IP"
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Current requests",
"requests_failed": "Failed requests"
"requests": "Aktuelle anmodninger",
"requests_failed": "Mislykkede anmodninger"
},
"evcc": {
"pv_power": "Production",
"battery_soc": "Battery",
"grid_power": "Grid",
"home_power": "Consumption",
"charge_power": "Charger",
"pv_power": "Produktion",
"battery_soc": "Batteri",
"grid_power": "Gitter",
"home_power": "Forbrug",
"charge_power": "Oplader",
"watt_hour": "Wh"
},
"pialert": {
"total": "Total",
"connected": "Connected",
"new_devices": "New Devices",
"down_alerts": "Down Alerts"
"connected": "Forbundet",
"new_devices": "Nye Enheder",
"down_alerts": "Nedadvarsler"
},
"jdownloader": {
"downloadSpeed": "Download Speed",
"downloadCount": "Queue Count",
"downloadBytesRemaining": "Remaining",
"downloadTotalBytes": "Size"
"downloadSpeed": "Hastighed",
"downloadCount": "",
"downloadBytesRemaining": "Tilbage",
"downloadTotalBytes": "Størrelse"
},
"kavita": {
"seriesCount": "Series",
"totalFiles": "Files"
"seriesCount": "Serier",
"totalFiles": "Filer"
},
"gamedig": {
"name": "Name",
"map": "Map",
"currentPlayers": "Current players",
"players": "Players",
"maxPlayers": "Max players",
"name": "Navn",
"map": "Kort",
"currentPlayers": "Nuværende Spillere",
"players": "Spillere",
"maxPlayers": "Maks spillere",
"bots": "Bots",
"ping": "Ping",
"status": "Status",
@@ -675,48 +676,62 @@
"offline": "Offline"
},
"azuredevops": {
"result": "Result",
"result": "Resultat",
"status": "Status",
"buildId": "Build ID",
"succeeded": "Succeeded",
"notStarted": "Not Started",
"failed": "Failed",
"canceled": "Canceled",
"inProgress": "In Progress",
"succeeded": "Lykkedes",
"notStarted": "Ikke Startet",
"failed": "Mislykket",
"canceled": "Annulleret",
"inProgress": "I Gang",
"totalPrs": "Total PRs",
"myPrs": "My PRs",
"approved": "Approved"
"myPrs": "Mine PRs",
"approved": "Godkendt"
},
"urbackup": {
"ok": "Ok",
"errored": "Errors",
"noRecent": "Out of Date",
"totalUsed": "Used Storage"
"errored": "Fejl",
"noRecent": "Uddateret",
"totalUsed": "Brugt Lager"
},
"openmediavault": {
"downloading": "Downloading",
"downloading": "Downloader",
"total": "Total",
"running": "Running",
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
"running": "Kører",
"stopped": "Stoppet",
"passed": "Gennemført",
"failed": "Mislykket"
},
"mealie": {
"recipes": "Recipes",
"users": "Users",
"categories": "Categories",
"recipes": "Opskrifter",
"users": "Brugere",
"categories": "Kategorier",
"tags": "Tags"
},
"atsumeru": {
"series": "Series",
"archives": "Archives",
"chapters": "Chapters",
"categories": "Categories"
"series": "Serier",
"archives": "Arkiver",
"chapters": "Kapitler",
"categories": "Kategorier"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
"books": "Bøger",
"authors": "Forfattere",
"categories": "Kategorier",
"series": "Serier"
},
"uptimerobot": {
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -34,7 +34,7 @@
"offline": "Offline",
"error": "Fehler",
"unknown": "Unbekannt",
"running": "Laufend",
"running": "Wird ausgeführt",
"starting": "Startet",
"unhealthy": "Unhealthy",
"not_found": "Nicht gefunden",
@@ -48,7 +48,7 @@
"bitrate": "Bitrate",
"no_active": "Keine aktiven Streams",
"movies": "Filme",
"series": "Serien",
"series": "Serie",
"episodes": "Folgen",
"songs": "Songs"
},
@@ -57,7 +57,7 @@
"transcoding": "Transcodierung",
"bitrate": "Bitrate",
"no_active": "Keine aktiven Streams",
"plex_connection_error": "Check Plex Connection"
"plex_connection_error": "Plex-Verbindung prüfen"
},
"rutorrent": {
"active": "Aktiv",
@@ -67,17 +67,17 @@
"sonarr": {
"wanted": "Gesucht",
"queued": "In Warteschlange",
"series": "Serien",
"queue": "Queue",
"unknown": "Unknown"
"series": "Serie",
"queue": "Warteschlange",
"unknown": "Unbekannt"
},
"radarr": {
"wanted": "Gesucht",
"queued": "In Warteschlange",
"movies": "Filme",
"missing": "Fehlt",
"queue": "Queue",
"unknown": "Unknown"
"queue": "Warteschlange",
"unknown": "Unbekannt"
},
"readarr": {
"wanted": "Gesucht",
@@ -106,7 +106,7 @@
"ping": "Ping"
},
"portainer": {
"running": "Betrieb",
"running": "Wird ausgeführt",
"stopped": "Gestoppt",
"total": "Gesamt"
},
@@ -178,7 +178,7 @@
"lidarr": {
"wanted": "Gesucht",
"queued": "In Warteschlange",
"artists": "Artists"
"artists": "Künstler"
},
"adguard": {
"queries": "Anfragen",
@@ -249,12 +249,13 @@
"total": "Gesamt",
"free": "Frei",
"used": "Verwendet",
"write": "Write",
"write": "Schreiben",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap",
"crit": "Crit",
"read": "Read"
"swap": "Auslagerung",
"crit": "Krit",
"read": "Lesen",
"_temp": "Temperatur"
},
"changedetectionio": {
"totalObserved": "Gesamt beobachtet",
@@ -438,7 +439,7 @@
"mikrotik": {
"cpuLoad": "CPU Auslastung",
"memoryUsed": "RAM Verbrauch",
"uptime": "Laufzeit",
"uptime": "Betriebszeit",
"numberOfLeases": "Leases"
},
"xteve": {
@@ -488,7 +489,7 @@
"uptimekuma": {
"up": "Seiten verfügbar",
"down": "Seiten nicht verfügbar",
"uptime": "Laufzeit",
"uptime": "Betriebszeit",
"incident": "Vorfall",
"m": "m"
},
@@ -510,7 +511,7 @@
},
"diskstation": {
"days": "Tage",
"uptime": "Laufzeit",
"uptime": "Betriebszeit",
"volumeAvailable": "Verfügbar"
},
"fileflows": {
@@ -620,7 +621,7 @@
"memUsage": "MEM Nutzung",
"systemTempC": "System Temp",
"poolUsage": "Pool Nutzung",
"volumeUsage": "Volume Usage",
"volumeUsage": "Speicher benutzung",
"invalid": "Ungültig"
},
"pfsense": {
@@ -642,7 +643,7 @@
"watt_hour": "Wh",
"pv_power": "Produktion",
"battery_soc": "Batterie",
"grid_power": "Grid",
"grid_power": "Raster",
"home_power": "Verbrauch",
"charge_power": "Ladegerät"
},
@@ -653,70 +654,84 @@
"down_alerts": "Down Alarme"
},
"jdownloader": {
"downloadCount": "Queue Count",
"downloadSpeed": "Download Speed",
"downloadBytesRemaining": "Remaining",
"downloadTotalBytes": "Size"
"downloadCount": "Warteschlange",
"downloadSpeed": "Geschwindigkeit",
"downloadBytesRemaining": "Verbleibend",
"downloadTotalBytes": "Größe"
},
"kavita": {
"seriesCount": "Series",
"totalFiles": "Files"
"seriesCount": "Serie",
"totalFiles": "Dateien"
},
"gamedig": {
"name": "Name",
"map": "Map",
"currentPlayers": "Current players",
"players": "Players",
"map": "Karte",
"currentPlayers": "Aktuelle Spieler",
"players": "Spieler",
"bots": "Bots",
"ping": "Ping",
"maxPlayers": "Max players",
"maxPlayers": "Max. Spieler",
"status": "Status",
"online": "Online",
"offline": "Offline"
},
"azuredevops": {
"result": "Result",
"result": "Ergebnis",
"status": "Status",
"buildId": "Build ID",
"succeeded": "Succeeded",
"notStarted": "Not Started",
"failed": "Failed",
"canceled": "Canceled",
"succeeded": "Erfolgreich",
"notStarted": "Nicht gestartet",
"failed": "Fehlgeschlagen",
"canceled": "Abgebrochen",
"totalPrs": "Total PRs",
"myPrs": "My PRs",
"approved": "Approved",
"inProgress": "In Progress"
"approved": "Genehmigt",
"inProgress": "In Bearbeitung"
},
"urbackup": {
"ok": "Ok",
"errored": "Errors",
"noRecent": "Out of Date",
"totalUsed": "Used Storage"
"errored": "Fehler",
"noRecent": "Nicht mehr aktuell",
"totalUsed": "Belegter Speicherplatz"
},
"openmediavault": {
"downloading": "Downloading",
"total": "Total",
"running": "Running",
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
"downloading": "Wird heruntergeladen",
"total": "Gesamt",
"running": "Wird ausgeführt",
"stopped": "Gestoppt",
"passed": "Bestanden",
"failed": "Fehlgeschlagen"
},
"mealie": {
"recipes": "Recipes",
"users": "Users",
"categories": "Categories",
"tags": "Tags"
"users": "Benutzer",
"categories": "Kategorien",
"tags": "Schlagwörter"
},
"atsumeru": {
"series": "Series",
"archives": "Archives",
"chapters": "Chapters",
"categories": "Categories"
"series": "Serie",
"archives": "Archive",
"chapters": "Kapitel",
"categories": "Kategorien"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
"books": "Bücher",
"authors": "Autoren",
"categories": "Kategorien",
"series": "Serie"
},
"uptimerobot": {
"status": "Status",
"uptime": "Betriebszeit",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Seiten verfügbar",
"sitesDown": "Seiten nicht verfügbar",
"paused": "Pausiert",
"notyetchecked": "Noch nicht geprüft",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unbekannt"
}
}

View File

@@ -375,7 +375,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -431,7 +432,7 @@
},
"pyload": {
"speed": "Speed",
"active": "Active",
"active": "Ενεργό",
"queue": "Queue",
"total": "Total"
},
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"up": "Up",
"unknown": "Unknown",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"seemsdown": "Seems Down",
"down": "Down"
}
}

View File

@@ -365,6 +365,7 @@
"load": "Load",
"wait": "Please wait",
"temp": "TEMP",
"_temp": "Temp",
"warn": "Warn",
"uptime": "UP",
"total": "Total",
@@ -727,5 +728,19 @@
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -272,7 +272,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"categories": "Categories",
"authors": "Authors",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"notyetchecked": "Not Yet Checked",
"downDuration": "Downtime Duration",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -48,7 +48,7 @@
"bitrate": "Tasa de bits",
"no_active": "Sin transmisiones activas",
"movies": "Películas",
"series": "Serie",
"series": "Series",
"episodes": "Episodios",
"songs": "Canciones"
},
@@ -234,7 +234,7 @@
"plex": {
"streams": "Transmisiones activas",
"movies": "Películas",
"tv": "Series",
"tv": "Programas de televisión",
"albums": "Álbumes"
},
"glances": {
@@ -254,7 +254,8 @@
"write": "Escribir",
"gpu": "GPU",
"mem": "Memoria",
"swap": "Intercambiar"
"swap": "Intercambiar",
"_temp": "Temperatura"
},
"changedetectionio": {
"totalObserved": "Total Observados",
@@ -461,7 +462,7 @@
"medusa": {
"wanted": "Querido",
"queued": "A la espera",
"series": "Serie"
"series": "Series"
},
"octoprint": {
"temp_bed": "Temperatura de la plataforma",
@@ -659,7 +660,7 @@
"downloadTotalBytes": "Tamaño"
},
"kavita": {
"seriesCount": "Serie",
"seriesCount": "Series",
"totalFiles": "Archivos"
},
"gamedig": {
@@ -714,9 +715,23 @@
"categories": "Categorías"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"books": "Libros",
"authors": "Autores",
"categories": "Categorías",
"series": "Series"
},
"uptimerobot": {
"status": "Estado",
"uptime": "Tiempo de actividad",
"lastDown": "Último periodo de inactividad",
"downDuration": "Tiempo de inactividad",
"sitesUp": "Páginas web con conexión",
"sitesDown": "Páginas web caídas",
"paused": "Pausado",
"notyetchecked": "Aún no verificado",
"up": "Arriba",
"seemsdown": "Parece caída",
"down": "Abajo",
"unknown": "Desconocido"
}
}

View File

@@ -437,7 +437,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"uptime": "Uptime",
"status": "Status",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Écrit.",
"gpu": "GPU",
"mem": "Mém.",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observé",
@@ -714,9 +715,23 @@
"categories": "Catégories"
},
"calibreweb": {
"series": "Series",
"books": "Books",
"authors": "Authors",
"categories": "Categories"
"series": "Séries",
"books": "Ebooks",
"authors": "Auteurs",
"categories": "Catégories"
},
"uptimerobot": {
"status": "Statut",
"uptime": "Disponibilité",
"lastDown": "Dernière interruption",
"downDuration": "Durée d'interruption",
"sitesUp": "Sites en ligne",
"sitesDown": "Sites hors ligne",
"paused": "En pause",
"notyetchecked": "Non vérifié",
"up": "En ligne",
"seemsdown": "Semble hors ligne",
"down": "Hors ligne",
"unknown": "Inconnu"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -262,7 +262,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Ukupno promatrano",
@@ -718,5 +719,19 @@
"categories": "Categories",
"series": "Series",
"authors": "Authors"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Összes Megfigyelt",
@@ -718,5 +719,19 @@
"authors": "Authors",
"series": "Series",
"categories": "Categories"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -228,7 +228,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -9,11 +9,11 @@
"unknown": "Sconosciuto",
"running": "In esecuzione",
"starting": "In avvio",
"unhealthy": "Unhealthy",
"unhealthy": "Non sano",
"not_found": "Non trovato",
"exited": "Uscito",
"partial": "Parziale",
"healthy": "Healthy"
"healthy": "Sano"
},
"emby": {
"playing": "In riproduzione",
@@ -30,7 +30,7 @@
"transcoding": "Transcodifica",
"bitrate": "Bitrate",
"no_active": "Nessuno Stream Attivo",
"plex_connection_error": "Check Plex Connection"
"plex_connection_error": "Controllo Connessione a Plex"
},
"speedtest": {
"upload": "Upload",
@@ -53,7 +53,7 @@
"status": "Stato",
"url": "URL",
"information": "Informazione",
"raw_error": "Raw Error",
"raw_error": "Errore non processato",
"response_data": "Dati risposta"
},
"search": {
@@ -116,7 +116,7 @@
"blocked_percent": "Bloccato %"
},
"npm": {
"enabled": "Attivi",
"enabled": "Abilitato",
"disabled": "Disabilitati",
"total": "Totali"
},
@@ -156,7 +156,7 @@
},
"prowlarr": {
"enableIndexers": "Indicizzatori",
"numberOfGrabs": "Grabs",
"numberOfGrabs": "Grab",
"numberOfQueries": "Interrogazioni",
"numberOfFailGrabs": "Grabs Falliti",
"numberOfFailQueries": "Queries Fallite"
@@ -164,12 +164,12 @@
"transmission": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "In scaricamento",
"seed": "Seed"
},
"jackett": {
"configured": "Configurato",
"errored": "Errore"
"errored": "In errore"
},
"bazarr": {
"missingEpisodes": "Episodi Mancanti",
@@ -188,7 +188,7 @@
},
"qbittorrent": {
"download": "Download",
"leech": "Leech",
"leech": "In scaricamento",
"upload": "Upload",
"seed": "Seed"
},
@@ -242,19 +242,20 @@
"wait": "Attendere prego",
"temp": "TEMP",
"uptime": "UP",
"days": "d",
"hours": "h",
"days": "g",
"hours": "o",
"load": "Carico",
"warn": "Avviso",
"total": "Totale",
"free": "Libero",
"used": "Usato",
"crit": "Crit",
"read": "Read",
"write": "Write",
"crit": "Critico",
"read": "Lettura",
"write": "Scrittura",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"mem": "Mem.",
"swap": "Swap",
"_temp": "Temp."
},
"changedetectionio": {
"totalObserved": "Totale Osservato",
@@ -331,7 +332,7 @@
"updates": "Aggiornamenti",
"update_available": "Aggiornamento Disponibile",
"up_to_date": "Aggiornato",
"child_bridges": "Child Bridges",
"child_bridges": "Bridge Figli",
"child_bridges_status": "{{ok}}/{{total}}",
"up": "Up",
"pending": "In attesa",
@@ -373,7 +374,7 @@
"gluetun": {
"public_ip": "IP pubblico",
"region": "Località",
"country": "Stato"
"country": "Paese"
},
"hdhomerun": {
"channels": "Canali",
@@ -395,19 +396,19 @@
"deluge": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "In scaricamento",
"seed": "Seed"
},
"flood": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "In scaricamento",
"seed": "Seed"
},
"tdarr": {
"queue": "In coda",
"processed": "Elaborati",
"errored": "Errori",
"errored": "In errore",
"saved": "Salvati"
},
"miniflux": {
@@ -432,7 +433,7 @@
"downloadstation": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "In scaricamento",
"seed": "Seed"
},
"mikrotik": {
@@ -465,8 +466,8 @@
},
"octoprint": {
"printer_state": "Stato",
"temp_tool": "Tool temp",
"temp_bed": "Bed temp",
"temp_tool": "Temp. utensile",
"temp_bed": "Temp. letto",
"job_completion": "Completamento"
},
"cloudflared": {
@@ -474,7 +475,7 @@
"status": "Stato"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"datastore_usage": "Archivio dati",
"failed_tasks_24h": "Attività Non Riuscite 24h",
"cpu_usage": "CPU",
"memory_usage": "Memoria"
@@ -483,12 +484,12 @@
"users": "Utenti",
"photos": "Foto",
"videos": "Video",
"storage": "Memoria"
"storage": "Archiviazione"
},
"uptimekuma": {
"up": "Siti On",
"down": "Siti Down",
"uptime": "Uptime",
"uptime": "Operatività",
"incident": "Incidente",
"m": "m"
},
@@ -510,7 +511,7 @@
},
"diskstation": {
"days": "Giorni",
"uptime": "Uptime",
"uptime": "Periodo Attività",
"volumeAvailable": "Disponibile"
},
"fileflows": {
@@ -520,7 +521,7 @@
"time": "Tempo"
},
"grafana": {
"dashboards": "Dashboards",
"dashboards": "Dashboard",
"datasources": "Origine dei Dati",
"totalalerts": "Avvisi Totali",
"alertstriggered": "Avvisi Attivati"
@@ -560,8 +561,8 @@
"nodes": "Nodi"
},
"prometheus": {
"targets_up": "Targets Up",
"targets_down": "Targets Down",
"targets_up": "Target Attivi",
"targets_down": "Target Non Attivi",
"targets_total": "Targets Totali"
},
"minecraft": {
@@ -663,60 +664,74 @@
"totalFiles": "File"
},
"gamedig": {
"name": "Name",
"map": "Map",
"currentPlayers": "Current players",
"players": "Players",
"maxPlayers": "Max players",
"bots": "Bots",
"name": "Nome",
"map": "Mappa",
"currentPlayers": "Giocatori attuali",
"players": "Giocatori",
"maxPlayers": "Giocatori max",
"bots": "Bot",
"ping": "Ping",
"status": "Status",
"status": "Stato",
"online": "Online",
"offline": "Offline"
},
"azuredevops": {
"result": "Result",
"myPrs": "My PRs",
"approved": "Approved",
"status": "Status",
"buildId": "Build ID",
"succeeded": "Succeeded",
"notStarted": "Not Started",
"failed": "Failed",
"canceled": "Canceled",
"inProgress": "In Progress",
"totalPrs": "Total PRs"
"result": "Risultato",
"myPrs": "Miei PR",
"approved": "Approvato",
"status": "Stato",
"buildId": "ID Build",
"succeeded": "Riuscito",
"notStarted": "Non Avviato",
"failed": "Fallito",
"canceled": "Cancellato",
"inProgress": "In corso",
"totalPrs": "PR Totali"
},
"urbackup": {
"ok": "Ok",
"errored": "Errors",
"noRecent": "Out of Date",
"totalUsed": "Used Storage"
"errored": "Errori",
"noRecent": "Obsoleto",
"totalUsed": "Spazio usato"
},
"openmediavault": {
"total": "Total",
"running": "Running",
"downloading": "Downloading",
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
"total": "Totale",
"running": "In funzione",
"downloading": "Download in corso",
"stopped": "Fermati",
"passed": "Riusciti",
"failed": "Falliti"
},
"mealie": {
"recipes": "Recipes",
"users": "Users",
"categories": "Categories",
"tags": "Tags"
"recipes": "Ricette",
"users": "Utenti",
"categories": "Categorie",
"tags": "Tag"
},
"atsumeru": {
"series": "Series",
"archives": "Archives",
"chapters": "Chapters",
"categories": "Categories"
"series": "Serie",
"archives": "Archivi",
"chapters": "Capitoli",
"categories": "Categorie"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
"books": "Libri",
"authors": "Autori",
"categories": "Categorie",
"series": "Serie"
},
"uptimerobot": {
"status": "Stato",
"uptime": "Tempo di attività",
"lastDown": "Ultimo periodo di inattività",
"downDuration": "Durata inattività",
"sitesUp": "Siti attivi",
"sitesDown": "Siti non attivi",
"paused": "In pausa",
"notyetchecked": "Non ancora controllati",
"up": "Attivi",
"seemsdown": "Sembrano non attivi",
"down": "Non attivi",
"unknown": "Sconosciuto"
}
}

View File

@@ -11,7 +11,7 @@
"strelaysrv": {
"numActiveSessions": "セッション",
"numConnections": "コネクション",
"dataRelayed": "Relayed",
"dataRelayed": "中継",
"transferRate": "レート"
},
"glances": {
@@ -21,17 +21,18 @@
"uptime": "UP",
"days": "日",
"hours": "時間",
"load": "Load",
"warn": "Warn",
"total": "Total",
"free": "Free",
"used": "Used",
"load": "ロード",
"warn": "警告",
"total": "トータル",
"free": "空き",
"used": "使用中",
"crit": "Crit",
"read": "Read",
"write": "Write",
"read": "読み込み",
"write": "書き込み",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"mem": "メモリ",
"swap": "スワップ",
"_temp": "Temp"
},
"autobrr": {
"filters": "フィルター",
@@ -131,7 +132,7 @@
"flood": {
"download": "ダウンロード",
"upload": "アップロード",
"leech": "Leech",
"leech": "リーチ",
"seed": "Seed"
},
"changedetectionio": {
@@ -143,7 +144,7 @@
"transcoding": "変換中",
"bitrate": "ビットレート",
"no_active": "アクティブストリームなし",
"plex_connection_error": "Check Plex Connection"
"plex_connection_error": "Plex接続の確認"
},
"omada": {
"connectedAp": "接続されたAP",
@@ -176,7 +177,7 @@
"transmission": {
"download": "ダウンロード",
"upload": "アップロード",
"leech": "Leech",
"leech": "リーチ",
"seed": "Seed"
},
"qbittorrent": {
@@ -201,21 +202,21 @@
"wanted": "募集中",
"queued": "待機中",
"series": "シリーズ",
"queue": "Queue",
"unknown": "Unknown"
"queue": "キュー",
"unknown": "不明"
},
"radarr": {
"wanted": "募集中",
"missing": "不明",
"queued": "キュー",
"movies": "映画",
"queue": "Queue",
"queue": "キュー",
"unknown": "Unknown"
},
"lidarr": {
"wanted": "募集中",
"queued": "キュー",
"artists": "Artists"
"artists": "アーティスト"
},
"readarr": {
"wanted": "募集中",
@@ -224,7 +225,7 @@
},
"bazarr": {
"missingEpisodes": "欠番エピソード",
"missingMovies": "不明映画"
"missingMovies": "行方不明映画"
},
"ombi": {
"pending": "保留中",
@@ -292,7 +293,7 @@
"numberOfGrabs": "Grabs",
"numberOfQueries": "クエリ",
"numberOfFailGrabs": "Fail Grabs",
"numberOfFailQueries": "Fail Queries"
"numberOfFailQueries": "失敗クエリー"
},
"jackett": {
"configured": "設定済",
@@ -304,8 +305,8 @@
"domain_count": "ドメイン"
},
"miniflux": {
"read": "Read",
"unread": "Unread"
"read": "既読",
"unread": "未読"
},
"authentik": {
"users": "ユーザー",
@@ -461,7 +462,7 @@
"medusa": {
"wanted": "Wanted",
"queued": "Queued",
"series": "Series"
"series": "シリーズ"
},
"octoprint": {
"temp_bed": "ベッド温度",
@@ -474,7 +475,7 @@
"status": "状態"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"datastore_usage": "データストア",
"failed_tasks_24h": "失敗タスク(24h)",
"cpu_usage": "CPU",
"memory_usage": "メモリ"
@@ -499,7 +500,7 @@
},
"mylar": {
"series": "シリーズ",
"issues": "Issues",
"issues": "課題",
"wanted": "Wanted"
},
"photoprism": {
@@ -546,7 +547,7 @@
"records_total": "キューの長さ"
},
"healthchecks": {
"never": "まだPingはありません",
"never": "Pingしていません",
"new": "New",
"up": "オンライン",
"grace": "猶予期間中",
@@ -595,10 +596,10 @@
"shows": "ショー",
"recordings": "レコーディング",
"scheduled": "予定済",
"passes": "Passes"
"passes": "パス"
},
"whatsupdocker": {
"monitoring": "Monitoring",
"monitoring": "モニタリング",
"updates": "アップデート"
},
"tailscale": {
@@ -621,22 +622,22 @@
"systemTempC": "システム温度",
"poolUsage": "プール使用量",
"volumeUsage": "ボリューム使用量",
"invalid": "Invalid"
"invalid": "無効"
},
"pfsense": {
"up": "Up",
"load": "Load Avg",
"memory": "Mem Usage",
"wanStatus": "WAN Status",
"down": "Down",
"temp": "Temp",
"disk": "Disk Usage",
"up": "アップ",
"load": "読み込み平均",
"memory": "メモリ使用量",
"wanStatus": "WANステータス",
"down": "ダウン",
"temp": "温度",
"disk": "ディスク使用量",
"wanIP": "WAN IP"
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Current requests",
"requests_failed": "Failed requests"
"upstreams": "アップストリーム",
"requests": "現在のリクエスト",
"requests_failed": "失敗したリクエスト"
},
"evcc": {
"watt_hour": "Wh",
@@ -647,76 +648,90 @@
"charge_power": "チャージャー"
},
"pialert": {
"total": "Total",
"connected": "Connected",
"new_devices": "New Devices",
"down_alerts": "Down Alerts"
"total": "トータル",
"connected": "接続済み",
"new_devices": "新しいデバイス",
"down_alerts": "ダウンアラート"
},
"jdownloader": {
"downloadCount": "Queue Count",
"downloadSpeed": "Download Speed",
"downloadBytesRemaining": "Remaining",
"downloadTotalBytes": "Size"
"downloadCount": "キュー",
"downloadSpeed": "スピード",
"downloadBytesRemaining": "残り",
"downloadTotalBytes": "サイズ"
},
"kavita": {
"seriesCount": "Series",
"totalFiles": "Files"
"seriesCount": "シリーズ",
"totalFiles": "ファイル"
},
"gamedig": {
"name": "Name",
"map": "Map",
"currentPlayers": "Current players",
"players": "Players",
"maxPlayers": "Max players",
"bots": "Bots",
"name": "名前",
"map": "マップ",
"currentPlayers": "現在のプレーヤー",
"players": "プレーヤー",
"maxPlayers": "最大プレーヤー",
"bots": "ボット",
"ping": "Ping",
"status": "Status",
"online": "Online",
"offline": "Offline"
"status": "ステータス",
"online": "オンライン",
"offline": "オフライン"
},
"azuredevops": {
"result": "Result",
"status": "Status",
"buildId": "Build ID",
"succeeded": "Succeeded",
"result": "結果",
"status": "ステータス",
"buildId": "ビルドID",
"succeeded": "成功",
"notStarted": "Not Started",
"failed": "Failed",
"canceled": "Canceled",
"inProgress": "In Progress",
"totalPrs": "Total PRs",
"myPrs": "My PRs",
"approved": "Approved"
"failed": "失敗",
"canceled": "キャンセル",
"inProgress": "進行中",
"totalPrs": "合計PR",
"myPrs": "私のPR",
"approved": "承認"
},
"urbackup": {
"ok": "Ok",
"errored": "Errors",
"noRecent": "Out of Date",
"totalUsed": "Used Storage"
"errored": "エラー",
"noRecent": "期限切れ",
"totalUsed": "使用済みストレージ"
},
"openmediavault": {
"downloading": "Downloading",
"total": "Total",
"running": "Running",
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
"downloading": "ダウンロード中",
"total": "トータル",
"running": "実行中",
"stopped": "停止中",
"passed": "合格",
"failed": "不合格"
},
"mealie": {
"recipes": "Recipes",
"users": "Users",
"categories": "Categories",
"tags": "Tags"
"recipes": "レシピ",
"users": "ユーザー",
"categories": "カテゴリー",
"tags": "タグ"
},
"atsumeru": {
"series": "Series",
"archives": "Archives",
"chapters": "Chapters",
"categories": "Categories"
"series": "シリーズ",
"archives": "アーカイブ",
"chapters": "チャプター",
"categories": "カテゴリー"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
"books": "書籍",
"authors": "著者",
"categories": "カテゴリー",
"series": "シリーズ"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -321,7 +321,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -310,7 +310,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"unknown": "Unknown",
"status": "Status",
"uptime": "Uptime",
"sitesDown": "Sites Down",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down"
}
}

View File

@@ -81,7 +81,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Tandabuku",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"uptime": "Uptime",
"status": "Status",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -1,20 +1,20 @@
{
"widget": {
"missing_type": "Missend Widget Type: {{type}}",
"api_error": "API Error",
"api_error": "API fout",
"status": "Status",
"information": "Informatie",
"url": "URL",
"raw_error": "Raw Fout",
"response_data": "Reactiegegevens"
"raw_error": "Raw Error",
"response_data": "Responsgegevens"
},
"resources": {
"total": "Totaal",
"free": "Vrij",
"used": "Gebruikt",
"load": "Laadt",
"load": "lading",
"cpu": "CPU",
"mem": "MEM",
"mem": "GEH",
"days": "d",
"hours": "h",
"temp": "TEMP",
@@ -31,7 +31,7 @@
"offline": "Offline",
"error": "Fout",
"unknown": "Onbekend",
"running": "Running",
"running": "Lopend",
"starting": "Starten",
"unhealthy": "Ongezond",
"not_found": "Niet Gevonden",
@@ -72,8 +72,8 @@
"playing": "Afspelen",
"transcoding": "Transcodering",
"bitrate": "Bitsnelheid",
"no_active": "Geen Actieve Streams",
"plex_connection_error": "Check Plex Connection"
"no_active": "Geen actieve streams",
"plex_connection_error": "Controleer Plex Connectie"
},
"rutorrent": {
"active": "Actief",
@@ -84,16 +84,16 @@
"wanted": "Gezocht",
"queued": "In de wachtrij",
"series": "Series",
"queue": "Queue",
"unknown": "Unknown"
"queue": "Rij",
"unknown": "Onbekend"
},
"radarr": {
"movies": "Films",
"wanted": "Gezocht",
"queued": "In de wachtrij",
"missing": "Missend",
"queue": "Queue",
"unknown": "Unknown"
"queue": "Rij",
"unknown": "Onbekend"
},
"readarr": {
"wanted": "Gezocht",
@@ -114,7 +114,7 @@
"queries": "Queries",
"blocked": "Geblokkeerd",
"gravity": "Gravity",
"blocked_percent": "Blocked %"
"blocked_percent": "Geblokkerde %"
},
"traefik": {
"routers": "Routers",
@@ -135,15 +135,15 @@
"sabnzbd": {
"rate": "Rate",
"queue": "Wachtrij",
"timeleft": "Time Left"
"timeleft": "Tijd Over"
},
"nzbget": {
"rate": "Rate",
"rate": "Tarief",
"remaining": "Resterend",
"downloaded": "Gedownload"
},
"coinmarketcap": {
"configure": "Configure one or more crypto currencies to track",
"configure": "Configureer een of meer crypto eenheiden om bij te houden",
"1hour": "1 Uur",
"7days": "7 Dagen",
"1day": "1 Dag",
@@ -151,7 +151,7 @@
},
"gotify": {
"apps": "Applicaties",
"clients": "Clients",
"clients": "Cliënten",
"messages": "Berichten"
},
"prowlarr": {
@@ -164,7 +164,7 @@
"transmission": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "Bloedzuiger",
"seed": "Seed"
},
"jackett": {
@@ -178,28 +178,28 @@
"lidarr": {
"wanted": "Gezocht",
"queued": "In de wachtrij",
"artists": "Artists"
"artists": "Artiesten"
},
"adguard": {
"queries": "Queries",
"blocked": "Geblokkeerd",
"filtered": "Filtered",
"filtered": "Gefilterde",
"latency": "Latency"
},
"qbittorrent": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "Bloedzuiger",
"seed": "Seed"
},
"mastodon": {
"user_count": "Users",
"user_count": "Gebruikers",
"status_count": "Posts",
"domain_count": "Domeinen"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"numActiveSessions": "Sessies",
"numConnections": "Connecties",
"dataRelayed": "Relayed",
"transferRate": "Rate"
},
@@ -223,13 +223,13 @@
"wlan_users": "WLAN Gebruikers",
"up": "UP",
"down": "DOWN",
"wait": "Wachten aub",
"wait": "Even geduld",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Apparaten",
"lan_devices": "LAN Apparaten",
"wlan_devices": "WLAN Apparaten",
"empty_data": "Subsystem status onbekend"
"empty_data": "Subsysteem status onbekend"
},
"plex": {
"streams": "Actieve Streams",
@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Totaal waargenomen",
@@ -395,7 +396,7 @@
"deluge": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "Bloedzuiger",
"seed": "Seed"
},
"flood": {
@@ -408,7 +409,7 @@
"queue": "Wachtrij",
"processed": "Processed",
"errored": "Errored",
"saved": "Saved"
"saved": "Opgeslagen"
},
"miniflux": {
"read": "Gelezen",
@@ -423,16 +424,16 @@
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
},
"omada": {
"connectedAp": "Connected APs",
"connectedAp": "Verbonden APs",
"activeUser": "Actieve apparaten",
"alerts": "Meldingen",
"connectedGateway": "Connected gateways",
"connectedSwitches": "Connected switches"
"connectedGateway": "Verbonden gateways",
"connectedSwitches": "Verbonden switches"
},
"downloadstation": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"leech": "Bloedzuiger",
"seed": "Seed"
},
"mikrotik": {
@@ -459,7 +460,7 @@
"layers": "Layers"
},
"medusa": {
"wanted": "Wanted",
"wanted": "Gewild",
"queued": "Queued",
"series": "Series"
},
@@ -588,13 +589,13 @@
"switches_on": "Switches On"
},
"freshrss": {
"subscriptions": "Subscriptions",
"unread": "Unread"
"subscriptions": "Abonnementen",
"unread": "Ongelezen"
},
"channelsdvrserver": {
"shows": "Shows",
"recordings": "Recordings",
"scheduled": "Scheduled",
"scheduled": "Geplanned",
"passes": "Passes"
},
"whatsupdocker": {
@@ -603,25 +604,25 @@
},
"tailscale": {
"address": "Address",
"expires": "Expires",
"never": "Never",
"last_seen": "Last Seen",
"now": "Now",
"expires": "Verloopt",
"never": "Nooit",
"last_seen": "Laatst Gezien",
"now": "Nu",
"years": "{{number}}y",
"weeks": "{{number}}w",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"ago": "{{value}} Ago"
"ago": "{{value}} Geleden"
},
"qnap": {
"cpuUsage": "CPU Usage",
"memUsage": "MEM Usage",
"systemTempC": "System Temp",
"poolUsage": "Pool Usage",
"cpuUsage": "CPU Verbruik",
"memUsage": "MEM Gebruik",
"systemTempC": "Systeem Temperatuur",
"poolUsage": "Pool Gebruik",
"volumeUsage": "Volume Usage",
"invalid": "Invalid"
"invalid": "ongeldig"
},
"pfsense": {
"load": "Load Avg",
@@ -635,21 +636,21 @@
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Current requests",
"requests_failed": "Failed requests"
"requests": "Momentele verzoeken",
"requests_failed": "Gefaalde verzoeken"
},
"evcc": {
"pv_power": "Production",
"pv_power": "Productie",
"battery_soc": "Battery",
"grid_power": "Grid",
"home_power": "Consumption",
"charge_power": "Charger",
"charge_power": "Oplader",
"watt_hour": "Wh"
},
"pialert": {
"total": "Total",
"connected": "Connected",
"new_devices": "New Devices",
"connected": "Verbonden",
"new_devices": "Nieuwe Apparaten",
"down_alerts": "Down Alerts"
},
"jdownloader": {
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"uptime": "Uptime",
"status": "Status",
"up": "Up",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"diffsDetected": "Wykryto różnic",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Observados",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -267,7 +267,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observado",
@@ -727,5 +728,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown",
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up"
}
}

View File

@@ -20,12 +20,12 @@
"mem": "MEM",
"cpu": "CPU",
"offline": "Offline",
"error": "Error",
"unknown": "Unknown",
"running": "Running",
"starting": "Starting",
"error": "Eroare",
"unknown": "Necunoscut",
"running": "Rulează",
"starting": "Începe",
"unhealthy": "Unhealthy",
"not_found": "Not Found",
"not_found": "Negăsit",
"exited": "Exited",
"partial": "Partial",
"healthy": "Healthy"
@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"sitesDown": "Sites Down",
"paused": "Paused",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -18,7 +18,7 @@
"load": "Загрузка",
"cpu": "ЦП",
"mem": "ОЗУ",
"temp": "Темпер.",
"temp": "Температура",
"max": "Макс.",
"uptime": "Работает",
"months": "мес",
@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Всего наблюдаемых",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -2,18 +2,18 @@
"docker": {
"rx": "RX",
"tx": "TX",
"mem": "MEM",
"mem": "RAM",
"cpu": "CPU",
"offline": "Offline",
"error": "Error",
"unknown": "Unknown",
"running": "Running",
"starting": "Starting",
"unhealthy": "Unhealthy",
"not_found": "Not Found",
"exited": "Exited",
"partial": "Partial",
"healthy": "Healthy"
"error": "Chyba",
"unknown": "Neznáme",
"running": "Beží",
"starting": "Spúšťa sa",
"unhealthy": "Nezdravý",
"not_found": "Nenájdené",
"exited": "Ukončené",
"partial": "Čiastočný",
"healthy": "Zdravý"
},
"rutorrent": {
"active": "Active",
@@ -21,10 +21,10 @@
"download": "Download"
},
"tdarr": {
"queue": "Queue",
"processed": "Processed",
"errored": "Errored",
"saved": "Saved"
"queue": "Fronta",
"processed": "Spracované",
"errored": "Chybné",
"saved": "Uložené"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
@@ -144,74 +144,74 @@
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
},
"widget": {
"api_error": "API Error",
"missing_type": "Missing Widget Type: {{type}}",
"information": "Information",
"status": "Status",
"api_error": "Chyba API",
"missing_type": "Chýba typ widgetu: {{type}}",
"information": "Informácia",
"status": "Stav",
"url": "URL",
"raw_error": "Raw Error",
"response_data": "Response Data"
"raw_error": "Nevyriešená chyba",
"response_data": "Dáta odpovede"
},
"weather": {
"current": "Current Location",
"allow": "Click to allow",
"updating": "Updating",
"wait": "Please wait"
"current": "Aktuálna poloha",
"allow": "Klikni pre povolenie",
"updating": "Prebieha aktualizácia",
"wait": "Počkajte prosím"
},
"search": {
"placeholder": "Search…"
"placeholder": "Hľadať…"
},
"resources": {
"cpu": "CPU",
"mem": "MEM",
"total": "Total",
"free": "Free",
"used": "Used",
"load": "Load",
"temp": "TEMP",
"max": "Max",
"uptime": "UP",
"months": "mo",
"mem": "RAM",
"total": "Celkovo",
"free": "Voľné",
"used": "Využité",
"load": "Záťaž",
"temp": "TEPLOTA",
"max": "Max.",
"uptime": "BEŽÍ",
"months": "mes.",
"days": "d",
"hours": "h",
"minutes": "m"
},
"unifi": {
"users": "Users",
"uptime": "System Uptime",
"days": "Days",
"users": "Používatelia",
"uptime": "Doba prevádzky",
"days": "D",
"wan": "WAN",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Devices",
"lan_devices": "LAN Devices",
"wlan_devices": "WLAN Devices",
"lan_users": "LAN Users",
"wlan_users": "WLAN Users",
"up": "UP",
"down": "DOWN",
"wait": "Please wait",
"empty_data": "Subsystem status unknown"
"devices": "Zariadenia",
"lan_devices": "Zariadenia LAN",
"wlan_devices": "Zariadenia WLAN",
"lan_users": "Používatelia LAN",
"wlan_users": "Používatelia WLAN",
"up": "BEŽÍ",
"down": "NEBEŽÍ",
"wait": "Počkajte prosím",
"empty_data": "Stav podsystému neznámy"
},
"ping": {
"error": "Error",
"ping": "Ping"
"error": "Chyba",
"ping": "Odozva"
},
"emby": {
"playing": "Playing",
"transcoding": "Transcoding",
"bitrate": "Bitrate",
"no_active": "No Active Streams",
"movies": "Movies",
"series": "Series",
"episodes": "Episodes",
"songs": "Songs"
"playing": "Prehrávané",
"transcoding": "Prekódovávané",
"bitrate": "Prenosová rýchlosť",
"no_active": "Žiadny aktívny stream",
"movies": "Filmy",
"series": "Seriály",
"episodes": "Epizódy",
"songs": "Skladby"
},
"flood": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"seed": "Seed"
"download": "Sťahovanie",
"upload": "Odosielanie",
"leech": "Leechovanie",
"seed": "Seedovanie"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -276,70 +276,70 @@
"queued": "Queued",
"series": "Series",
"queue": "Queue",
"unknown": "Unknown"
"unknown": "Neznáme"
},
"radarr": {
"wanted": "Wanted",
"missing": "Missing",
"queued": "Queued",
"movies": "Movies",
"queue": "Queue",
"unknown": "Unknown"
"wanted": "Chcené",
"missing": "Chýbajúce",
"queued": "Vo fronte",
"movies": "Filmy",
"queue": "Fronta",
"unknown": "Neznáme"
},
"lidarr": {
"wanted": "Wanted",
"queued": "Queued",
"artists": "Artists"
"wanted": "Chcené",
"queued": "Vo fronte",
"artists": "Interpreti"
},
"readarr": {
"wanted": "Wanted",
"queued": "Queued",
"books": "Books"
"wanted": "Chcené",
"queued": "Vo fronte",
"books": "Knihy"
},
"bazarr": {
"missingEpisodes": "Missing Episodes",
"missingMovies": "Missing Movies"
"missingEpisodes": "Chýbajúce epizódy",
"missingMovies": "Chýbajúce filmy"
},
"ombi": {
"pending": "Pending",
"approved": "Approved",
"available": "Available"
"pending": "Čakajúce",
"approved": "Schválené",
"available": "Dostupné"
},
"jellyseerr": {
"pending": "Pending",
"approved": "Approved",
"available": "Available"
"pending": "Čakajúce",
"approved": "Schválené",
"available": "Dostupné"
},
"overseerr": {
"pending": "Pending",
"processing": "Processing",
"approved": "Approved",
"available": "Available"
"pending": "Čakajúce",
"processing": "Spracovávané",
"approved": "Schválené",
"available": "Dostupné"
},
"pihole": {
"queries": "Queries",
"blocked": "Blocked",
"gravity": "Gravity",
"blocked_percent": "Blocked %"
"queries": "Dopyty",
"blocked": "Zablokované",
"gravity": "Gravitácia",
"blocked_percent": "Blokované %"
},
"adguard": {
"queries": "Queries",
"blocked": "Blocked",
"filtered": "Filtered",
"latency": "Latency"
"queries": "Dopyty",
"blocked": "Blokované",
"filtered": "Filtrované",
"latency": "Odozva"
},
"speedtest": {
"upload": "Upload",
"download": "Download",
"upload": "Odosielanie",
"download": "Sťahovanie",
"ping": "Ping"
},
"portainer": {
"running": "Running",
"stopped": "Stopped",
"total": "Total"
"running": "Spustené",
"stopped": "Zastavené",
"total": "Celkovo"
},
"traefik": {
"routers": "Routers",
"routers": "Routery",
"services": "Services",
"middleware": "Middleware"
},
@@ -418,7 +418,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -588,8 +589,8 @@
"switches_on": "Switches On"
},
"freshrss": {
"subscriptions": "Subscriptions",
"unread": "Unread"
"subscriptions": "Odbery",
"unread": "Neprečítané"
},
"channelsdvrserver": {
"shows": "Shows",
@@ -602,18 +603,18 @@
"updates": "Updates"
},
"tailscale": {
"address": "Address",
"years": "{{number}}y",
"expires": "Expires",
"never": "Never",
"last_seen": "Last Seen",
"now": "Now",
"weeks": "{{number}}w",
"address": "Adresa",
"years": "{{number}}r",
"expires": "Vyprší",
"never": "Nikdy",
"last_seen": "Naposledy videné",
"now": "Teraz",
"weeks": "{{number}}t",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"ago": "{{value}} Ago"
"ago": "Pred {{value}}"
},
"qnap": {
"cpuUsage": "CPU Usage",
@@ -634,23 +635,23 @@
"wanIP": "WAN IP"
},
"caddy": {
"upstreams": "Upstreams",
"upstreams": "Odosielanie dát",
"requests": "Current requests",
"requests_failed": "Failed requests"
},
"evcc": {
"pv_power": "Production",
"battery_soc": "Battery",
"grid_power": "Grid",
"home_power": "Consumption",
"charge_power": "Charger",
"pv_power": "Produkcia",
"battery_soc": "Batéria",
"grid_power": "Mriežka",
"home_power": "Spotreba",
"charge_power": "Nabíjačka",
"watt_hour": "Wh"
},
"pialert": {
"total": "Total",
"connected": "Connected",
"new_devices": "New Devices",
"down_alerts": "Down Alerts"
"total": "Celkovo",
"connected": "Pripojené",
"new_devices": "Nové zariadenia",
"down_alerts": "Upozornenia o výpadkoch"
},
"jdownloader": {
"downloadCount": "Queue Count",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -169,7 +169,7 @@
"bitrate": "Pasovna širina",
"playing": "Predvaja",
"no_active": "Ni aktivne vsebine",
"plex_connection_error": "Check Plex Connection"
"plex_connection_error": "Preveri Plex povezavo"
},
"flood": {
"download": "Prenos",
@@ -365,12 +365,13 @@
"warn": "Opoz.",
"total": "Skupaj",
"used": "V uporabi",
"crit": "Crit",
"read": "Read",
"write": "Write",
"crit": "Krit.",
"read": "Prebrano",
"write": "Zapisano",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"authentik": {
"users": "Uporabniki",
@@ -663,60 +664,74 @@
"totalFiles": "Datoteke"
},
"gamedig": {
"name": "Name",
"map": "Map",
"currentPlayers": "Current players",
"players": "Players",
"maxPlayers": "Max players",
"bots": "Bots",
"name": "Naziv",
"map": "Zemljevid",
"currentPlayers": "Igralcev",
"players": "Igralci",
"maxPlayers": "Maks igralcev",
"bots": "Boti",
"ping": "Ping",
"status": "Status",
"online": "Online",
"offline": "Offline"
"online": "Na spletu",
"offline": "Nepovezano"
},
"azuredevops": {
"result": "Result",
"result": "Rezultati",
"status": "Status",
"buildId": "Build ID",
"succeeded": "Succeeded",
"notStarted": "Not Started",
"failed": "Failed",
"canceled": "Canceled",
"inProgress": "In Progress",
"totalPrs": "Total PRs",
"myPrs": "My PRs",
"approved": "Approved"
"buildId": "ID gradnje",
"succeeded": "Uspešnih",
"notStarted": "Ni zagnano",
"failed": "Neuspešno",
"canceled": "Preklicano",
"inProgress": "V delu",
"totalPrs": "Skupaj PR",
"myPrs": "Moji PR",
"approved": "Odobreno"
},
"urbackup": {
"ok": "Ok",
"errored": "Errors",
"noRecent": "Out of Date",
"totalUsed": "Used Storage"
"ok": "V redu",
"errored": "Napake",
"noRecent": "Zastarano",
"totalUsed": "Shramba v uporabi"
},
"openmediavault": {
"downloading": "Downloading",
"total": "Total",
"running": "Running",
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
"downloading": "Prenašanje",
"total": "Skupaj",
"running": "V teku",
"stopped": "Ustavljeno",
"passed": "Opravljeno",
"failed": "Neuspešno"
},
"mealie": {
"recipes": "Recipes",
"users": "Users",
"categories": "Categories",
"tags": "Tags"
"recipes": "Recepti",
"users": "Uporabniki",
"categories": "Kategorije",
"tags": "Značke"
},
"atsumeru": {
"series": "Series",
"archives": "Archives",
"chapters": "Chapters",
"categories": "Categories"
"series": "Serije",
"archives": "Arhivi",
"chapters": "Poglavja",
"categories": "Kategorije"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
"books": "Knjige",
"authors": "Avtorji",
"categories": "Kategorije",
"series": "Serije"
},
"uptimerobot": {
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"unknown": "Unknown",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"seemsdown": "Seems Down",
"down": "Down"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"paused": "Paused",
"sitesDown": "Sites Down",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "మొత్తం గమనించబడింది",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -330,7 +330,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Bookmark",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Toplam Gözlenen",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -378,7 +378,8 @@
"write": "Написати",
"gpu": "GPU",
"mem": "Пам'ять",
"swap": "Обмін"
"swap": "Обмін",
"_temp": "Temp"
},
"quicklaunch": {
"bookmark": "Закладка",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"up": "Up",
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "Total Observed",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "Write",
"gpu": "GPU",
"mem": "Mem",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "观察到的总数",
@@ -659,8 +660,8 @@
"downloadTotalBytes": "Size"
},
"kavita": {
"seriesCount": "Series",
"totalFiles": "Files"
"seriesCount": "系列",
"totalFiles": "文件"
},
"gamedig": {
"name": "Name",
@@ -714,9 +715,23 @@
"categories": "Categories"
},
"calibreweb": {
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
"books": "书籍",
"authors": "作者",
"categories": "分类",
"series": "丛书"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -254,7 +254,8 @@
"write": "寫入",
"gpu": "GPU",
"mem": "記憶體",
"swap": "Swap"
"swap": "Swap",
"_temp": "Temp"
},
"changedetectionio": {
"totalObserved": "總監測數",
@@ -718,5 +719,19 @@
"authors": "Authors",
"categories": "Categories",
"series": "Series"
},
"uptimerobot": {
"status": "Status",
"uptime": "Uptime",
"lastDown": "Last Downtime",
"downDuration": "Downtime Duration",
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}
}

View File

@@ -5,44 +5,65 @@ import { MdKeyboardArrowDown } from "react-icons/md";
import ErrorBoundary from "components/errorboundry";
import List from "components/bookmarks/list";
import ResolvedIcon from "components/resolvedicon";
export default function BookmarksGroup({ group, disableCollapse }) {
export default function BookmarksGroup({ bookmarks, layout, disableCollapse }) {
const panel = useRef();
return (
<div key={group.name} className="flex-1">
<Disclosure defaultOpen>
{({ open }) => (
<>
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
<MdKeyboardArrowDown className={classNames(
disableCollapse ? 'hidden' : '',
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
open ? '' : 'rotate-90'
)} />
</Disclosure.Button>
<Transition
// Otherwise the transition group does display: none and cancels animation
className="!block"
unmount={false}
beforeLeave={() => {
panel.current.style.height = `${panel.current.scrollHeight}px`;
setTimeout(() => {panel.current.style.height = `0`}, 1);
}}
beforeEnter={() => {
panel.current.style.height = `0px`;
setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
}}
>
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
<ErrorBoundary>
<List bookmarks={group.bookmarks} />
</ErrorBoundary>
</Disclosure.Panel>
</Transition>
</>
)}
</Disclosure>
<div
key={bookmarks.name}
className={classNames(
"bookmark-group",
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1"
)}
>
<Disclosure defaultOpen>
{({ open }) => (
<>
{layout?.header !== false && (
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
{layout?.icon && (
<div className="flex-shrink-0 mr-2 w-7 h-7 bookmark-group-icon">
<ResolvedIcon icon={layout.icon} />
</div>
)}
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium bookmark-group-name">{bookmarks.name}</h2>
<MdKeyboardArrowDown
className={classNames(
disableCollapse ? "hidden" : "",
"transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl",
open ? "" : "rotate-180"
)}
/>
</Disclosure.Button>
)}
<Transition
// Otherwise the transition group does display: none and cancels animation
className="!block"
unmount={false}
beforeLeave={() => {
panel.current.style.height = `${panel.current.scrollHeight}px`;
setTimeout(() => {
panel.current.style.height = `0`;
}, 1);
}}
beforeEnter={() => {
panel.current.style.height = `0px`;
setTimeout(() => {
panel.current.style.height = `${panel.current.scrollHeight}px`;
}, 1);
}}
>
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
<ErrorBoundary>
<List bookmarks={bookmarks.bookmarks} layout={layout} />
</ErrorBoundary>
</Disclosure.Panel>
</Transition>
</>
)}
</Disclosure>
</div>
);
}

View File

@@ -9,18 +9,18 @@ export default function Item({ bookmark }) {
const { settings } = useContext(SettingsContext);
return (
<li key={bookmark.name}>
<li key={bookmark.name} id={bookmark.id} className="bookmark" data-name={bookmark.name}>
<a
href={bookmark.href}
title={bookmark.name}
target={bookmark.target ?? settings.target ?? "_blank"}
className="block w-full text-left cursor-pointer transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10"
className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
"block w-full text-left cursor-pointer transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10"
)}
>
<div className="flex">
<div className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
"flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md"
)}>
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md bookmark-icon">
{bookmark.icon &&
<div className="flex-shrink-0 w-5 h-5">
<ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
@@ -28,12 +28,9 @@ export default function Item({ bookmark }) {
}
{!bookmark.icon && bookmark.abbr}
</div>
<div className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
"flex-1 flex items-center justify-between rounded-r-md"
)}>
<div className="flex-1 grow pl-3 py-2 text-xs">{bookmark.name}</div>
<div className="px-2 py-2 truncate text-theme-500 dark:text-theme-300 text-xs">{hostname}</div>
<div className="flex-1 flex items-center justify-between rounded-r-md bookmark-text">
<div className="flex-1 grow pl-3 py-2 text-xs bookmark-name">{bookmark.name}</div>
<div className="px-2 py-2 truncate text-theme-500 dark:text-theme-300 text-xs bookmark-hostname">{hostname}</div>
</div>
</div>
</a>

View File

@@ -1,8 +1,17 @@
import classNames from "classnames";
import { columnMap } from "../../utils/layout/columns";
import Item from "components/bookmarks/item";
export default function List({ bookmarks }) {
export default function List({ bookmarks, layout }) {
return (
<ul className="mt-3 flex flex-col">
<ul
className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3 bookmark-list"
)}
>
{bookmarks.map((bookmark) => (
<Item key={`${bookmark.name}-${bookmark.href}`} bookmark={bookmark} />
))}

View File

@@ -0,0 +1,10 @@
import useSWR from "swr"
export default function FileContent({ path, loadingValue, errorValue, emptyValue = '' }) {
const fetcher = (url) => fetch(url).then((res) => res.text())
const { data, error, isLoading } = useSWR(`/api/config/${ path }`, fetcher)
if (error) return (errorValue)
if (isLoading) return (loadingValue)
return (data || emptyValue)
}

View File

@@ -61,7 +61,6 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
}
}
function handleItemHover(event) {
setCurrentItemIndex(parseInt(event.target?.dataset?.index, 10));
}
@@ -71,6 +70,16 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
openCurrentItem(event.metaKey);
}
function handleItemKeyDown(event) {
if (!isOpen) return;
// native button handles other keys
if (event.key === "Escape") {
closeAndReset();
event.preventDefault();
}
}
useEffect(() => {
if (searchString.length === 0) setResults([]);
else {
@@ -162,10 +171,10 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
{results.length > 0 && <ul className="max-h-[60vh] overflow-y-auto m-2">
{results.map((r, i) => (
<li key={r.container ?? r.app ?? `${r.name}-${r.href}`}>
<button type="button" data-index={i} onMouseEnter={handleItemHover} className={classNames(
<button type="button" data-index={i} onMouseEnter={handleItemHover} onClick={handleItemClick} onKeyDown={handleItemKeyDown} className={classNames(
"flex flex-row w-full items-center justify-between rounded-md text-sm md:text-xl py-2 px-4 cursor-pointer text-theme-700 dark:text-theme-200",
i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50",
)} onClick={handleItemClick}>
)}>
<div className="flex flex-row items-center mr-4 pointer-events-none">
{(r.icon || r.abbr) && <div className="w-5 text-xs mr-4">
{r.icon && <ResolvedIcon icon={r.icon} />}

View File

@@ -14,6 +14,7 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
<div
key={services.name}
className={classNames(
"services-group",
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1",
@@ -25,15 +26,15 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
{ layout?.header !== false &&
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
{layout?.icon &&
<div className="flex-shrink-0 mr-2 w-7 h-7">
<div className="flex-shrink-0 mr-2 w-7 h-7 service-group-icon">
<ResolvedIcon icon={layout.icon} />
</div>
}
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium service-group-name">{services.name}</h2>
<MdKeyboardArrowDown className={classNames(
disableCollapse ? 'hidden' : '',
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
open ? '' : 'rotate-90'
open ? '' : 'rotate-180'
)} />
</Disclosure.Button>
}

View File

@@ -29,28 +29,30 @@ export default function Item({ service, group }) {
}
};
return (
<li key={service.name}>
<li key={service.name} id={service.id} className="service" data-name={service.name || ""}>
<div
className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`,
hasLink && "cursor-pointer",
'transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip'
"transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip service-card"
)}
>
<div className="flex select-none z-0">
<div className="flex select-none z-0 service-title">
{service.icon &&
(hasLink ? (
<a
href={service.href}
target={service.target ?? settings.target ?? "_blank"}
rel="noreferrer"
className="flex-shrink-0 flex items-center justify-center w-12 "
className="flex-shrink-0 flex items-center justify-center w-12 service-icon"
>
<ResolvedIcon icon={service.icon} />
</a>
) : (
<div className="flex-shrink-0 flex items-center justify-center w-12 ">
<div className="flex-shrink-0 flex items-center justify-center w-12 service-icon">
<ResolvedIcon icon={service.icon} />
</div>
))}
@@ -60,25 +62,25 @@ export default function Item({ service, group }) {
href={service.href}
target={service.target ?? settings.target ?? "_blank"}
rel="noreferrer"
className="flex-1 flex items-center justify-between rounded-r-md "
className="flex-1 flex items-center justify-between rounded-r-md service-title-text"
>
<div className="flex-1 px-2 py-2 text-sm text-left z-10">
<div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name">
{service.name}
<p className="text-theme-500 dark:text-theme-300 text-xs font-light">{service.description}</p>
<p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">{service.description}</p>
</div>
</a>
) : (
<div className="flex-1 flex items-center justify-between rounded-r-md ">
<div className="flex-1 px-2 py-2 text-sm text-left z-10">
<div className="flex-1 flex items-center justify-between rounded-r-md service-title-text">
<div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name">
{service.name}
<p className="text-theme-500 dark:text-theme-300 text-xs font-light">{service.description}</p>
<p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">{service.description}</p>
</div>
</div>
)}
<div className="absolute top-0 right-0 w-1/2 flex flex-row justify-end gap-2 mr-2 z-30">
<div className="absolute top-0 right-0 flex flex-row justify-end gap-2 mr-2 z-30 service-tags">
{service.ping && (
<div className="flex-shrink-0 flex items-center justify-center cursor-pointer">
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
<Ping group={group} service={service.name} />
<span className="sr-only">Ping status</span>
</div>
@@ -88,7 +90,7 @@ export default function Item({ service, group }) {
<button
type="button"
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
className="flex-shrink-0 flex items-center justify-center cursor-pointer"
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-container-stats"
>
<Status service={service} />
<span className="sr-only">View container stats</span>
@@ -98,7 +100,7 @@ export default function Item({ service, group }) {
<button
type="button"
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
className="flex-shrink-0 flex items-center justify-center cursor-pointer"
className="flex-shrink-0 flex items-center justify-center cursor-pointer service-tag service-app"
>
<KubernetesStatus service={service} />
<span className="sr-only">View container stats</span>
@@ -111,7 +113,7 @@ export default function Item({ service, group }) {
<div
className={classNames(
showStats || (statsOpen && !statsClosing) ? "max-h-[110px] opacity-100" : " max-h-[0] opacity-0",
"w-full overflow-hidden transition-all duration-300 ease-in-out"
"w-full overflow-hidden transition-all duration-300 ease-in-out service-stats"
)}
>
{(showStats || statsOpen) && <Docker service={{ widget: { container: service.container, server: service.server } }} />}
@@ -121,7 +123,7 @@ export default function Item({ service, group }) {
<div
className={classNames(
showStats || (statsOpen && !statsClosing) ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0",
"w-full overflow-hidden transition-all duration-300 ease-in-out"
"w-full overflow-hidden transition-all duration-300 ease-in-out service-stats"
)}
>
{(showStats || statsOpen) && <Kubernetes service={{ widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector } }} />}

View File

@@ -6,14 +6,14 @@ export default function KubernetesStatus({ service }) {
const { data, error } = useSWR(`/api/kubernetes/status/${service.namespace}/${service.app}?${podSelectorString}`);
if (error) {
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.error")}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-error" title={t("docker.error")}>
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
</div>
}
if (data && data.status === "running") {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health ?? data.status}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status" title={data.health ?? data.status}>
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health ?? data.status}</div>
</div>
);
@@ -21,14 +21,14 @@ export default function KubernetesStatus({ service }) {
if (data && (data.status === "not found" || data.status === "down" || data.status === "partial")) {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.status}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-warning" title={data.status}>
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</div>
</div>
);
}
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden k8s-status-unknown">
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
</div>
);

View File

@@ -1,25 +1,15 @@
import classNames from "classnames";
import Item from "components/services/item";
import { columnMap } from "../../utils/layout/columns";
const columnMap = [
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
"grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-2",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-6",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-7",
"grid-cols-1 md:grid-cols-2 lg:grid-cols-8",
];
import Item from "components/services/item";
export default function List({ group, services, layout }) {
return (
<ul
className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3"
"mt-3 services-list"
)}
>
{services.map((service) => (

View File

@@ -9,7 +9,7 @@ export default function Ping({ group, service }) {
if (error) {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-error">
<div className="text-[8px] font-bold text-rose-500 uppercase">{t("ping.error")}</div>
</div>
);
@@ -17,7 +17,7 @@ export default function Ping({ group, service }) {
if (!data) {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-ping">
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("ping.ping")}</div>
</div>
);
@@ -27,14 +27,14 @@ export default function Ping({ group, service }) {
if (data.status > 403) {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusText}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-status-invalid" title={statusText}>
<div className="text-[8px] font-bold text-rose-500/80">{data.status}</div>
</div>
);
}
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusText}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden ping-status-valid" title={statusText}>
<div className="text-[8px] font-bold text-emerald-500/80">{t("common.ms", { value: data.latency, style: "unit", unit: "millisecond", maximumFractionDigits: 0 })}</div>
</div>
);

View File

@@ -7,7 +7,7 @@ export default function Status({ service }) {
const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`);
if (error) {
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.error")}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-error" title={t("docker.error")}>
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
</div>
}
@@ -18,7 +18,7 @@ export default function Status({ service }) {
if (data.status?.includes("running")) {
if (data.health === "starting") {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.starting")}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-starting" title={t("docker.starting")}>
<div className="text-[8px] font-bold text-blue-500/80 uppercase">{t("docker.starting")}</div>
</div>
);
@@ -26,7 +26,7 @@ export default function Status({ service }) {
if (data.health === "unhealthy") {
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={t("docker.unhealthy")}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-unhealthy" title={t("docker.unhealthy")}>
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{t("docker.unhealthy")}</div>
</div>
);
@@ -39,7 +39,7 @@ export default function Status({ service }) {
}
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusLabel}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status" title={statusLabel}>
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{statusLabel}</div>
</div>
);
@@ -50,7 +50,7 @@ export default function Status({ service }) {
else if (data.status === "exited") statusLabel = t("docker.exited")
else statusLabel = data.status.replace("partial", t("docker.partial"))
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={statusLabel}>
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status-warning" title={statusLabel}>
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{statusLabel}</div>
</div>
);
@@ -58,7 +58,7 @@ export default function Status({ service }) {
}
return (
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden docker-status-unknown">
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
</div>
);

View File

@@ -17,7 +17,7 @@ export default function Widget({ service }) {
}
return (
<div className="bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1">
<div className="bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1 service-missing">
<div className="font-thin text-sm">{t("widget.missing_type", { type: service.widget.type })}</div>
</div>
);

View File

@@ -8,7 +8,8 @@ export default function Block({ value, label }) {
<div
className={classNames(
"bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center text-center p-1",
value === undefined ? "animate-pulse" : ""
value === undefined ? "animate-pulse" : "",
"service-block"
)}
>
<div className="font-thin text-sm">{value === undefined || value === null ? "-" : value}</div>

View File

@@ -36,5 +36,5 @@ export default function Container({ error = false, children, service }) {
}));
}
return <div className="relative flex flex-row w-full">{visibleChildren}</div>;
return <div className="relative flex flex-row w-full service-container">{visibleChildren}</div>;
}

31
src/components/tab.jsx Normal file
View File

@@ -0,0 +1,31 @@
import { useContext } from "react";
import classNames from "classnames";
import { TabContext } from "utils/contexts/tab";
export function slugify(tabName) {
return tabName !== undefined ? encodeURIComponent(tabName.toString().replace(/\s+/g, '-').toLowerCase()) : ''
}
export default function Tab({ tab }) {
const { activeTab, setActiveTab } = useContext(TabContext);
return (
<li key={tab} role="presentation"
className={classNames(
"text-theme-700 dark:text-theme-200 relative h-8 w-full rounded-md flex m-1",
)}>
<button id={`${tab}-tab`} type="button" role="tab"
aria-controls={`#${tab}`} aria-selected={activeTab === slugify(tab) ? "true" : "false"}
className={classNames(
"h-full w-full rounded-md",
activeTab === slugify(tab) ? "bg-theme-300/20 dark:bg-white/10" : "hover:bg-theme-100/20 dark:hover:bg-white/5",
)}
onClick={() => {
setActiveTab(slugify(tab));
window.location.hash = `#${slugify(tab)}`;
}}
>{tab}</button>
</li>
);
}

View File

@@ -38,7 +38,7 @@ export default function ColorToggle() {
}
return (
<div className="w-full self-center">
<div id="color" className="w-full self-center">
<Popover className="relative flex items-center">
<Popover.Button className="outline-none">
<IoColorPalette

View File

@@ -10,7 +10,7 @@ export default function Revalidate() {
};
return (
<div className="rounded-full flex align-middle self-center mr-3">
<div id="revalidate" className="rounded-full flex align-middle self-center mr-3">
<MdRefresh onClick={() => revalidate()} className="text-theme-800 dark:text-theme-200 w-6 h-6 cursor-pointer" />
</div>
);

View File

@@ -11,7 +11,7 @@ export default function ThemeToggle() {
}
return (
<div className="rounded-full flex self-end">
<div id="theme" className="rounded-full flex self-end">
<MdLightMode className="text-theme-800 dark:text-theme-200 w-5 h-5 m-1.5" />
{theme === "dark" ? (
<MdToggleOn

View File

@@ -25,7 +25,7 @@ export default function Version() {
const latestRelease = releaseData?.[0];
return (
<div className="flex flex-row items-center">
<div id="version" className="flex flex-row items-center">
<span className="text-xs text-theme-500 dark:text-theme-400">
{version === "main" || version === "dev" || version === "nightly" ? (
<>

View File

@@ -30,7 +30,7 @@ export default function DateTime({ options }) {
}, [date, setDate, dateLocale, format]);
return (
<Container options={options}>
<Container options={options} additionalClassNames="information-widget-datetime">
<Raw>
<div className="flex flex-row items-center grow justify-end">
<span className={`text-theme-800 dark:text-theme-200 tabular-nums ${textSizes[textSize || "lg"]}`}>

View File

@@ -3,6 +3,7 @@ import { useContext } from "react";
import { FaMemory, FaRegClock, FaThermometerHalf } from "react-icons/fa";
import { FiCpu, FiHardDrive } from "react-icons/fi";
import { useTranslation } from "next-i18next";
import classNames from "classnames";
import Error from "../widget/error";
import Resource from "../widget/resource";
@@ -32,9 +33,9 @@ export default function Widget({ options }) {
}
if (!data) {
return <Resources options={options}>
<Resource icon={FiCpu} label={t("glances.wait")} percentage="0" />
<Resource icon={FaMemory} label={t("glances.wait")} percentage="0" />
return <Resources options={options} additionalClassNames="information-widget-glances">
{ options.cpu !== false && <Resource icon={FiCpu} label={t("glances.wait")} percentage="0" /> }
{ options.mem !== false && <Resource icon={FaMemory} label={t("glances.wait")} percentage="0" /> }
{ options.cputemp && <Resource icon={FaThermometerHalf} label={t("glances.wait")} percentage="0" /> }
{ options.disk && !Array.isArray(options.disk) && <Resource key={options.disk} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> }
{ options.disk && Array.isArray(options.disk) && options.disk.map((disk) => <Resource key={`disk_${disk}`} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> ) }
@@ -69,9 +70,11 @@ export default function Widget({ options }) {
: [data.fs.find((d) => d.mnt_point === options.disk)].filter((d) => d);
}
const addedClasses = classNames('information-widget-glances', { 'expanded': options.expanded })
return (
<Resources options={options} target={settings.target ?? "_blank"}>
<Resource
<Resources options={options} target={settings.target ?? "_blank"} additionalClassNames={addedClasses}>
{options.cpu !== false && <Resource
icon={FiCpu}
value={t("common.number", {
value: data.cpu.total,
@@ -89,8 +92,8 @@ export default function Widget({ options }) {
expandedLabel={t("glances.load")}
percentage={data.cpu.total}
expanded={options.expanded}
/>
<Resource
/>}
{options.mem !== false && <Resource
icon={FaMemory}
value={t("common.bytes", {
value: data.mem.free,
@@ -106,7 +109,7 @@ export default function Widget({ options }) {
expandedLabel={t("glances.total")}
percentage={data.mem.percent}
expanded={options.expanded}
/>
/>}
{disks.map((disk) => (
<Resource key={`disk_${disk.mnt_point ?? disk.device_name}`}
icon={FiHardDrive}

View File

@@ -14,7 +14,7 @@ const textSizes = {
export default function Greeting({ options }) {
if (options.text) {
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-greeting">
<Raw>
<span className={`text-theme-800 dark:text-theme-200 mr-3 ${textSizes[options.text_size || "xl"]}`}>
{options.text}

View File

@@ -36,7 +36,7 @@ export default function Widget({ options }) {
}
if (!data) {
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-kubernetes">
<Raw>
<div className="flex flex-row self-center flex-wrap justify-between">
{cluster.show &&
@@ -50,7 +50,7 @@ export default function Widget({ options }) {
</Container>;
}
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-kubernetes">
<Raw>
<div className="flex flex-row self-center flex-wrap justify-between">
{cluster.show &&

View File

@@ -5,14 +5,14 @@ import ResolvedIcon from "components/resolvedicon"
export default function Logo({ options }) {
return (
<Container options={options}>
<Container options={options} additionalClassNames={`information-widget-logo ${ options.icon ? 'resolved' : 'fallback'}`}>
<Raw>
{options.icon ?
<div className="mr-3">
<div className="resolved mr-3">
<ResolvedIcon icon={options.icon} width={48} height={48} />
</div> :
// fallback to homepage logo
<div className="w-12 h-12">
<div className="fallback w-12 h-12">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1024 1024"

View File

@@ -17,14 +17,14 @@ export default function Longhorn({ options }) {
}
if (!data) {
return <Container options={options}>
return <Container options={options} additionalClassNames="infomation-widget-longhorn">
<Raw>
<div className="flex flex-row self-center flex-wrap justify-between" />
</Raw>
</Container>;
}
return <Container options={options}>
return <Container options={options} additionalClassNames="infomation-widget-longhorn">
<Raw>
<div className="flex flex-row self-center flex-wrap justify-between">
{data.nodes

View File

@@ -8,6 +8,7 @@ export default function Node({ data, expanded, labels }) {
const { t } = useTranslation();
return <Resource
additionalClassNames="information-widget-longhorn-node"
icon={FaThermometerHalf}
value={t("common.bytes", { value: data.node.available })}
label={t("resources.free")}

View File

@@ -24,7 +24,7 @@ function Widget({ options }) {
}
if (!data) {
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-openmeteo">
<PrimaryText>{t("weather.updating")}</PrimaryText>
<SecondaryText>{t("weather.wait")}</SecondaryText>
<WidgetIcon icon={WiCloudDown} size="l" />
@@ -35,7 +35,7 @@ function Widget({ options }) {
const condition = data.current_weather.weathercode;
const timeOfDay = data.current_weather.time > data.daily.sunrise[0] && data.current_weather.time < data.daily.sunset[0] ? "day" : "night";
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-openmeteo">
<PrimaryText>
{options.label && `${options.label}, `}
{t("common.number", {
@@ -81,7 +81,7 @@ export default function OpenMeteo({ options }) {
// if (!requesting && !location) requestLocation();
if (!location) {
return <ContainerButton options={options} callback={requestLocation} >
return <ContainerButton options={options} callback={requestLocation} additionalClassNames="information-widget-openmeteo-location-button">
<PrimaryText>{t("weather.current")}</PrimaryText>
<SecondaryText>{t("weather.allow")}</SecondaryText>
<WidgetIcon icon={ requesting ? MdLocationSearching : MdLocationDisabled} size="m" pulse />

View File

@@ -24,7 +24,7 @@ function Widget({ options }) {
}
if (!data) {
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-openweathermap">
<PrimaryText>{t("weather.updating")}</PrimaryText>
<SecondaryText>{t("weather.wait")}</SecondaryText>
<WidgetIcon icon={WiCloudDown} size="l" />
@@ -36,7 +36,7 @@ function Widget({ options }) {
const condition = data.weather[0].id;
const timeOfDay = data.dt > data.sys.sunrise && data.dt < data.sys.sunset ? "day" : "night";
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-openweathermap">
<PrimaryText>{options.label && `${options.label}, ` }{t("common.number", { value: data.main.temp, style: "unit", unit })}</PrimaryText>
<SecondaryText>{data.weather[0].description}</SecondaryText>
<WidgetIcon icon={mapIcon(condition, timeOfDay)} size="xl" />

View File

@@ -1,6 +1,6 @@
export default function UsageBar({ percent }) {
export default function UsageBar({ percent, additionalClassNames='' }) {
return (
<div className="mt-0.5 w-full bg-theme-800/30 rounded-full h-1 dark:bg-theme-200/20">
<div className={`mt-0.5 w-full bg-theme-800/30 rounded-full h-1 dark:bg-theme-200/20 ${additionalClassNames}`}>
<div
className="bg-theme-800/70 h-1 rounded-full dark:bg-theme-200/50 transition-all duration-1000"
style={{

View File

@@ -103,7 +103,7 @@ export default function Search({ options }) {
localStorage.setItem(localStorageKey, provider.name);
}
return <ContainerForm options={options} callback={submitCallback} additionalClassNames="grow" >
return <ContainerForm options={options} callback={submitCallback} additionalClassNames="grow information-widget-search" >
<Raw>
<div className="flex-col relative h-8 my-4 min-w-fit">
<div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-white" />

View File

@@ -25,7 +25,7 @@ export default function Widget({ options }) {
const defaultSite = options.site ? statsData?.data.find(s => s.desc === options.site) : statsData?.data?.find(s => s.name === "default");
if (!defaultSite) {
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-unifi-console">
<PrimaryText>{t("unifi.wait")}</PrimaryText>
<WidgetIcon icon={SiUbiquiti} />
</Container>;
@@ -43,7 +43,7 @@ export default function Widget({ options }) {
const dataEmpty = !(wan.show || lan.show || wlan.show || uptime);
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-unifi-console">
<Raw>
<div className="flex-none flex flex-row items-center mr-3 py-1.5">
<div className="flex flex-col">

View File

@@ -24,7 +24,7 @@ function Widget({ options }) {
}
if (!data) {
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-weather">
<PrimaryText>{t("weather.updating")}</PrimaryText>
<SecondaryText>{t("weather.wait")}</SecondaryText>
<WidgetIcon icon={WiCloudDown} size="l" />
@@ -35,7 +35,7 @@ function Widget({ options }) {
const condition = data.current.condition.code;
const timeOfDay = data.current.is_day ? "day" : "night";
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-weather">
<PrimaryText>
{options.label && `${options.label}, `}
{t("common.number", {

View File

@@ -9,11 +9,14 @@ export function getAllClasses(options, additionalClassNames = '') {
if (options?.style?.header === "boxedWidgets") {
if (options?.style?.cardBlur !== undefined) {
// eslint-disable-next-line no-param-reassign
additionalClassNames = additionalClassNames.concat(additionalClassNames, ` backdrop-blur${options.style.cardBlur.length ? '-' : ""}${options.style.cardBlur}`)
additionalClassNames = [
additionalClassNames,
`backdrop-blur${options.style.cardBlur.length ? '-' : ""}${options.style.cardBlur}`
].join(' ')
}
return classNames(
"flex flex-col justify-center first:ml-0 ml-2 mr-2",
"flex flex-col justify-center ml-2 mr-2",
"mt-2 m:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-2 pl-3 pr-3",
additionalClassNames
);
@@ -32,9 +35,9 @@ export function getAllClasses(options, additionalClassNames = '') {
export function getInnerBlock(children) {
// children won't be an array if it's Raw component
return Array.isArray(children) && <div className="flex flex-row items-center justify-end">
<div className="flex flex-col items-center">{children.find(child => child.type === WidgetIcon)}</div>
<div className="flex flex-col ml-3 text-left">
return Array.isArray(children) && <div className="flex flex-row items-center justify-end widget-inner">
<div className="flex flex-col items-center widget-inner-icon">{children.find(child => child.type === WidgetIcon)}</div>
<div className="flex flex-col ml-3 text-left widget-inner-text">
{children.find(child => child.type === PrimaryText)}
{children.find(child => child.type === SecondaryText)}
</div>
@@ -51,7 +54,7 @@ export function getBottomBlock(children) {
export default function Container({ children = [], options, additionalClassNames = '' }) {
return (
<div className={getAllClasses(options, additionalClassNames)}>
<div className={getAllClasses(options, `${ additionalClassNames } widget-container`)}>
{getInnerBlock(children)}
{getBottomBlock(children)}
</div>

View File

@@ -2,7 +2,7 @@ import { getAllClasses, getInnerBlock, getBottomBlock } from "./container";
export default function ContainerButton ({ children = [], options, additionalClassNames = '', callback }) {
return (
<button type="button" onClick={callback} className={getAllClasses(options, additionalClassNames)}>
<button type="button" onClick={callback} className={`${ getAllClasses(options, additionalClassNames) } information-widget-container-button`}>
{getInnerBlock(children)}
{getBottomBlock(children)}
</button>

View File

@@ -2,7 +2,7 @@ import { getAllClasses, getInnerBlock, getBottomBlock } from "./container";
export default function ContainerForm ({ children = [], options, additionalClassNames = '', callback }) {
return (
<form type="button" onSubmit={callback} className={getAllClasses(options, additionalClassNames)}>
<form type="button" onSubmit={callback} className={`${ getAllClasses(options, additionalClassNames) } information-widget-form`}>
{getInnerBlock(children)}
{getBottomBlock(children)}
</form>

View File

@@ -2,7 +2,7 @@ import { getAllClasses, getInnerBlock, getBottomBlock } from "./container";
export default function ContainerLink ({ children = [], options, additionalClassNames = '', target }) {
return (
<a href={options.url} target={target} className={getAllClasses(options, additionalClassNames)}>
<a href={options.url} target={target} className={`${ getAllClasses(options, additionalClassNames) } information-widget-link`}>
{getInnerBlock(children)}
{getBottomBlock(children)}
</a>

View File

@@ -8,7 +8,7 @@ import WidgetIcon from "./widget_icon";
export default function Error({ options }) {
const { t } = useTranslation();
return <Container options={options}>
return <Container options={options} additionalClassNames="information-widget-error">
<PrimaryText>{t("widget.api_error")}</PrimaryText>
<WidgetIcon icon={BiError} size="l" />
</Container>;

View File

@@ -1,5 +1,5 @@
export default function PrimaryText({ children }) {
return (
<span className="text-theme-800 dark:text-theme-200 text-sm">{children}</span>
<span className="primary-text text-theme-800 dark:text-theme-200 text-sm">{children}</span>
);
}

View File

@@ -1,11 +1,11 @@
import UsageBar from "../resources/usage-bar";
export default function Resource({ children, icon, value, label, expandedValue = "", expandedLabel = "", percentage, expanded = false }) {
export default function Resource({ children, icon, value, label, expandedValue = "", expandedLabel = "", percentage, expanded = false, additionalClassNames='' }) {
const Icon = icon;
return <div className="flex-none flex flex-row items-center mr-3 py-1.5">
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5"/>
<div className="flex flex-col ml-3 text-left min-w-[85px]">
return <div className={`flex-none flex flex-row items-center mr-3 py-1.5 information-widget-resource ${ additionalClassNames }`}>
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon"/>
<div className={ `flex flex-col ml-3 text-left min-w-[85px] ${ expanded ? ' expanded' : ''}`}>
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
<div className="pl-0.5">{value}</div>
<div className="pr-1">{label}</div>
@@ -15,7 +15,7 @@ export default function Resource({ children, icon, value, label, expandedValue =
<div className="pr-1">{expandedLabel}</div>
</div>
}
{ percentage >= 0 && <UsageBar percent={percentage} /> }
{ percentage >= 0 && <UsageBar percent={percentage} additionalClassNames="resource-usage" /> }
{ children }
</div>
</div>;

View File

@@ -1,12 +1,15 @@
import classNames from "classnames";
import ContainerLink from "./container_link";
import Resource from "./resource";
import Raw from "./raw";
import WidgetLabel from "./widget_label";
export default function Resources({ options, children, target }) {
export default function Resources({ options, children, target, additionalClassNames }) {
const widgetParts = [].concat(...children);
const addedClassNames = classNames('information-widget-resources', additionalClassNames);
return <ContainerLink options={options} target={target}>
return <ContainerLink options={options} target={target} additionalClassNames={ addedClassNames }>
<Raw>
<div className="flex flex-row self-center flex-wrap justify-between">
{ widgetParts.filter(child => child && child.type === Resource) }

View File

@@ -1,5 +1,5 @@
export default function SecondaryText({ children }) {
return (
<span className="text-theme-800 dark:text-theme-200 text-xs">{children}</span>
<span className="secondary-text text-theme-800 dark:text-theme-200 text-xs">{children}</span>
);
}

View File

@@ -1,6 +1,6 @@
export default function WidgetIcon({ icon, size = "s", pulse = false }) {
const Icon = icon;
let additionalClasses = "text-theme-800 dark:text-theme-200 ";
let additionalClasses = "information-widget-icon text-theme-800 dark:text-theme-200 ";
switch (size) {
case "m": additionalClasses += "w-6 h-6 "; break;

View File

@@ -1,3 +1,3 @@
export default function WidgetLabel({ label = "" }) {
return <div className="pt-1 text-center text-theme-800 dark:text-theme-200 text-xs">{label}</div>
return <div className="information-widget-label pt-1 text-center text-theme-800 dark:text-theme-200 text-xs">{label}</div>
}

View File

@@ -11,6 +11,7 @@ import nextI18nextConfig from "../../next-i18next.config";
import { ColorProvider } from "utils/contexts/color";
import { ThemeProvider } from "utils/contexts/theme";
import { SettingsProvider } from "utils/contexts/settings";
import { TabProvider } from "utils/contexts/tab";
function MyApp({ Component, pageProps }) {
return (
@@ -26,7 +27,9 @@ function MyApp({ Component, pageProps }) {
<ColorProvider>
<ThemeProvider>
<SettingsProvider>
<Component {...pageProps} />
<TabProvider>
<Component {...pageProps} />
</TabProvider>
</SettingsProvider>
</ThemeProvider>
</ColorProvider>

View File

@@ -9,7 +9,7 @@ export default function Document() {
content="A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations."
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="manifest" href="/site.webmanifest?v=4" />
<link rel="manifest" href="/site.webmanifest?v=4" crossOrigin="use-credentials" />
<link rel="mask-icon" href="/safari-pinned-tab.svg?v=4" color="#1e9cd7" />
</Head>
<body>

View File

@@ -0,0 +1,35 @@
import path from "path";
import fs from "fs";
import { CONF_DIR } from "utils/config/config";
import createLogger from "utils/logger";
const logger = createLogger("configFileService");
/**
* @param {import("next").NextApiRequest} req
* @param {import("next").NextApiResponse} res
*/
export default async function handler(req, res) {
const { path: relativePath } = req.query;
// only two supported files, for now
if (!['custom.css', 'custom.js'].includes(relativePath))
{
return res.status(422).end('Unsupported file');
}
const filePath = path.join(CONF_DIR, relativePath);
try {
// Read the content of the file or return empty content
const fileContent = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf-8') : '';
// hard-coded since we only support two known files for now
const mimeType = (relativePath === 'custom.css') ? 'text/css' : 'text/javascript';
res.setHeader('Content-Type', mimeType);
return res.status(200).send(fileContent);
} catch (error) {
logger.error(error);
return res.status(500).end('Internal Server Error');
}
}

View File

@@ -4,7 +4,7 @@ import { readFileSync } from "fs";
import checkAndCopyConfig, { CONF_DIR } from "utils/config/config";
const configs = ["docker.yaml", "settings.yaml", "services.yaml", "bookmarks.yaml", "widgets.yaml"];
const configs = ["docker.yaml", "settings.yaml", "services.yaml", "bookmarks.yaml", "widgets.yaml", "custom.css", "custom.js"];
function hash(buffer) {
const hashSum = createHash("sha256");

View File

@@ -4,10 +4,13 @@ import Head from "next/head";
import dynamic from "next/dynamic";
import classNames from "classnames";
import { useTranslation } from "next-i18next";
import { useEffect, useContext, useState } from "react";
import { useEffect, useContext, useState, useMemo } from "react";
import { BiError } from "react-icons/bi";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { useRouter } from "next/router";
import Tab, { slugify } from "components/tab";
import FileContent from "components/filecontent";
import ServicesGroup from "components/services/group";
import BookmarksGroup from "components/bookmarks/group";
import Widget from "components/widgets/widget";
@@ -18,6 +21,7 @@ import { getSettings } from "utils/config/config";
import { ColorContext } from "utils/contexts/color";
import { ThemeContext } from "utils/contexts/theme";
import { SettingsContext } from "utils/contexts/settings";
import { TabContext } from "utils/contexts/tab";
import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response";
import ErrorBoundary from "components/errorboundry";
import themes from "utils/styles/themes";
@@ -157,10 +161,10 @@ function Index({ initialSettings, fallback }) {
const headerStyles = {
boxed:
"m-4 mb-0 sm:m-8 sm:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-3",
underlined: "m-4 mb-0 sm:m-8 sm:mb-1 border-b-2 pb-4 border-theme-800 dark:border-theme-200/50",
clean: "m-4 mb-0 sm:m-8 sm:mb-0",
boxedWidgets: "m-4 mb-0 sm:m-8 sm:mb-0 sm:mt-1",
"m-6 mb-0 sm:m-9 sm:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-3",
underlined: "m-6 mb-0 sm:m-9 sm:mb-1 border-b-2 pb-4 border-theme-800 dark:border-theme-200/50",
clean: "m-6 mb-0 sm:m-9 sm:mb-0",
boxedWidgets: "m-6 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
};
function Home({ initialSettings }) {
@@ -168,6 +172,8 @@ function Home({ initialSettings }) {
const { theme, setTheme } = useContext(ThemeContext);
const { color, setColor } = useContext(ColorContext);
const { settings, setSettings } = useContext(SettingsContext);
const { activeTab, setActiveTab } = useContext(TabContext);
const { asPath } = useRouter();
useEffect(() => {
setSettings(initialSettings);
@@ -209,12 +215,12 @@ function Home({ initialSettings }) {
searchProvider = searchProviders[searchWidget.options?.provider];
}
}
const headerStyle = initialSettings?.headerStyle || "underlined";
const headerStyle = settings?.headerStyle || "underlined";
useEffect(() => {
function handleKeyDown(e) {
if (e.target.tagName === "BODY") {
if (String.fromCharCode(e.keyCode).match(/(\w|\s)/g) && !(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)) {
if (e.target.tagName === "BODY" || e.target.id === "inner_wrapper") {
if (e.key.match(/(\w|\s)/g) && !(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.code === "Tab")) {
setSearching(true);
} else if (e.key === "Escape") {
setSearchString("");
@@ -230,15 +236,110 @@ function Home({ initialSettings }) {
}
})
const tabs = useMemo( () => [
...new Set(
Object.keys(settings.layout ?? {}).map(
(groupName) => settings.layout[groupName]?.tab?.toString()
).filter(group => group)
)
], [settings.layout]);
useEffect(() => {
if (!activeTab) {
const initialTab = decodeURI(asPath.substring(asPath.indexOf("#") + 1));
setActiveTab(initialTab === '/' ? slugify(tabs['0']) : initialTab)
}
})
const servicesAndBookmarksGroups = useMemo(() => {
const tabGroupFilter = g => g && [activeTab, ''].includes(slugify(settings.layout?.[g.name]?.tab));
const undefinedGroupFilter = g => settings.layout?.[g.name] === undefined;
const layoutGroups = Object.keys(settings.layout ?? {}).map(
(groupName) => services?.find(g => g.name === groupName) ?? bookmarks?.find(b => b.name === groupName)
).filter(tabGroupFilter);
if (!settings.layout && JSON.stringify(settings.layout) !== JSON.stringify(initialSettings.layout)) {
// wait for settings to populate (if different from initial settings), otherwise all the widgets will be requested initially even if we are on a single tab
return <div />;
}
const serviceGroups = services?.filter(tabGroupFilter).filter(undefinedGroupFilter);
const bookmarkGroups = bookmarks.filter(tabGroupFilter).filter(undefinedGroupFilter);
return <>
{tabs.length > 0 && <div key="tabs" id="tabs" className="m-6 sm:m-9 sm:mt-4 sm:mb-0">
<ul className={classNames(
"sm:flex rounded-md bg-theme-100/20 dark:bg-white/5",
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-': "" }${settings.cardBlur}`
)} id="myTab" data-tabs-toggle="#myTabContent" role="tablist" >
{tabs.map(tab => <Tab key={tab} tab={tab} />)}
</ul>
</div>}
{layoutGroups.length > 0 && <div key="layoutGroups" id="layout-groups" className="flex flex-wrap m-4 sm:m-8 sm:mt-4 items-start mb-2">
{layoutGroups.map((group) => (
group.services ?
(<ServicesGroup
key={group.name}
group={group.name}
services={group}
layout={settings.layout?.[group.name]}
fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse}
/>) :
(<BookmarksGroup
key={group.name}
bookmarks={group}
layout={settings.layout?.[group.name]}
disableCollapse={settings.disableCollapse}
/>)
)
)}
</div>}
{serviceGroups?.length > 0 && <div key="services" id="services" className="flex flex-wrap m-4 sm:m-8 sm:mt-4 items-start mb-2">
{serviceGroups.map((group) => (
<ServicesGroup
key={group.name}
group={group.name}
services={group}
layout={settings.layout?.[group.name]}
fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse}
/>
))}
</div>}
{bookmarkGroups?.length > 0 && <div key="bookmarks" id="bookmarks" className="flex flex-wrap m-4 sm:m-8 sm:mt-4 items-start mb-2">
{bookmarkGroups.map((group) => (
<BookmarksGroup
key={group.name}
bookmarks={group}
layout={settings.layout?.[group.name]}
disableCollapse={settings.disableCollapse}
/>
))}
</div>}
</>
}, [
tabs,
activeTab,
services,
bookmarks,
settings.layout,
settings.fiveColumns,
settings.disableCollapse,
settings.cardBlur,
initialSettings.layout
]);
return (
<>
<Head>
<title>{initialSettings.title || "Homepage"}</title>
{initialSettings.base && <base href={initialSettings.base} />}
{initialSettings.favicon ? (
<title>{settings.title || "Homepage"}</title>
{settings.base && <base href={settings.base} />}
{settings.favicon ? (
<>
<link rel="apple-touch-icon" sizes="180x180" href={initialSettings.favicon} />
<link rel="icon" href={initialSettings.favicon} />
<link rel="apple-touch-icon" sizes="180x180" href={settings.favicon} />
<link rel="icon" href={settings.favicon} />
</>
) : (
<>
@@ -248,84 +349,78 @@ function Home({ initialSettings }) {
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png?v=4" />
</>
)}
<meta
name="msapplication-TileColor"
content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]}
/>
<meta name="theme-color" content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]} />
<meta name="msapplication-TileColor" content={themes[settings.color || "slate"][settings.theme || "dark"]} />
<meta name="theme-color" content={themes[settings.color || "slate"][settings.theme || "dark"]} />
</Head>
<link rel="preload" href="/api/config/custom.css" as="fetch" crossOrigin="anonymous" />
<style data-name="custom.css">
<FileContent path="custom.css"
loadingValue="/* Loading custom CSS... */"
errorValue="/* Failed to load custom CSS... */"
emptyValue="/* No custom CSS */"
/>
</style>
<link rel="preload" href="/api/config/custom.js" as="fetch" crossOrigin="anonymous" />
<script data-name="custom.js" src="/api/config/custom.js" async="{true}" />
<div className="relative container m-auto flex flex-col justify-start z-10 h-full">
<QuickLaunch
servicesAndBookmarks={servicesAndBookmarks}
searchString={searchString}
setSearchString={setSearchString}
isOpen={searching}
close={setSearching}
searchProvider={settings.quicklaunch?.hideInternetSearch ? null : searchProvider}
/>
<div
id="information-widgets"
className={classNames(
"flex flex-row flex-wrap justify-between",
headerStyles[headerStyle],
initialSettings.cardBlur !== undefined && headerStyle === "boxed" && `backdrop-blur${initialSettings.cardBlur.length ? '-' : ""}${initialSettings.cardBlur}`
settings.cardBlur !== undefined && headerStyle === "boxed" && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`
)}
>
<QuickLaunch
servicesAndBookmarks={servicesAndBookmarks}
searchString={searchString}
setSearchString={setSearchString}
isOpen={searching}
close={setSearching}
searchProvider={settings.quicklaunch?.hideInternetSearch ? null : searchProvider}
/>
{widgets && (
<>
{widgets
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false, cardBlur: initialSettings.cardBlur }} />
))}
<div className={classNames(
"m-auto flex flex-wrap grow sm:basis-auto justify-between md:justify-end",
headerStyle === "boxedWidgets" ? "sm:ml-4" : "sm:ml-2"
)}>
<div id="widgets-wrap"
style={{width: 'calc(100% + 1rem)'}}
className={classNames(
"flex flex-row w-full flex-wrap justify-between -ml-2 -mr-2"
)}
>
{widgets && (
<>
{widgets
.filter((widget) => rightAlignedWidgets.includes(widget.type))
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true, cardBlur: initialSettings.cardBlur }} />
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false, cardBlur: settings.cardBlur }} />
))}
</div>
</>
)}
<div id="information-widgets-right" className={classNames(
"m-auto flex flex-wrap grow sm:basis-auto justify-between md:justify-end",
headerStyle === "boxedWidgets" ? "sm:ml-4" : "sm:ml-2"
)}>
{widgets
.filter((widget) => rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true, cardBlur: settings.cardBlur }} />
))}
</div>
</>
)}
</div>
</div>
{services?.length > 0 && (
<div className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
{services.map((group) => (
<ServicesGroup
key={group.name}
group={group.name}
services={group}
layout={initialSettings.layout?.[group.name]}
fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse} />
))}
</div>
)}
{servicesAndBookmarksGroups}
{bookmarks?.length > 0 && (
<div className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(6, bookmarks.length)}`}>
{bookmarks.map((group) => (
<BookmarksGroup
key={group.name}
group={group}
disableCollapse={settings.disableCollapse} />
))}
</div>
)}
<div className="flex flex-col mt-auto p-8 w-full">
<div className="flex w-full justify-end">
{!initialSettings?.color && <ColorToggle />}
<div id="footer" className="flex flex-col mt-auto p-8 w-full">
<div id="style" className="flex w-full justify-end">
{!settings?.color && <ColorToggle />}
<Revalidate />
{!initialSettings?.theme && <ThemeToggle />}
{!settings.theme && <ThemeToggle />}
</div>
<div className="flex mt-4 w-full justify-end">
{!initialSettings?.hideVersion && <Version />}
<div id="version" className="flex mt-4 w-full justify-end">
{!settings.hideVersion && <Version />}
</div>
</div>
</div>
@@ -375,6 +470,7 @@ export default function Wrapper({ initialSettings, fallback }) {
>
<div
id="inner_wrapper"
tabIndex="-1"
className={classNames(
'fixed overflow-auto w-full h-full',
backgroundBlur && `backdrop-blur${initialSettings.background.blur.length ? '-' : ""}${initialSettings.background.blur}`,

Some files were not shown because too many files have changed in this diff Show More