Compare commits

...

42 Commits

Author SHA1 Message Date
shamoon
0ae13d8ed3 Merge pull request #1335 from benphelps/5th-column-setting
Move 5th column behind setting
2023-04-07 22:42:42 -07:00
shamoon
91646888cd Move 5th column behind setting 2023-04-07 22:35:42 -07:00
shamoon
0416f53c04 Update group.jsx 2023-04-07 22:28:19 -07:00
shamoon
6dcec48669 Merge pull request #1334 from benphelps/feature-stats-control
Feature: Global & per-service docker stats control
2023-04-07 21:55:17 -07:00
shamoon
7e012993d8 Support per-service stats control 2023-04-07 21:34:33 -07:00
G. Petrakis
1a374dec3c Translated using Weblate (Greek)
Currently translated at 27.2% (110 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/el/
2023-04-08 04:49:31 +02:00
Felipe Nogueira
e6dd4f20a3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.0% (395 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt_BR/
2023-04-08 04:49:30 +02:00
zxb0303
336aa26263 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.2% (400 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2023-04-08 04:49:30 +02:00
Felipe Nogueira
fc05808fb2 Translated using Weblate (Portuguese)
Currently translated at 98.0% (395 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2023-04-08 04:49:30 +02:00
David Tornero
612d533a38 Translated using Weblate (Spanish)
Currently translated at 100.0% (403 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-04-08 04:49:29 +02:00
shamoon
7aa496f66f Update item.jsx 2023-04-06 21:53:49 -07:00
shamoon
48224f89a4 Allow show docker stats by default 2023-04-06 20:38:39 -07:00
shamoon
e4788cc7f6 Fix widget option boolean parsing with docker labels 2023-04-06 20:18:06 -07:00
shamoon
4824ed1a2c Fix data buffer parsing error 2023-04-06 07:03:06 -07:00
shamoon
cd95c93e68 Increase breakpoint for 5 columns 2023-04-05 23:25:08 -07:00
shamoon
379d2e59f1 preserve swr mutate 2023-04-05 22:45:27 -07:00
shamoon
64b43871c6 Try to fix false data parse errors 2023-04-05 22:17:52 -07:00
shamoon
5c84b90634 Rename discussion template 2023-04-05 16:19:27 -07:00
shamoon
4e138e3d0f Move FR template to discussion ,add config 2023-04-05 16:13:22 -07:00
Anonymous
8b38f12452 Translated using Weblate (Greek)
Currently translated at 100.0% (0 of 0 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/el/
2023-04-05 21:34:11 +02:00
Przemek
b3ea7b816d Translated using Weblate (Polish)
Currently translated at 72.2% (291 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/
2023-04-05 21:33:57 +02:00
Juan Manuel Bennàssar Carretero
1bec7897f0 Translated using Weblate (Catalan)
Currently translated at 64.0% (258 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2023-04-05 21:33:56 +02:00
Nonoss117
98422a0727 Translated using Weblate (French)
Currently translated at 99.5% (401 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2023-04-05 21:33:56 +02:00
David Tornero
57c145c3d2 Translated using Weblate (Spanish)
Currently translated at 100.0% (403 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-04-05 21:33:56 +02:00
Juan Manuel Bennàssar Carretero
43233cf446 Translated using Weblate (Spanish)
Currently translated at 100.0% (403 of 403 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-04-05 21:33:55 +02:00
G. Petrakis
187df778bf Added translation using Weblate (Greek) 2023-04-05 21:32:53 +02:00
shamoon
d7dc328cdc Merge pull request #1191 from benphelps/feature/987
Add 5th column for 2xl screens
2023-04-05 08:54:41 -07:00
shamoon
066995702b Add 5th column for 2xl screens 2023-04-05 08:53:28 -07:00
shamoon
777c78363d Merge pull request #1187 from benphelps/fix-576-final
True fix for settings revert after container creation
2023-04-04 23:08:13 -07:00
shamoon
6701e3bd77 Use HOMEPAGE_BUILDTIME to revalidate container restart/recreate 2023-04-04 22:55:26 -07:00
shamoon
a42c50f1cc fix emby widget options interpolation 2023-04-04 19:08:52 -07:00
shamoon
2fbe4e5f24 Update cputemp.jsx 2023-04-04 17:05:22 -07:00
shamoon
a0fa6367ca Merge pull request #1161 from MrLemur/add-traefik-ingressroute
Feature: Add Traefik IngressRoute support for Kubernetes
2023-04-04 15:56:38 -07:00
shamoon
8378066bd4 Merge pull request #1182 from benphelps/fix-1181
Fix emby/jellyfin now playing > 1
2023-04-04 15:04:16 -07:00
shamoon
db85193bbf Fix emby/jellyfin now playing > 1 2023-04-04 15:00:09 -07:00
shamoon
364c7ce183 make osx-temperature-sensor optional 2023-04-04 14:27:44 -07:00
shamoon
48180604f9 Fix jellyfin / emby blocks boolean evaluation 2023-04-04 00:55:05 -07:00
shamoon
88089a8a11 Merge pull request #1174 from benphelps/fix-memory-calc
Fix memory display in v0.6.11
2023-04-03 23:29:12 -07:00
shamoon
2829f0b649 Update memory.jsx 2023-04-03 23:22:28 -07:00
shamoon
0d5856db1e Merge pull request #1172 from benphelps/cpu-temp-fixes
Fix glances cpu temp detection & fahrenheit conversion
2023-04-03 21:50:23 -07:00
shamoon
f3ec238a2c Fix glances cpu temp detection & fahrenheit conversion 2023-04-03 21:49:28 -07:00
Kassim Benhaddad
df714c7556 feat: add Traefik IngressRoute support for k8s 2023-03-29 23:19:56 +01:00
28 changed files with 719 additions and 91 deletions

View File

@@ -1,5 +1,3 @@
name: Feature request
description: Suggest an idea for this project
title: "[Feature Request] "
labels: ["enhancement"]
body:

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 🤔 Questions and Help
url: https://github.com/benphelps/homepage/discussions
about: This issue tracker is for bugs only, not general support questions. Please refer to our Discussions.
- name: 💬 Chat
url: https://discord.gg/k4ruYNrudu
about: Want to discuss homepage with others? Check out our chat.
- name: 🚀 Feature Request
url: https://github.com/benphelps/homepage/discussions/new?category=feature-requests
about: Remember to search for existing feature requests and "up-vote" any you like

View File

@@ -29,7 +29,7 @@ COPY . .
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
RUN npm run telemetry \
&& mkdir config && echo '---' > config/settings.yaml \
&& mkdir config \
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
# Production image, copy all the files and run next

View File

@@ -10,6 +10,8 @@ export PGID=${PGID:-0}
# while also supporting the lscr.io /config directory
[ ! -d "/app/config" ] && ln -s /config /app/config
export HOMEPAGE_BUILDTIME=$(date +%s)
# Set privileges for /app but only if pid 1 user is root and we are dropping privileges.
# If container is run as an unprivileged user, it means owner already handled ownership setup on their own.
# Running chown in that case (as non-root) will cause error

6
package-lock.json generated
View File

@@ -21,7 +21,7 @@
"minecraft-ping-js": "^1.0.2",
"next": "^12.3.1",
"next-i18next": "^12.0.1",
"osx-temperature-sensor": "^1.0.8",
"osx-temperature-sensor": "*",
"pretty-bytes": "^6.0.0",
"raw-body": "^2.5.1",
"react": "^18.2.0",
@@ -52,6 +52,9 @@
"tailwind-scrollbar": "^2.0.1",
"tailwindcss": "^3.1.8",
"typescript": "^4.8.3"
},
"optionalDependencies": {
"osx-temperature-sensor": "^1.0.8"
}
},
"node_modules/@babel/runtime": {
@@ -4034,6 +4037,7 @@
"resolved": "https://registry.npmjs.org/osx-temperature-sensor/-/osx-temperature-sensor-1.0.8.tgz",
"integrity": "sha512-Gl3b+bn7+oDDnqPa+4v/cg3yg9lnE8ppS7ivL3opBZh4i7h99JNmkm6zWmo0m2a83UUJu+C9D7lGP0OS8IlehA==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],

View File

@@ -23,7 +23,6 @@
"minecraft-ping-js": "^1.0.2",
"next": "^12.3.1",
"next-i18next": "^12.0.1",
"osx-temperature-sensor": "^1.0.8",
"pretty-bytes": "^6.0.0",
"raw-body": "^2.5.1",
"react": "^18.2.0",
@@ -54,5 +53,8 @@
"tailwind-scrollbar": "^2.0.1",
"tailwindcss": "^3.1.8",
"typescript": "^4.8.3"
},
"optionalDependencies": {
"osx-temperature-sensor": "^1.0.8"
}
}

14
pnpm-lock.yaml generated
View File

@@ -40,9 +40,6 @@ dependencies:
next-i18next:
specifier: ^12.0.1
version: 12.1.0(next@12.3.4)(react-dom@18.2.0)(react@18.2.0)
osx-temperature-sensor:
specifier: ^1.0.8
version: 1.0.8
pretty-bytes:
specifier: ^6.0.0
version: 6.1.0
@@ -80,6 +77,11 @@ dependencies:
specifier: ^1.6.11
version: 1.6.11
optionalDependencies:
osx-temperature-sensor:
specifier: ^1.0.8
version: 1.0.8
devDependencies:
'@tailwindcss/forms':
specifier: ^0.5.3
@@ -645,6 +647,7 @@ packages:
/autoprefixer@10.4.14(postcss@8.4.21):
resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
postcss: ^8.1.0
dependencies:
@@ -1221,6 +1224,7 @@ packages:
/eslint-config-prettier@8.8.0(eslint@8.37.0):
resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
dependencies:
@@ -2374,6 +2378,7 @@ packages:
/next@12.3.4(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-VcyMJUtLZBGzLKo3oMxrEF0stxh8HwuW976pAzlHhI3t8qJ4SROjCrSh1T24bhrbjw55wfZXAbXPGwPt5FLRfQ==}
engines: {node: '>=12.22.0'}
hasBin: true
peerDependencies:
fibers: '>= 3.1.0'
node-sass: ^6.0.0 || ^7.0.0
@@ -2574,6 +2579,7 @@ packages:
os: [darwin]
requiresBuild: true
dev: false
optional: true
/p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
@@ -3229,6 +3235,7 @@ packages:
/tailwindcss@3.3.0(postcss@8.4.21):
resolution: {integrity: sha512-hOXlFx+YcklJ8kXiCAfk/FMyr4Pm9ck477G0m/us2344Vuj355IpoEDB5UmGAsSpTBmr+4ZhjzW04JuFXkb/fw==}
engines: {node: '>=12.13.0'}
hasBin: true
peerDependencies:
postcss: ^8.0.9
dependencies:
@@ -3450,6 +3457,7 @@ packages:
/update-browserslist-db@1.0.10(browserslist@4.21.5):
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
dependencies:

View File

@@ -183,7 +183,7 @@
"qbittorrent": {
"download": "Descàrrega",
"upload": "Pujada",
"leech": "Company",
"leech": "Companys",
"seed": "Llavors"
},
"mastodon": {

View File

@@ -0,0 +1,566 @@
{
"resources": {
"used": "χρησιμοποιημένο",
"load": "Φόρτωση",
"cpu": "CPU",
"mem": "MEM",
"temp": "ΘΕΡΜΟΚΡΑΣΪΑ",
"total": "Σύνολο",
"free": "Δωρεάν",
"max": "Μέγιστο",
"uptime": "ΠΑΝΩ",
"months": "mo",
"days": "d",
"hours": "h",
"minutes": "m"
},
"omada": {
"activeUser": "Ενεργές συσκευές",
"alerts": "Ειδοποιήσεις",
"connectedAp": "Συνδεδεμένα APs",
"connectedGateway": "Συνδεδεμένα gateways",
"connectedSwitches": "Συνδεδεμένα switches"
},
"wmo": {
"0-night": "Clear",
"65-day": "Heavy Rain",
"65-night": "Heavy Rain",
"0-day": "Sunny",
"1-day": "Mainly Sunny",
"1-night": "Mainly Clear",
"2-day": "Partly Cloudy",
"2-night": "Partly Cloudy",
"3-day": "Cloudy",
"3-night": "Cloudy",
"45-day": "Foggy",
"45-night": "Foggy",
"48-day": "Foggy",
"48-night": "Foggy",
"51-day": "Light Drizzle",
"51-night": "Light Drizzle",
"53-day": "Drizzle",
"53-night": "Drizzle",
"55-day": "Heavy Drizzle",
"55-night": "Heavy Drizzle",
"56-day": "Light Freezing Drizzle",
"56-night": "Light Freezing Drizzle",
"57-day": "Freezing Drizzle",
"57-night": "Freezing Drizzle",
"61-day": "Light Rain",
"61-night": "Light Rain",
"63-day": "Rain",
"63-night": "Rain",
"66-day": "Freezing Rain",
"66-night": "Freezing Rain",
"67-day": "Freezing Rain",
"67-night": "Freezing Rain",
"71-day": "Light Snow",
"71-night": "Light Snow",
"73-day": "Snow",
"73-night": "Snow",
"75-day": "Heavy Snow",
"75-night": "Heavy Snow",
"77-day": "Snow Grains",
"77-night": "Snow Grains",
"80-day": "Light Showers",
"80-night": "Light Showers",
"81-day": "Showers",
"81-night": "Showers",
"82-day": "Heavy Showers",
"82-night": "Heavy Showers",
"85-day": "Snow Showers",
"85-night": "Snow Showers",
"86-day": "Snow Showers",
"86-night": "Snow Showers",
"95-day": "Thunderstorm",
"95-night": "Thunderstorm",
"96-day": "Thunderstorm With Hail",
"96-night": "Thunderstorm With Hail",
"99-day": "Thunderstorm With Hail",
"99-night": "Thunderstorm With Hail"
},
"common": {
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
},
"widget": {
"missing_type": "Λείπει ο τύπος widget: {{type}}",
"api_error": "Σφάλμα API",
"information": "Πληροφορία",
"status": "Κατάσταση",
"url": "URL",
"raw_error": "Ανεπεξέργαστο σφάλμα",
"response_data": "Δεδομένα απόκρισης"
},
"weather": {
"current": "Τωρινή τοποθεσία",
"allow": "Κάντε κλικ για να επιτρέψετε",
"updating": "Ενημέρωση",
"wait": "Παρακαλώ περιμένετε"
},
"search": {
"placeholder": "Αναζήτηση…"
},
"unifi": {
"users": "Χρήστες",
"uptime": "Χρόνος λειτουργίας συστήματος",
"days": "Ημέρες",
"wan": "WAN",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Συσκευές",
"lan_devices": "LAN Συσκευές",
"wlan_devices": "WLAN Συσκευές",
"lan_users": "LAN Χρήστες",
"wlan_users": "WLAN Χρήστες",
"up": "ΠΑΝΩ",
"down": "ΚΑΤΩ",
"wait": "Παρακαλώ περιμένετε",
"empty_data": "Άγνωστη κατάσταση υποσυστήματος"
},
"docker": {
"rx": "RX",
"tx": "TX",
"mem": "MEM",
"cpu": "CPU",
"running": "Τρέχων",
"offline": "Εκτός σύνδεσης",
"error": "Σφάλμα",
"unknown": "Άγνωστο",
"healthy": "Υγειές",
"exited": "Έκλεισε",
"starting": "Ξεκινάει",
"partial": "Μερικό",
"unhealthy": "Άρρωστο",
"not_found": "Δεν βρέθηκε"
},
"ping": {
"error": "Σφάλμα",
"ping": "Ping"
},
"emby": {
"playing": "Παίζει",
"transcoding": "Διακωδικοποίηση",
"bitrate": "Ρυθμός bit",
"no_active": "Δεν υπάρχουν ενεργές ροές",
"movies": "Ταινίες",
"series": "Σειρές",
"episodes": "Επεισόδια",
"songs": "Τραγούδια"
},
"flood": {
"download": "Κατέβασμα",
"upload": "Ανέβασμα",
"leech": "Αφαίμαξη",
"seed": "Σπείρε"
},
"changedetectionio": {
"totalObserved": "Συνολικά παρατηρηθείσα",
"diffsDetected": "Εντοπίστηκαν διαφορές"
},
"tautulli": {
"playing": "Παίζει",
"transcoding": "Διακωδικοποίηση",
"bitrate": "Ρυθμός bit",
"no_active": "Δεν υπάρχουν ενεργές ροές"
},
"nzbget": {
"rate": "βαθμός",
"remaining": "Υπόλοιπο",
"downloaded": "Κατεβασμένο"
},
"plex": {
"streams": "Ενεργά Streams",
"movies": "Ταινίες",
"tv": "Σειρές"
},
"sabnzbd": {
"rate": "Βαθμός",
"queue": "Ουρά",
"timeleft": "Χρόνος που απομένει"
},
"rutorrent": {
"active": "Ενεργό",
"upload": "Ανέβασμα",
"download": "Κατέβασμα"
},
"transmission": {
"download": "Κατέβασμα",
"upload": "Ανέβασμα",
"leech": "Leech",
"seed": "Seed"
},
"qbittorrent": {
"download": "Κατέβασμα",
"upload": "Ανέβασμα",
"leech": "Leech",
"seed": "Seed"
},
"deluge": {
"download": "Κατέβασμα",
"upload": "Upload",
"leech": "Leech",
"seed": "Seed"
},
"sonarr": {
"series": "Series",
"wanted": "Wanted",
"queued": "Queued"
},
"downloadstation": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"seed": "Seed"
},
"radarr": {
"wanted": "Wanted",
"missing": "Missing",
"queued": "Queued",
"movies": "Movies"
},
"lidarr": {
"wanted": "Wanted",
"queued": "Queued",
"albums": "Albums"
},
"readarr": {
"wanted": "Wanted",
"queued": "Queued",
"books": "Books"
},
"bazarr": {
"missingEpisodes": "Missing Episodes",
"missingMovies": "Missing Movies"
},
"ombi": {
"pending": "Pending",
"approved": "Approved",
"available": "Available"
},
"jellyseerr": {
"pending": "Pending",
"approved": "Approved",
"available": "Available"
},
"overseerr": {
"pending": "Pending",
"processing": "Processing",
"approved": "Approved",
"available": "Available"
},
"pihole": {
"queries": "Queries",
"blocked": "Blocked",
"gravity": "Gravity"
},
"adguard": {
"queries": "Queries",
"blocked": "Blocked",
"filtered": "Filtered",
"latency": "Latency"
},
"speedtest": {
"upload": "Upload",
"download": "Download",
"ping": "Ping"
},
"portainer": {
"running": "Running",
"stopped": "Stopped",
"total": "Total"
},
"tdarr": {
"queue": "Queue",
"processed": "Processed",
"errored": "Errored",
"saved": "Saved"
},
"traefik": {
"routers": "Routers",
"services": "Services",
"middleware": "Middleware"
},
"navidrome": {
"nothing_streaming": "No Active Streams",
"please_wait": "Please Wait"
},
"npm": {
"enabled": "Enabled",
"disabled": "Disabled",
"total": "Total"
},
"coinmarketcap": {
"configure": "Configure one or more crypto currencies to track",
"1hour": "1 Hour",
"1day": "1 Day",
"7days": "7 Days",
"30days": "30 Days"
},
"gotify": {
"apps": "Applications",
"clients": "Clients",
"messages": "Messages"
},
"prowlarr": {
"enableIndexers": "Indexers",
"numberOfGrabs": "Grabs",
"numberOfQueries": "Queries",
"numberOfFailGrabs": "Fail Grabs",
"numberOfFailQueries": "Fail Queries"
},
"strelaysrv": {
"numActiveSessions": "Sessions",
"numConnections": "Connections",
"dataRelayed": "Relayed",
"transferRate": "Rate"
},
"jackett": {
"configured": "Configured",
"errored": "Errored"
},
"mastodon": {
"user_count": "Users",
"status_count": "Posts",
"domain_count": "Domains"
},
"medusa": {
"wanted": "Wanted",
"queued": "Queued",
"series": "Series"
},
"minecraft": {
"players": "Players",
"version": "Version",
"down": "Offline",
"status": "Status",
"up": "Online"
},
"miniflux": {
"read": "Read",
"unread": "Unread"
},
"authentik": {
"users": "Users",
"loginsLast24H": "Logins (24h)",
"failedLoginsLast24H": "Failed Logins (24h)"
},
"proxmox": {
"mem": "MEM",
"cpu": "CPU",
"lxc": "LXC",
"vms": "VMs"
},
"glances": {
"cpu": "CPU",
"mem": "MEM",
"wait": "Please wait",
"temp": "TEMP",
"uptime": "UP",
"days": "d",
"hours": "h"
},
"quicklaunch": {
"bookmark": "Bookmark",
"service": "Service",
"search": "Search",
"custom": "Custom",
"visit": "Visit",
"url": "URL"
},
"homebridge": {
"available_update": "System",
"updates": "Updates",
"update_available": "Update Available",
"up_to_date": "Up to Date",
"child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}",
"up": "Up",
"pending": "Pending",
"down": "Down"
},
"healthchecks": {
"new": "New",
"up": "Online",
"grace": "In Grace Period",
"down": "Offline",
"paused": "Paused",
"status": "Status",
"last_ping": "Last Ping",
"never": "No pings yet"
},
"watchtower": {
"containers_scanned": "Scanned",
"containers_updated": "Updated",
"containers_failed": "Failed"
},
"autobrr": {
"approvedPushes": "Approved",
"rejectedPushes": "Rejected",
"filters": "Filters",
"indexers": "Indexers"
},
"tubearchivist": {
"downloads": "Queue",
"videos": "Videos",
"channels": "Channels",
"playlists": "Playlists"
},
"truenas": {
"load": "System Load",
"uptime": "Uptime",
"alerts": "Alerts",
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
},
"pyload": {
"speed": "Speed",
"active": "Active",
"queue": "Queue",
"total": "Total"
},
"gluetun": {
"public_ip": "Public IP",
"region": "Region",
"country": "Country"
},
"hdhomerun": {
"channels": "Channels",
"hd": "HD"
},
"scrutiny": {
"passed": "Passed",
"failed": "Failed",
"unknown": "Unknown"
},
"paperlessngx": {
"inbox": "Inbox",
"total": "Total"
},
"nextdns": {
"wait": "Please Wait",
"no_devices": "No Device Data Received"
},
"mikrotik": {
"cpuLoad": "CPU Load",
"memoryUsed": "Memory Used",
"uptime": "Uptime",
"numberOfLeases": "Leases"
},
"xteve": {
"streams_all": "All Streams",
"streams_active": "Active Streams",
"streams_xepg": "XEPG Channels"
},
"opnsense": {
"cpu": "CPU Load",
"memory": "Active Memory",
"wanUpload": "WAN Upload",
"wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
},
"octoprint": {
"printer_state": "Status",
"temp_tool": "Tool temp",
"temp_bed": "Bed temp",
"job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
},
"uptimekuma": {
"up": "Sites Up",
"down": "Sites Down",
"uptime": "Uptime",
"incident": "Incident",
"m": "m"
},
"komga": {
"libraries": "Libraries",
"series": "Series",
"books": "Books"
},
"diskstation": {
"days": "Days",
"uptime": "Uptime",
"volumeAvailable": "Available"
},
"mylar": {
"series": "Series",
"issues": "Issues",
"wanted": "Wanted"
},
"photoprism": {
"albums": "Albums",
"photos": "Photos",
"videos": "Videos",
"people": "People"
},
"fileflows": {
"processed": "Processed",
"queue": "Queue",
"processing": "Processing",
"time": "Time"
},
"grafana": {
"dashboards": "Dashboards",
"datasources": "Data Sources",
"totalalerts": "Total Alerts",
"alertstriggered": "Alerts Triggered"
},
"nextcloud": {
"cpuload": "Cpu Load",
"memoryusage": "Memory Usage",
"freespace": "Free Space",
"activeusers": "Active Users"
},
"kopia": {
"status": "Status",
"size": "Size",
"lastrun": "Last Run",
"nextrun": "Next Run",
"failed": "Failed"
},
"unmanic": {
"active_workers": "Active Workers",
"total_workers": "Total Workers",
"records_total": "Queue Length"
},
"pterodactyl": {
"servers": "Servers",
"nodes": "Nodes"
},
"prometheus": {
"targets_up": "Targets Up",
"targets_down": "Targets Down",
"targets_total": "Total Targets"
},
"ghostfolio": {
"gross_percent_today": "Today",
"gross_percent_1y": "One year",
"gross_percent_max": "All time"
},
"audiobookshelf": {
"podcasts": "Podcasts",
"books": "Books",
"podcastsDuration": "Duration",
"booksDuration": "Διάρκεια"
}
}

View File

@@ -19,7 +19,7 @@
"cpu": "CPU",
"mem": "MEM",
"temp": "TEMPORAL",
"max": "Máximo",
"max": "Máx.",
"uptime": "ARRIBA",
"months": "Meses",
"days": "Días",
@@ -118,7 +118,7 @@
"current": "Ubicación actual",
"allow": "Clic para permitir",
"updating": "Actualizando",
"wait": "Espere, por favor"
"wait": "Espera, por favor"
},
"overseerr": {
"pending": "Pendiente",
@@ -158,7 +158,7 @@
"transmission": {
"download": "Bajada",
"upload": "Subida",
"leech": "Sanguijuela",
"leech": "Compañeros",
"seed": "Semillas"
},
"jackett": {
@@ -183,7 +183,7 @@
"qbittorrent": {
"download": "Bajada",
"upload": "Subida",
"leech": "Depender",
"leech": "Compañeros",
"seed": "Semillas"
},
"mastodon": {
@@ -213,11 +213,11 @@
"users": "Usuarios",
"uptime": "Tiempo de actividad",
"days": "Días",
"wan": "Red WAN",
"wan": "WAN",
"lan_users": "Usuarios LAN",
"wlan_users": "Usuarios WLAN",
"down": "CAÍDO",
"wait": "Espere por favor",
"wait": "Espera por favor",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Dispositivos",
@@ -228,12 +228,12 @@
"plex": {
"streams": "Transmisiones activas",
"movies": "Películas",
"tv": "Programas de TV"
"tv": "Series"
},
"glances": {
"cpu": "Procesador",
"mem": "Memoria",
"wait": "Espere por favor",
"wait": "Espera por favor",
"temp": "TEMPORAL",
"uptime": "ARRIBA",
"days": "Días",
@@ -277,20 +277,20 @@
"66-night": "Granizo",
"67-night": "Granizo",
"71-day": "Nevada Leve",
"71-night": "Nevada Leva",
"71-night": "Nevada Leve",
"73-day": "Nevada",
"73-night": "Nevada",
"75-day": "Fuertes Nevadas",
"75-night": "Fuertes Nevadas",
"77-day": "Nevada Leve",
"77-night": "Nevada Leve",
"80-day": "llovizna",
"80-day": "Llovizna",
"80-night": "Llovizna",
"81-day": "Lluvia",
"81-night": "Lluvia",
"82-day": "Chubascos",
"82-night": "Chubascos",
"85-day": "Chubascos",
"85-day": "Lluvia de nieve",
"85-night": "Lluvia de nieve",
"86-day": "Lluvia de nieve",
"86-night": "Lluvia de nieve",
@@ -378,12 +378,12 @@
"deluge": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semilla"
"leech": "Compañeros",
"seed": "Semillas"
},
"flood": {
"download": "Descargar",
"upload": "Subir",
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
},
@@ -398,7 +398,7 @@
"unread": "Sin leer"
},
"nextdns": {
"wait": "Espere, por favor",
"wait": "Espera, por favor",
"no_devices": "No se reciben datos del dispositivo"
},
"common": {
@@ -415,7 +415,7 @@
"downloadstation": {
"download": "Descargar",
"upload": "Subir",
"leech": "Sanguijuela",
"leech": "Compañeros",
"seed": "Semilla"
},
"mikrotik": {
@@ -425,8 +425,8 @@
"numberOfLeases": "Alquileres"
},
"xteve": {
"streams_all": "Todas las corrientes",
"streams_active": "Corrientes activas",
"streams_all": "Todas las transmisiones",
"streams_active": "Transmisiones activas",
"streams_xepg": "Canales XEPG"
},
"opnsense": {
@@ -437,7 +437,7 @@
},
"moonraker": {
"printer_state": "Estado de la impresora",
"print_status": "Estado de la impresora",
"print_status": "Estado de la impresión",
"print_progress": "Progreso",
"layers": "Capas"
},
@@ -447,9 +447,9 @@
"series": "Serie"
},
"octoprint": {
"temp_bed": "temperatura de la plataforma",
"printer_state": "Status",
"temp_tool": "Herramienta de temperatura",
"temp_bed": "Temperatura de la plataforma",
"printer_state": "Estado",
"temp_tool": "Temperatura de la herramienta",
"job_completion": "Finalización"
},
"cloudflared": {
@@ -533,7 +533,7 @@
"grace": "En Periodo de Gracia",
"paused": "Pausado",
"status": "Estado",
"last_ping": "Último Ping",
"last_ping": "Último ping",
"never": "Aún no hay pings"
},
"pterodactyl": {

View File

@@ -24,7 +24,7 @@
"months": "mo",
"days": "d",
"hours": "h",
"minutes": "m"
"minutes": "mn"
},
"docker": {
"rx": "Rx",

View File

@@ -15,13 +15,13 @@
"free": "Wolne",
"cpu": "CPU",
"mem": "PAM",
"temp": "TEMP",
"temp": "TYMCZASOWE",
"max": "Max",
"uptime": "UP",
"months": "mo",
"days": "d",
"months": "misiąc",
"days": "dni",
"hours": "h",
"minutes": "m"
"minutes": "minuty"
},
"emby": {
"no_active": "Brak aktywnych strumieni",
@@ -79,7 +79,7 @@
"error": "Błąd",
"unknown": "Nieznany",
"running": "Działa",
"starting": "Starting",
"starting": "Startować",
"unhealthy": "Unhealthy",
"not_found": "Not Found",
"exited": "Exited",

View File

@@ -52,9 +52,9 @@
"load": "Carregamento",
"cpu": "CPU",
"mem": "MEM",
"max": "Max",
"max": "Máximo",
"temp": "TEMP",
"uptime": "UP",
"uptime": "CIMA",
"months": "mo",
"days": "d",
"hours": "h",
@@ -235,7 +235,7 @@
"mem": "MEM",
"wait": "Por favor aguarde",
"temp": "TEMP",
"uptime": "UP",
"uptime": "CIMA",
"days": "d",
"hours": "h"
},
@@ -316,9 +316,9 @@
"up_to_date": "Atualizado",
"child_bridges": "Pontes Filhas",
"child_bridges_status": "{{ok}}/{{total}}",
"up": "Up",
"up": "Cima",
"pending": "Pendente",
"down": "Down"
"down": "Baixo"
},
"autobrr": {
"approvedPushes": "Aprovado",

View File

@@ -18,9 +18,9 @@
"load": "Carga",
"cpu": "CPU",
"mem": "MEM",
"max": "Max",
"max": "Máximo",
"temp": "TEMP",
"uptime": "UP",
"uptime": "CIMA",
"months": "mo",
"days": "d",
"hours": "h",
@@ -248,7 +248,7 @@
"mem": "MEM",
"wait": "Por favor, aguarde",
"temp": "TEMP",
"uptime": "UP",
"uptime": "Cima",
"days": "d",
"hours": "h"
},
@@ -331,7 +331,7 @@
"child_bridges_status": "{{ok}}/{{total}}",
"up": "Up",
"pending": "Pendente",
"down": "Down"
"down": "Baixo"
},
"autobrr": {
"approvedPushes": "Aprovado",
@@ -550,8 +550,8 @@
"nodes": "Nós"
},
"prometheus": {
"targets_up": "Targets Up",
"targets_down": "Targets Down",
"targets_up": "Alvo ativo",
"targets_down": "Alvo inativo",
"targets_total": "Total de Alvos"
},
"minecraft": {

View File

@@ -234,8 +234,8 @@
"cpu": "处理器",
"mem": "内存",
"wait": "请稍等",
"temp": "TEMP",
"uptime": "UP",
"temp": "温度",
"uptime": "运行时间",
"days": "天",
"hours": "时"
},
@@ -260,8 +260,8 @@
"45-night": "有雾",
"48-night": "有雾",
"51-night": "小雨",
"53-day": "Drizzle",
"53-night": "Drizzle",
"53-day": "小雨",
"53-night": "小雨",
"55-day": "毛毛雨",
"55-night": "毛毛雨",
"56-day": "小冻毛雨",

View File

@@ -3,12 +3,13 @@ import classNames from "classnames";
import List from "components/services/list";
import ResolvedIcon from "components/resolvedicon";
export default function ServicesGroup({ services, layout }) {
export default function ServicesGroup({ services, layout, fiveColumns }) {
return (
<div
key={services.name}
className={classNames(
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4",
layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "",
"flex-1 p-1"
)}
>

View File

@@ -14,7 +14,8 @@ import ResolvedIcon from "components/resolvedicon";
export default function Item({ service }) {
const hasLink = service.href && service.href !== "#";
const { settings } = useContext(SettingsContext);
const [statsOpen, setStatsOpen] = useState(false);
const showStats = (service.showStats === false) ? false : settings.showStats;
const [statsOpen, setStatsOpen] = useState(service.showStats);
const [statsClosing, setStatsClosing] = useState(false);
// set stats to closed after 300ms
@@ -107,21 +108,21 @@ export default function Item({ service }) {
{service.container && service.server && (
<div
className={classNames(
statsOpen && !statsClosing ? "max-h-[110px] opacity-100" : " max-h-[0] opacity-0",
showStats || (statsOpen && !statsClosing) ? "max-h-[110px] opacity-100" : " max-h-[0] opacity-0",
"w-full overflow-hidden transition-all duration-300 ease-in-out"
)}
>
{statsOpen && <Docker service={{ widget: { container: service.container, server: service.server } }} />}
{(showStats || statsOpen) && <Docker service={{ widget: { container: service.container, server: service.server } }} />}
</div>
)}
{service.app && (
<div
className={classNames(
statsOpen && !statsClosing ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0",
showStats || (statsOpen && !statsClosing) ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0",
"w-full overflow-hidden transition-all duration-300 ease-in-out"
)}
>
{statsOpen && <Kubernetes service={{ widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector } }} />}
{(showStats || statsOpen) && <Kubernetes service={{ widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector } }} />}
</div>
)}

View File

@@ -6,6 +6,12 @@ import { useTranslation } from "next-i18next";
import UsageBar from "../resources/usage-bar";
const cpuSensorLabels = ["cpu_thermal", "Core"];
function convertToFahrenheit(t) {
return t * 9/5 + 32
}
export default function Widget({ options }) {
const { t, i18n } = useTranslation();
@@ -65,11 +71,20 @@ export default function Widget({ options }) {
}
const unit = options.units === "imperial" ? "fahrenheit" : "celsius";
let mainTemp;
let mainTemp = 0;
let maxTemp = 80;
if (options.cputemp && data.sensors) {
mainTemp = unit === "celsius" ? data.sensors.find(s => s.label.includes("cpu_thermal")).value : data.sensors.find(s => s.label.includes("cpu_thermal")).value * 5/9 + 32;
if (data.sensors.warning) maxTemp = data.sensors.warning;
const cpuSensors = data.sensors?.filter(s => cpuSensorLabels.some(label => s.label.startsWith(label)) && s.type === "temperature_core");
if (options.cputemp && cpuSensors) {
try {
mainTemp = cpuSensors.reduce((acc, s) => acc + s.value, 0) / cpuSensors.length;
maxTemp = Math.max(cpuSensors.reduce((acc, s) => acc + s.warning, 0) / cpuSensors.length, maxTemp);
if (unit === "fahrenheit") {
mainTemp = convertToFahrenheit(mainTemp);
maxTemp = convertToFahrenheit(maxTemp);
}
} catch (e) {
// cpu sensor retrieval failed
}
}
const tempPercent = Math.round((mainTemp / maxTemp) * 100);
@@ -110,7 +125,7 @@ export default function Widget({ options }) {
<UsageBar percent={data.quicklook.mem} />
</div>
</div>
{options.cputemp && mainTemp &&
{options.cputemp && mainTemp > 0 &&
(<div className="flex-none flex flex-row items-center mr-3 py-1.5">
<FaThermometerHalf className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left min-w-[85px]">

View File

@@ -6,7 +6,7 @@ import { useTranslation } from "next-i18next";
import UsageBar from "./usage-bar";
function convertToFahrenheit(t) {
return t * 5/9 + 32
return t * 9/5 + 32
}
export default function CpuTemp({ expanded, units }) {
@@ -47,16 +47,14 @@ export default function CpuTemp({ expanded, units }) {
);
}
let minTemp = 0;
let mainTemp = data.cputemp.main;
if (data.cputemp.cores?.length) {
mainTemp = data.cputemp.cores.reduce((a, b) => a + b) / data.cputemp.cores.length;
minTemp = Math.min(...data.cputemp.cores);
}
const unit = units === "imperial" ? "fahrenheit" : "celsius";
mainTemp = (unit === "celsius") ? mainTemp : convertToFahrenheit(mainTemp);
const maxTemp = (unit === "celsius") ? data.cputemp.max : convertToFahrenheit(data.cputemp.max);
const percent = Math.round(((mainTemp - minTemp) / (maxTemp - minTemp)) * 100);
const percent = Math.round((mainTemp / maxTemp) * 100);
return (
<div className="flex-none flex flex-row items-center mr-3 py-1.5">

View File

@@ -44,7 +44,7 @@ export default function Memory({ expanded }) {
);
}
const percent = Math.round((data.memory.used / data.memory.total) * 100);
const percent = Math.round((data.memory.active / data.memory.total) * 100);
return (
<div className="flex-none flex flex-row items-center mr-3 py-1.5">
@@ -52,7 +52,7 @@ export default function Memory({ expanded }) {
<div className="flex flex-col ml-3 text-left min-w-[85px]">
<span className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
<div className="pl-0.5 pr-1">
{t("common.bytes", { value: data.memory.free, maximumFractionDigits: 1, binary: true })}
{t("common.bytes", { value: data.memory.available, maximumFractionDigits: 1, binary: true })}
</div>
<div className="pr-1">{t("resources.free")}</div>
</span>

View File

@@ -19,8 +19,8 @@ export default async function handler(req, res) {
return hash(readFileSync(configYaml, "utf8"));
});
// this ties hash to specific build which should force revaliation between versions
const buildTime = process.env.NEXT_PUBLIC_BUILDTIME?.length ? process.env.NEXT_PUBLIC_BUILDTIME : '';
// set to date by docker entrypoint, will force revalidation between restarts/recreates
const buildTime = process.env.HOMEPAGE_BUILDTIME?.length ? process.env.HOMEPAGE_BUILDTIME : '';
const combinedHash = hash(hashes.join("") + buildTime);

View File

@@ -289,7 +289,7 @@ function Home({ initialSettings }) {
{services && (
<div className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
{services.map((group) => (
<ServicesGroup key={group.name} services={group} layout={initialSettings.layout?.[group.name]} />
<ServicesGroup key={group.name} services={group} layout={initialSettings.layout?.[group.name]} fiveColumns={settings.fiveColumns} />
))}
</div>
)}

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { join } from "path";
import { existsSync, copyFile, readFileSync } from "fs";
import { existsSync, readFileSync, copyFileSync } from "fs";
import cache from "memory-cache";
import yaml from "js-yaml";
@@ -13,13 +13,13 @@ export default function checkAndCopyConfig(config) {
const configYaml = join(process.cwd(), "config", config);
if (!existsSync(configYaml)) {
const configSkeleton = join(process.cwd(), "src", "skeleton", config);
copyFile(configSkeleton, configYaml, (err) => {
if (err) {
try {
copyFileSync(configSkeleton, configYaml)
console.info("%s was copied to the config folder", config);
} catch (err) {
console.error("error copying config", err);
throw err;
}
console.info("%s was copied to the config folder", config);
});
}
return true;
}

View File

@@ -4,7 +4,7 @@ import path from "path";
import yaml from "js-yaml";
import Docker from "dockerode";
import * as shvl from "shvl";
import { NetworkingV1Api } from "@kubernetes/client-node";
import { CustomObjectsApi, NetworkingV1Api } from "@kubernetes/client-node";
import createLogger from "utils/logger";
import checkAndCopyConfig, { substituteEnvironmentVars } from "utils/config/config";
@@ -145,6 +145,7 @@ export async function servicesFromKubernetes() {
return [];
}
const networking = kc.makeApiClient(NetworkingV1Api);
const crd = kc.makeApiClient(CustomObjectsApi);
const ingressList = await networking.listIngressForAllNamespaces(null, null, null, null)
.then((response) => response.body)
@@ -152,6 +153,20 @@ export async function servicesFromKubernetes() {
logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response);
return null;
});
const traefikIngressList = await crd.listClusterCustomObject("traefik.containo.us", "v1alpha1", "ingressroutes")
.then((response) => response.body)
.catch((error) => {
logger.error("Error getting traefik ingresses: %d %s %s", error.statusCode, error.body, error.response);
return null;
});
if (traefikIngressList && traefikIngressList.items.length > 0) {
const traefikServices = traefikIngressList.items
.filter((ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${ANNOTATION_BASE}/href`])
ingressList.items.push(...traefikServices);
}
if (!ingressList) {
return [];
}
@@ -221,6 +236,7 @@ export function cleanServiceGroups(groups) {
name: serviceGroup.name,
services: serviceGroup.services.map((service) => {
const cleanedService = { ...service };
if (cleanedService.showStats !== undefined) cleanedService.showStats = JSON.parse(cleanedService.showStats);
if (typeof service.weight === 'string') {
const weight = parseInt(service.weight, 10);
if (Number.isNaN(weight)) {
@@ -282,8 +298,8 @@ export function cleanServiceGroups(groups) {
if (wan) cleanedService.widget.wan = wan;
}
if (type === "emby" || type === "jellyfin") {
if (enableBlocks) cleanedService.widget.enableBlocks = enableBlocks === 'true';
if (enableNowPlaying) cleanedService.widget.enableNowPlaying = enableNowPlaying === 'true';
if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = JSON.parse(enableBlocks);
if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = JSON.parse(enableNowPlaying);
}
if (type === "diskstation") {
if (volume) cleanedService.widget.volume = volume;

View File

@@ -7,7 +7,7 @@ export default function useWidgetAPI(widget, ...options) {
if (options && options[1]?.refreshInterval) {
config.refreshInterval = options[1].refreshInterval;
}
const { data, error } = useSWR(formatProxyUrl(widget, ...options), config);
const { data, error, mutate } = useSWR(formatProxyUrl(widget, ...options), config);
// make the data error the top-level error
return { data, error: data?.error ?? error }
return { data, error: data?.error ?? error, mutate }
}

View File

@@ -2,11 +2,13 @@ import widgets from "widgets/widgets";
export default function validateWidgetData(widget, endpoint, data) {
let valid = true;
let dataParsed;
try {
dataParsed = JSON.parse(data);
} catch (e) {
valid = false;
let dataParsed = data;
if (Buffer.isBuffer(data)) {
try {
dataParsed = JSON.parse(data);
} catch (e) {
valid = false;
}
}
if (dataParsed && Object.entries(dataParsed).length) {

View File

@@ -272,7 +272,7 @@ export default function Component({ service }) {
);
}
if (playing.length === -1)
if (playing.length > 0)
return (
<>
{enableBlocks && <CountBlocks service={service} countData={countData} />}

View File

@@ -25,6 +25,10 @@ module.exports = {
900: "rgb(var(--color-900) / <alpha-value>)",
},
},
screens: {
'3xl': '1800px',
// => @media (min-width: 1800px) { ... }
},
},
},
plugins: [tailwindForms, tailwindScrollbars],