Merge remote-tracking branch 'origin/main' into dev

This commit is contained in:
GodD6366 2024-04-26 09:35:00 +08:00
commit 4a291b7f53
25 changed files with 556 additions and 378 deletions

View File

@ -235,4 +235,4 @@ You can show the docker stats by clicking the status indicator but this can also
showStats: true showStats: true
``` ```
Also see the settings for [show docker stats](docker.md#show-docker-stats). Also see the settings for [show docker stats](settings.md#show-docker-stats).

47
docs/overrides/main.html Normal file
View File

@ -0,0 +1,47 @@
{% extends "base.html" %}
{% block site_nav %}
<!-- Navigation -->
{% if nav %}
{% if page.meta and page.meta.hide %}
{% set hidden = "hidden" if "navigation" in page.meta.hide %}
{% endif %}
<div
class="md-sidebar md-sidebar--primary"
data-md-component="sidebar"
data-md-type="navigation"
{{ hidden }}
>
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
{% include "partials/nav.html" %}
{% if 'widgets/' not in page.url and 'more/' not in page.url %}
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CWYIL2JU&placement=gethomepagedev&format=cover" id="_carbonads_js"></script>
{% endif %}
</div>
</div>
</div>
{% endif %}
<!-- Table of contents -->
{% if "toc.integrate" not in features %}
{% if page.meta and page.meta.hide %}
{% set hidden = "hidden" if "toc" in page.meta.hide %}
{% endif %}
<div
class="md-sidebar md-sidebar--secondary"
data-md-component="sidebar"
data-md-type="toc"
{{ hidden }}
>
<div class="md-sidebar__scrollwrap" style="height: 200px;">
<div class="md-sidebar__inner">
{% include "partials/toc.html" %}
{% if 'widgets/' in page.url or 'more/' in page.url %}
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CWYIL2JU&placement=gethomepagedev&format=cover" id="_carbonads_js"></script>
{% endif %}
</div>
</div>
</div>
{% endif %}
{% endblock %}

View File

@ -22,3 +22,15 @@
#glimeRoot * { #glimeRoot * {
font-family: var(--md-text-font) !important; font-family: var(--md-text-font) !important;
} }
#carbonads {
margin-top: 10px;
}
#carbon-responsive {
--carbon-padding: 1em;
--carbon-max-char: 20ch;
--carbon-bg-primary: var(--md-default-bg-color) !important;
--carbon-bg-secondary: var(--md-default-fg-color--lightest) !important;
--carbon-text-color: var(--md-typeset-color) !important;
}

View File

@ -19,6 +19,8 @@ _Note: unfortunately, the package used for getting CPU temp ([systeminformation]
memory: true memory: true
disk: /disk/mount/path disk: /disk/mount/path
cputemp: true cputemp: true
tempmin: 0 # optional, minimum cpu temp
tempmax: 100 # optional, maximum cpu temp
uptime: true uptime: true
units: imperial # only used by cpu temp units: imperial # only used by cpu temp
refresh: 3000 # optional, in ms refresh: 3000 # optional, in ms

View File

@ -12,10 +12,8 @@ Make sure to set Intent to "API Token".
The account you made the API token for also needs the following **Assigned global permissions** in Authentik: The account you made the API token for also needs the following **Assigned global permissions** in Authentik:
- authentik Core - authentik Core -> Can view User (Model: User)
- User - authentik Events -> Can view Event (Model: Event)
- authentik Events
- Event
Allowed fields: `["users", "loginsLast24H", "failedLoginsLast24H"]`. Allowed fields: `["users", "loginsLast24H", "failedLoginsLast24H"]`.

View File

@ -16,4 +16,7 @@ widget:
key: apikeyapikeyapikeyapikeyapikey key: apikeyapikeyapikeyapikeyapikey
enableBlocks: true # optional, defaults to false enableBlocks: true # optional, defaults to false
enableNowPlaying: true # optional, defaults to true enableNowPlaying: true # optional, defaults to true
enableUser: true # optional, defaults to false
showEpisodeNumber: true # optional, defaults to false
expandOneStreamToTwoRows: false # optional, defaults to true
``` ```

View File

@ -16,4 +16,7 @@ widget:
key: apikeyapikeyapikeyapikeyapikey key: apikeyapikeyapikeyapikeyapikey
enableBlocks: true # optional, defaults to false enableBlocks: true # optional, defaults to false
enableNowPlaying: true # optional, defaults to true enableNowPlaying: true # optional, defaults to true
enableUser: true # optional, defaults to false
showEpisodeNumber: true # optional, defaults to false
expandOneStreamToTwoRows: false # optional, defaults to true
``` ```

View File

@ -3,7 +3,7 @@ title: Medusa
description: Medusa Widget Configuration description: Medusa Widget Configuration
--- ---
Learn more about [Medusa](https://github.com/medusajs/medusa). Learn more about [Medusa](https://github.com/pymedusa/Medusa).
Allowed fields: `["wanted", "queued", "series"]`. Allowed fields: `["wanted", "queued", "series"]`.

View File

@ -14,4 +14,7 @@ widget:
type: tautulli type: tautulli
url: http://tautulli.host.or.ip url: http://tautulli.host.or.ip
key: apikeyapikeyapikeyapikeyapikey key: apikeyapikeyapikeyapikeyapikey
enableUser: true # optional, defaults to false
showEpisodeNumber: true # optional, defaults to false
expandOneStreamToTwoRows: false # optional, defaults to true
``` ```

View File

@ -16,4 +16,5 @@ Allowed fields: `["download", "upload", "ping"]`.
widget: widget:
type: speedtest type: speedtest
url: http://speedtest.host.or.ip url: http://speedtest.host.or.ip
bitratePrecision: 3 # optional, default is 0
``` ```

View File

@ -5,7 +5,7 @@ description: Uptime Kuma Widget Configuration
Learn more about [Uptime Kuma](https://github.com/louislam/uptime-kuma). Learn more about [Uptime Kuma](https://github.com/louislam/uptime-kuma).
As Uptime Kuma does not yet have a full API the widget uses data from a single "status page". As such you will need a status page setup with a group of monitored sites, which is where you get the slug (without the `/status/` portion). As Uptime Kuma does not yet have a full API the widget uses data from a single "status page". As such you will need a status page setup with a group of monitored sites, which is where you get the slug (the url without the `/status/` portion). E.g. if your status page is URL http://uptimekuma.host/status/statuspageslug, insert `slug: statuspageslug`.
Allowed fields: `["up", "down", "uptime", "incident"]`. Allowed fields: `["up", "down", "uptime", "incident"]`.

View File

@ -90,6 +90,7 @@ nav:
- widgets/services/mylar.md - widgets/services/mylar.md
- widgets/services/navidrome.md - widgets/services/navidrome.md
- widgets/services/netdata.md - widgets/services/netdata.md
- widgets/services/netalertx.md
- widgets/services/nextcloud.md - widgets/services/nextcloud.md
- widgets/services/nextdns.md - widgets/services/nextdns.md
- widgets/services/nginx-proxy-manager.md - widgets/services/nginx-proxy-manager.md
@ -100,12 +101,12 @@ nav:
- widgets/services/opendtu.md - widgets/services/opendtu.md
- widgets/services/openmediavault.md - widgets/services/openmediavault.md
- widgets/services/opnsense.md - widgets/services/opnsense.md
- widgets/services/openwrt.md
- widgets/services/overseerr.md - widgets/services/overseerr.md
- widgets/services/paperlessngx.md - widgets/services/paperlessngx.md
- widgets/services/peanut.md - widgets/services/peanut.md
- widgets/services/pfsense.md - widgets/services/pfsense.md
- widgets/services/photoprism.md - widgets/services/photoprism.md
- widgets/services/pialert.md
- widgets/services/pihole.md - widgets/services/pihole.md
- widgets/services/plantit.md - widgets/services/plantit.md
- widgets/services/plex-tautulli.md - widgets/services/plex-tautulli.md
@ -130,6 +131,7 @@ nav:
- widgets/services/stash.md - widgets/services/stash.md
- widgets/services/syncthing-relay-server.md - widgets/services/syncthing-relay-server.md
- widgets/services/tailscale.md - widgets/services/tailscale.md
- widgets/services/tandoor.md
- widgets/services/tdarr.md - widgets/services/tdarr.md
- widgets/services/traefik.md - widgets/services/traefik.md
- widgets/services/transmission.md - widgets/services/transmission.md
@ -166,6 +168,7 @@ nav:
theme: theme:
name: material name: material
custom_dir: docs/overrides
language: en language: en
palette: palette:
- media: "(prefers-color-scheme)" - media: "(prefers-color-scheme)"

View File

@ -14,7 +14,7 @@
"date": "{{value, date}}", "date": "{{value, date}}",
"relativeDate": "{{value, relativeDate}}", "relativeDate": "{{value, relativeDate}}",
"uptime": "{{value, uptime}}", "uptime": "{{value, uptime}}",
"months": "mo", "months": "mes",
"days": "d", "days": "d",
"hours": "h", "hours": "h",
"minutes": "m", "minutes": "m",
@ -46,8 +46,8 @@
"used": "Utilitzat", "used": "Utilitzat",
"load": "Càrrega", "load": "Càrrega",
"temp": "TEMP", "temp": "TEMP",
"max": "Max", "max": "Màx.",
"uptime": "UP" "uptime": "ACTIU"
}, },
"unifi": { "unifi": {
"users": "Usuaris", "users": "Usuaris",
@ -61,65 +61,65 @@
"wlan_devices": "Dispositius WLAN", "wlan_devices": "Dispositius WLAN",
"lan_users": "Usuaris LAN", "lan_users": "Usuaris LAN",
"wlan_users": "Usuaris WLAN", "wlan_users": "Usuaris WLAN",
"up": "UP", "up": "ACTIU",
"down": "INACTIU", "down": "INACTIU",
"wait": "Si us plau, espereu", "wait": "Si us plau, espereu",
"empty_data": "Subsystem status unknown" "empty_data": "Estat del subsistema desconegut"
}, },
"docker": { "docker": {
"rx": "Rebut", "rx": "Rebut",
"tx": "Transmès", "tx": "Transmès",
"mem": "MEM", "mem": "MEM",
"cpu": "CPU", "cpu": "CPU",
"running": "Running", "running": "En execució",
"offline": "Fora de línia", "offline": "Fora de línia",
"error": "Error", "error": "Error",
"unknown": "Desconegut", "unknown": "Desconegut",
"healthy": "Healthy", "healthy": "Saludable",
"starting": "Starting", "starting": "Iniciant",
"unhealthy": "Unhealthy", "unhealthy": "No saludable",
"not_found": "Not Found", "not_found": "No trobat",
"exited": "Exited", "exited": "Tancat",
"partial": "Partial" "partial": "Parcial"
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping", "ping": "Latència",
"down": "Down", "down": "Inactiu",
"up": "Up", "up": "Actiu",
"not_available": "Not Available" "not_available": "No Disponible"
}, },
"siteMonitor": { "siteMonitor": {
"http_status": "HTTP status", "http_status": "Estat HTTP",
"error": "Error", "error": "Error",
"response": "Response", "response": "Resposta",
"down": "Down", "down": "Inactiu",
"up": "Up", "up": "Actiu",
"not_available": "Not Available" "not_available": "No Disponible"
}, },
"emby": { "emby": {
"playing": "Reproduint", "playing": "Reproduint",
"transcoding": "Transcodificant", "transcoding": "Transcodificant",
"bitrate": "Taxa de bits", "bitrate": "Taxa de bits",
"no_active": "Sense reproduccions actives", "no_active": "Sense reproduccions actives",
"movies": "Movies", "movies": "Pel·lícules",
"series": "Series", "series": "Sèries",
"episodes": "Episodes", "episodes": "Episodis",
"songs": "Songs" "songs": "Cançons"
}, },
"esphome": { "esphome": {
"offline": "Fora de línia", "offline": "Fora de línia",
"offline_alt": "Fora de línia", "offline_alt": "Fora de línia",
"online": "Online", "online": "En línia",
"total": "Total", "total": "Total",
"unknown": "Desconegut" "unknown": "Desconegut"
}, },
"evcc": { "evcc": {
"pv_power": "Production", "pv_power": "Producció",
"battery_soc": "Battery", "battery_soc": "Bateria",
"grid_power": "Grid", "grid_power": "Xarxa",
"home_power": "Consumption", "home_power": "Consum",
"charge_power": "Charger", "charge_power": "Carregador",
"watt_hour": "Wh" "watt_hour": "Wh"
}, },
"flood": { "flood": {
@ -129,55 +129,55 @@
"seed": "Llavor" "seed": "Llavor"
}, },
"freshrss": { "freshrss": {
"subscriptions": "Subscriptions", "subscriptions": "Subcripcions",
"unread": "Unread" "unread": "Sense llegir"
}, },
"fritzbox": { "fritzbox": {
"connectionStatus": "Estat", "connectionStatus": "Estat",
"connectionStatusUnconfigured": "Unconfigured", "connectionStatusUnconfigured": "Sense configurar",
"connectionStatusConnecting": "Connecting", "connectionStatusConnecting": "Connectant",
"connectionStatusAuthenticating": "Authenticating", "connectionStatusAuthenticating": "Autenticant",
"connectionStatusPendingDisconnect": "Pending Disconnect", "connectionStatusPendingDisconnect": "Desconnexió pendent",
"connectionStatusDisconnecting": "Disconnecting", "connectionStatusDisconnecting": "Desconnectant",
"connectionStatusDisconnected": "Disconnected", "connectionStatusDisconnected": "Desconnectat",
"connectionStatusConnected": "Connected", "connectionStatusConnected": "Connectat",
"uptime": "Temps actiu", "uptime": "Temps actiu",
"maxDown": "Max. Down", "maxDown": "Màx. Descàrrega",
"maxUp": "Max. Up", "maxUp": "Màx. Càrrega",
"down": "Down", "down": "Inactiu",
"up": "Up", "up": "Actiu",
"received": "Received", "received": "Rebuts",
"sent": "Sent", "sent": "Enviats",
"externalIPAddress": "Ext. IP" "externalIPAddress": "IP ext."
}, },
"caddy": { "caddy": {
"upstreams": "Upstreams", "upstreams": "Upstreams",
"requests": "Current requests", "requests": "Peticions actuals",
"requests_failed": "Failed requests" "requests_failed": "Peticions fallides"
}, },
"changedetectionio": { "changedetectionio": {
"totalObserved": "Total d'observats", "totalObserved": "Total d'observats",
"diffsDetected": "Diferències detectades" "diffsDetected": "Diferències detectades"
}, },
"channelsdvrserver": { "channelsdvrserver": {
"shows": "Shows", "shows": "Sèries",
"recordings": "Recordings", "recordings": "Gravacions",
"scheduled": "Scheduled", "scheduled": "Programat",
"passes": "Passes" "passes": "Aprovat"
}, },
"tautulli": { "tautulli": {
"playing": "Reproduint", "playing": "Reproduint",
"transcoding": "Transcodificant", "transcoding": "Transcodificant",
"bitrate": "Taxa de bits", "bitrate": "Taxa de bits",
"no_active": "Sense reproduccions actives", "no_active": "Sense reproduccions actives",
"plex_connection_error": "Check Plex Connection" "plex_connection_error": "Comprova la connexió de Plex"
}, },
"omada": { "omada": {
"connectedAp": "Connected APs", "connectedAp": "AP connectats",
"activeUser": "Active devices", "activeUser": "Dispositius actius",
"alerts": "Alerts", "alerts": "Alertes",
"connectedGateway": "Connected gateways", "connectedGateway": "Pasarel·les connectades",
"connectedSwitches": "Connected switches" "connectedSwitches": "Conmutadors connectats"
}, },
"nzbget": { "nzbget": {
"rate": "Taxa", "rate": "Taxa",
@ -187,7 +187,7 @@
"plex": { "plex": {
"streams": "Transmissions actives", "streams": "Transmissions actives",
"albums": "Àlbums", "albums": "Àlbums",
"movies": "Movies", "movies": "Pel·lícules",
"tv": "Sèries" "tv": "Sèries"
}, },
"sabnzbd": { "sabnzbd": {
@ -213,12 +213,12 @@
"seed": "Llavor" "seed": "Llavor"
}, },
"qnap": { "qnap": {
"cpuUsage": "CPU Usage", "cpuUsage": "Ús de CPU",
"memUsage": "MEM Usage", "memUsage": "Ús de Memòria",
"systemTempC": "System Temp", "systemTempC": "Temp. Sistema",
"poolUsage": "Pool Usage", "poolUsage": "Ús de les Reserves",
"volumeUsage": "Volume Usage", "volumeUsage": "Ús dels Volums",
"invalid": "Invalid" "invalid": "No vàlid"
}, },
"deluge": { "deluge": {
"download": "Descarregar", "download": "Descarregar",
@ -235,7 +235,7 @@
"sonarr": { "sonarr": {
"wanted": "Volgut", "wanted": "Volgut",
"queued": "En cua", "queued": "En cua",
"series": "Series", "series": "Sèries",
"queue": "Cua", "queue": "Cua",
"unknown": "Desconegut" "unknown": "Desconegut"
}, },
@ -243,14 +243,14 @@
"wanted": "Volgut", "wanted": "Volgut",
"missing": "Faltant", "missing": "Faltant",
"queued": "En cua", "queued": "En cua",
"movies": "Movies", "movies": "Pel·lícules",
"queue": "Cua", "queue": "Cua",
"unknown": "Desconegut" "unknown": "Desconegut"
}, },
"lidarr": { "lidarr": {
"wanted": "Volgut", "wanted": "Volgut",
"queued": "En cua", "queued": "En cua",
"artists": "Artists" "artists": "Artistes"
}, },
"readarr": { "readarr": {
"wanted": "Volgut", "wanted": "Volgut",
@ -279,15 +279,15 @@
}, },
"netalertx": { "netalertx": {
"total": "Total", "total": "Total",
"connected": "Connected", "connected": "Connectat",
"new_devices": "New Devices", "new_devices": "Nous dispositius",
"down_alerts": "Down Alerts" "down_alerts": "Alertes de caigudes"
}, },
"pihole": { "pihole": {
"queries": "Consultes", "queries": "Consultes",
"blocked": "Bloquejat", "blocked": "Bloquejat",
"blocked_percent": "Blocked %", "blocked_percent": "Bloquejat %",
"gravity": "Gravity" "gravity": "Gravetat"
}, },
"adguard": { "adguard": {
"queries": "Consultes", "queries": "Consultes",
@ -298,37 +298,37 @@
"speedtest": { "speedtest": {
"upload": "Pujada", "upload": "Pujada",
"download": "Descarregar", "download": "Descarregar",
"ping": "Ping" "ping": "Latència"
}, },
"portainer": { "portainer": {
"running": "Running", "running": "En execució",
"stopped": "Aturat", "stopped": "Aturat",
"total": "Total" "total": "Total"
}, },
"tailscale": { "tailscale": {
"address": "Address", "address": "Adreça",
"expires": "Expires", "expires": "Caduca",
"never": "Never", "never": "Mai",
"last_seen": "Last Seen", "last_seen": "Vist per darrer cop",
"now": "Now", "now": "Ara",
"years": "{{number}}y", "years": "{{number}}a",
"weeks": "{{number}}w", "weeks": "{{number}}set",
"days": "{{number}}d", "days": "{{number}}d",
"hours": "{{number}}h", "hours": "{{number}}h",
"minutes": "{{number}}m", "minutes": "{{number}}m",
"seconds": "{{number}}s", "seconds": "{{number}}s",
"ago": "{{value}} Ago" "ago": "Fa {{value}}"
}, },
"tdarr": { "tdarr": {
"queue": "Cua", "queue": "Cua",
"processed": "Processed", "processed": "Processat",
"errored": "Errored", "errored": "Error",
"saved": "Saved" "saved": "Desat"
}, },
"traefik": { "traefik": {
"routers": "Encaminadors", "routers": "Encaminadors",
"services": "Serveis", "services": "Serveis",
"middleware": "Middleware" "middleware": "Intermediari"
}, },
"navidrome": { "navidrome": {
"nothing_streaming": "Sense reproduccions actives", "nothing_streaming": "Sense reproduccions actives",
@ -360,7 +360,7 @@
}, },
"jackett": { "jackett": {
"configured": "Configurat", "configured": "Configurat",
"errored": "Errored" "errored": "Error"
}, },
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessions", "numActiveSessions": "Sessions",
@ -376,18 +376,18 @@
"medusa": { "medusa": {
"wanted": "Volgut", "wanted": "Volgut",
"queued": "En cua", "queued": "En cua",
"series": "Series" "series": "Sèries"
}, },
"minecraft": { "minecraft": {
"players": "Players", "players": "Jugadors",
"version": "Version", "version": "Versió",
"status": "Estat", "status": "Estat",
"up": "Online", "up": "En línia",
"down": "Fora de línia" "down": "Fora de línia"
}, },
"miniflux": { "miniflux": {
"read": "Read", "read": "Llegir",
"unread": "Unread" "unread": "Sense llegir"
}, },
"authentik": { "authentik": {
"users": "Usuaris", "users": "Usuaris",
@ -406,28 +406,28 @@
"wait": "Si us plau, espereu", "wait": "Si us plau, espereu",
"temp": "TEMP", "temp": "TEMP",
"_temp": "Temp", "_temp": "Temp",
"warn": "Warn", "warn": "Avís",
"uptime": "UP", "uptime": "ACTIU",
"total": "Total", "total": "Total",
"free": "Lliure", "free": "Lliure",
"used": "Utilitzat", "used": "Utilitzat",
"days": "d", "days": "d",
"hours": "h", "hours": "h",
"crit": "Crit", "crit": "Crític",
"read": "Read", "read": "Llegir",
"write": "Write", "write": "Escriure",
"gpu": "GPU", "gpu": "GPU",
"mem": "Mem", "mem": "Mem",
"swap": "Swap" "swap": "Intercanvi"
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Marcador", "bookmark": "Marcador",
"service": "Servei", "service": "Servei",
"search": "Search", "search": "Cercar",
"custom": "Custom", "custom": "Personalitzat",
"visit": "Visit", "visit": "Visitar",
"url": "URL", "url": "URL",
"searchsuggestion": "Suggestion" "searchsuggestion": "Suggeriment"
}, },
"wmo": { "wmo": {
"0-day": "Assolellat", "0-day": "Assolellat",
@ -492,21 +492,21 @@
"updates": "Actualitzacions", "updates": "Actualitzacions",
"update_available": "Actualització disponible", "update_available": "Actualització disponible",
"up_to_date": "Actualitzat", "up_to_date": "Actualitzat",
"child_bridges": "Child Bridges", "child_bridges": "Ponts fills",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"up": "Up", "up": "Actiu",
"pending": "Pendent", "pending": "Pendent",
"down": "Down" "down": "Inactiu"
}, },
"healthchecks": { "healthchecks": {
"new": "New", "new": "Nou",
"up": "Up", "up": "Actiu",
"grace": "In Grace Period", "grace": "En Període de gràcia",
"down": "Down", "down": "Inactiu",
"paused": "Paused", "paused": "En pausa",
"status": "Estat", "status": "Estat",
"last_ping": "Last Ping", "last_ping": "Últim ping",
"never": "No pings yet" "never": "Sense pings"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "Escanejat", "containers_scanned": "Escanejat",
@ -528,7 +528,7 @@
"truenas": { "truenas": {
"load": "Càrrega del sistema", "load": "Càrrega del sistema",
"uptime": "Temps actiu", "uptime": "Temps actiu",
"alerts": "Alerts" "alerts": "Alertes"
}, },
"pyload": { "pyload": {
"speed": "Velocitat", "speed": "Velocitat",
@ -544,12 +544,12 @@
"hdhomerun": { "hdhomerun": {
"channels": "Canals", "channels": "Canals",
"hd": "HD", "hd": "HD",
"tunerCount": "Tuners", "tunerCount": "Sintonitzadors",
"channelNumber": "Channel", "channelNumber": "Canal",
"channelNetwork": "Network", "channelNetwork": "Xarxa",
"signalStrength": "Strength", "signalStrength": "Intensitat",
"signalQuality": "Quality", "signalQuality": "Qualitat",
"symbolQuality": "Quality", "symbolQuality": "Qualitat",
"networkRate": "Taxa de bits", "networkRate": "Taxa de bits",
"clientIP": "Client" "clientIP": "Client"
}, },
@ -563,94 +563,94 @@
"total": "Total" "total": "Total"
}, },
"peanut": { "peanut": {
"battery_charge": "Battery Charge", "battery_charge": "Càrrega de la bateria",
"ups_load": "UPS Load", "ups_load": "Càrrega del SAI",
"ups_status": "UPS Status", "ups_status": "Estat del SAI",
"online": "Online", "online": "En línia",
"on_battery": "On Battery", "on_battery": "En Bateria",
"low_battery": "Low Battery" "low_battery": "Bateria Baixa"
}, },
"nextdns": { "nextdns": {
"wait": "Espereu si us plau", "wait": "Espereu si us plau",
"no_devices": "No Device Data Received" "no_devices": "No s'han rebut dades del Dispositiu"
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU Load", "cpuLoad": "Càrrega de CPU",
"memoryUsed": "Memory Used", "memoryUsed": "Memoria en ús",
"uptime": "Temps actiu", "uptime": "Temps actiu",
"numberOfLeases": "Leases" "numberOfLeases": "IPs assignades"
}, },
"xteve": { "xteve": {
"streams_all": "All Streams", "streams_all": "Tots els fluxos",
"streams_active": "Transmissions actives", "streams_active": "Transmissions actives",
"streams_xepg": "XEPG Channels" "streams_xepg": "Canals XEPG"
}, },
"opendtu": { "opendtu": {
"yieldDay": "Today", "yieldDay": "Avui",
"absolutePower": "Power", "absolutePower": "Potència",
"relativePower": "Power %", "relativePower": "Potència %",
"limit": "Limit" "limit": "Límit"
}, },
"opnsense": { "opnsense": {
"cpu": "CPU Load", "cpu": "Càrrega de CPU",
"memory": "Active Memory", "memory": "Memòria activa",
"wanUpload": "WAN Upload", "wanUpload": "Pujada WAN",
"wanDownload": "WAN Download" "wanDownload": "Baixada WAN"
}, },
"moonraker": { "moonraker": {
"printer_state": "Printer State", "printer_state": "Estat de l'impressora",
"print_status": "Print Status", "print_status": "Estat de l'impressió",
"print_progress": "Progress", "print_progress": "Progress",
"layers": "Layers" "layers": "Capes"
}, },
"octoprint": { "octoprint": {
"printer_state": "Estat", "printer_state": "Estat",
"temp_tool": "Tool temp", "temp_tool": "Temperatura capçal",
"temp_bed": "Bed temp", "temp_bed": "Temperatura llit",
"job_completion": "Completion" "job_completion": "Finalització"
}, },
"cloudflared": { "cloudflared": {
"origin_ip": "Origin IP", "origin_ip": "IP Origen",
"status": "Estat" "status": "Estat"
}, },
"pfsense": { "pfsense": {
"load": "Load Avg", "load": "Promig Càrrega",
"memory": "Mem Usage", "memory": "Ús Memòria",
"wanStatus": "WAN Status", "wanStatus": "Estat WAN",
"up": "Up", "up": "Actiu",
"down": "Down", "down": "Inactiu",
"temp": "Temp", "temp": "Temp",
"disk": "Disk Usage", "disk": "Ús Disc",
"wanIP": "WAN IP" "wanIP": "WAN IP"
}, },
"proxmoxbackupserver": { "proxmoxbackupserver": {
"datastore_usage": "Datastore", "datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h", "failed_tasks_24h": "Tasques fallides (24h)",
"cpu_usage": "CPU", "cpu_usage": "CPU",
"memory_usage": "Memory" "memory_usage": "Memòria"
}, },
"immich": { "immich": {
"users": "Usuaris", "users": "Usuaris",
"photos": "Photos", "photos": "Fotos",
"videos": "Vídeos", "videos": "Vídeos",
"storage": "Storage" "storage": "Emmagatzematge"
}, },
"uptimekuma": { "uptimekuma": {
"up": "Sites Up", "up": "Actius",
"down": "Sites Down", "down": "Caiguts",
"uptime": "Temps actiu", "uptime": "Temps actiu",
"incident": "Incident", "incident": "Incidència",
"m": "m" "m": "m"
}, },
"atsumeru": { "atsumeru": {
"series": "Series", "series": "Sèries",
"archives": "Archives", "archives": "Arxius",
"chapters": "Chapters", "chapters": "Capítols",
"categories": "Categories" "categories": "Categories"
}, },
"komga": { "komga": {
"libraries": "Libraries", "libraries": "Biblioteques",
"series": "Series", "series": "Sèries",
"books": "Llibres" "books": "Llibres"
}, },
"diskstation": { "diskstation": {
@ -659,77 +659,77 @@
"volumeAvailable": "Disponible" "volumeAvailable": "Disponible"
}, },
"mylar": { "mylar": {
"series": "Series", "series": "Sèries",
"issues": "Issues", "issues": "Problemes",
"wanted": "Volgut" "wanted": "Volgut"
}, },
"photoprism": { "photoprism": {
"albums": "Àlbums", "albums": "Àlbums",
"photos": "Photos", "photos": "Fotos",
"videos": "Vídeos", "videos": "Vídeos",
"people": "People" "people": "Gent"
}, },
"fileflows": { "fileflows": {
"queue": "Cua", "queue": "Cua",
"processing": "Processant", "processing": "Processant",
"processed": "Processed", "processed": "Processat",
"time": "Time" "time": "Temps"
}, },
"grafana": { "grafana": {
"dashboards": "Dashboards", "dashboards": "Taulells",
"datasources": "Data Sources", "datasources": "Origen de dades",
"totalalerts": "Total Alerts", "totalalerts": "Alertes Totals",
"alertstriggered": "Alerts Triggered" "alertstriggered": "Alertes disparades"
}, },
"nextcloud": { "nextcloud": {
"cpuload": "Cpu Load", "cpuload": "Càrrega de CPU",
"memoryusage": "Memory Usage", "memoryusage": "Ús Memòria",
"freespace": "Free Space", "freespace": "Espai lliure",
"activeusers": "Active Users", "activeusers": "Usuaris actius",
"numfiles": "Files", "numfiles": "Fitxers",
"numshares": "Shared Items" "numshares": "Elements compartits"
}, },
"kopia": { "kopia": {
"status": "Estat", "status": "Estat",
"size": "Size", "size": "Mida",
"lastrun": "Last Run", "lastrun": "Darrera execució",
"nextrun": "Next Run", "nextrun": "Següent execució",
"failed": "Error" "failed": "Error"
}, },
"unmanic": { "unmanic": {
"active_workers": "Active Workers", "active_workers": "Treballadors actius",
"total_workers": "Total Workers", "total_workers": "Treballadors Totals",
"records_total": "Queue Length" "records_total": "Llargada de la Cua"
}, },
"pterodactyl": { "pterodactyl": {
"servers": "Servers", "servers": "Servidors",
"nodes": "Nodes" "nodes": "Nodes"
}, },
"prometheus": { "prometheus": {
"targets_up": "Targets Up", "targets_up": "Objectius actius",
"targets_down": "Targets Down", "targets_down": "Objectius caiguts",
"targets_total": "Total Targets" "targets_total": "Objectius Totals"
}, },
"gatus": { "gatus": {
"up": "Sites Up", "up": "Actius",
"down": "Sites Down", "down": "Caiguts",
"uptime": "Temps actiu" "uptime": "Temps actiu"
}, },
"ghostfolio": { "ghostfolio": {
"gross_percent_today": "Today", "gross_percent_today": "Avui",
"gross_percent_1y": "One year", "gross_percent_1y": "Un any",
"gross_percent_max": "All time" "gross_percent_max": "Tot"
}, },
"audiobookshelf": { "audiobookshelf": {
"podcasts": "Podcasts", "podcasts": "Podcasts",
"books": "Llibres", "books": "Llibres",
"podcastsDuration": "Duration", "podcastsDuration": "Durada",
"booksDuration": "Duration" "booksDuration": "Durada"
}, },
"homeassistant": { "homeassistant": {
"people_home": "People Home", "people_home": "Gent a casa",
"lights_on": "Lights On", "lights_on": "Llums enceses",
"switches_on": "Switches On" "switches_on": "Endolls activats"
}, },
"whatsupdocker": { "whatsupdocker": {
"monitoring": "Supervisió", "monitoring": "Supervisió",
@ -737,144 +737,144 @@
}, },
"calibreweb": { "calibreweb": {
"books": "Llibres", "books": "Llibres",
"authors": "Authors", "authors": "Autors",
"categories": "Categories", "categories": "Categories",
"series": "Series" "series": "Sèries"
}, },
"jdownloader": { "jdownloader": {
"downloadCount": "Cua", "downloadCount": "Cua",
"downloadBytesRemaining": "Restant", "downloadBytesRemaining": "Restant",
"downloadTotalBytes": "Size", "downloadTotalBytes": "Mida",
"downloadSpeed": "Velocitat" "downloadSpeed": "Velocitat"
}, },
"kavita": { "kavita": {
"seriesCount": "Series", "seriesCount": "Sèries",
"totalFiles": "Files" "totalFiles": "Fitxers"
}, },
"azuredevops": { "azuredevops": {
"result": "Result", "result": "Resultat",
"status": "Estat", "status": "Estat",
"buildId": "Build ID", "buildId": "Id de compilació",
"succeeded": "Succeeded", "succeeded": "Amb èxit",
"notStarted": "Not Started", "notStarted": "No Iniciat",
"failed": "Error", "failed": "Error",
"canceled": "Canceled", "canceled": "Cancel·lat",
"inProgress": "In Progress", "inProgress": "En curs",
"totalPrs": "Total PRs", "totalPrs": "RP Totals",
"myPrs": "My PRs", "myPrs": "Els meus RP",
"approved": "Aprovat" "approved": "Aprovat"
}, },
"gamedig": { "gamedig": {
"status": "Estat", "status": "Estat",
"online": "Online", "online": "En línia",
"offline": "Fora de línia", "offline": "Fora de línia",
"name": "Name", "name": "Nom",
"map": "Map", "map": "Mapa",
"currentPlayers": "Current players", "currentPlayers": "Jugadors actuals",
"players": "Players", "players": "Jugadors",
"maxPlayers": "Max players", "maxPlayers": "Màxim de jugadors",
"bots": "Bots", "bots": "Bots",
"ping": "Ping" "ping": "Latència"
}, },
"urbackup": { "urbackup": {
"ok": "Ok", "ok": "Ok",
"errored": "Errors", "errored": "Errors",
"noRecent": "Out of Date", "noRecent": "Obsolet",
"totalUsed": "Used Storage" "totalUsed": "Emmagatzematge utilitzat"
}, },
"mealie": { "mealie": {
"recipes": "Recipes", "recipes": "Receptes",
"users": "Usuaris", "users": "Usuaris",
"categories": "Categories", "categories": "Categories",
"tags": "Tags" "tags": "Etiquetes"
}, },
"openmediavault": { "openmediavault": {
"downloading": "Downloading", "downloading": "Descarregant",
"total": "Total", "total": "Total",
"running": "Running", "running": "En execució",
"stopped": "Aturat", "stopped": "Aturat",
"passed": "Aprobat", "passed": "Aprobat",
"failed": "Error" "failed": "Error"
}, },
"openwrt": { "openwrt": {
"uptime": "Temps actiu", "uptime": "Temps actiu",
"cpuLoad": "CPU Load Avg (5m)", "cpuLoad": "Càrrega promig de CPU (5m)",
"up": "Up", "up": "Actiu",
"down": "Down", "down": "Inactiu",
"bytesTx": "Transmitted", "bytesTx": "Enviat",
"bytesRx": "Received" "bytesRx": "Rebuts"
}, },
"uptimerobot": { "uptimerobot": {
"status": "Estat", "status": "Estat",
"uptime": "Temps actiu", "uptime": "Temps actiu",
"lastDown": "Last Downtime", "lastDown": "Darrera Inactivitat",
"downDuration": "Downtime Duration", "downDuration": "Duració d'Inactivitat",
"sitesUp": "Sites Up", "sitesUp": "Actius",
"sitesDown": "Sites Down", "sitesDown": "Caiguts",
"paused": "Paused", "paused": "En pausa",
"notyetchecked": "Not Yet Checked", "notyetchecked": "Sense verificar",
"up": "Up", "up": "Actiu",
"seemsdown": "Seems Down", "seemsdown": "Sembla caigut",
"down": "Down", "down": "Inactiu",
"unknown": "Desconegut" "unknown": "Desconegut"
}, },
"calendar": { "calendar": {
"inCinemas": "In cinemas", "inCinemas": "En cines",
"physicalRelease": "Physical release", "physicalRelease": "Estrena física",
"digitalRelease": "Digital release", "digitalRelease": "Estrena digital",
"noEventsToday": "No events for today!", "noEventsToday": "Cap esdeveniment per avui!",
"noEventsFound": "No events found" "noEventsFound": "No s'han trobat esdeveniments"
}, },
"romm": { "romm": {
"platforms": "Platforms", "platforms": "Plataformes",
"totalRoms": "Total ROMs" "totalRoms": "ROMs totals"
}, },
"netdata": { "netdata": {
"warnings": "Warnings", "warnings": "Avisos",
"criticals": "Criticals" "criticals": "Crítics"
}, },
"plantit": { "plantit": {
"events": "Events", "events": "Esdeveniments",
"plants": "Plants", "plants": "Plantes",
"photos": "Photos", "photos": "Fotos",
"species": "Species" "species": "Espècies"
}, },
"gitea": { "gitea": {
"notifications": "Notifications", "notifications": "Notificacions",
"issues": "Issues", "issues": "Problemes",
"pulls": "Pull Requests" "pulls": "Sol·licitud de Canvis"
}, },
"stash": { "stash": {
"scenes": "Scenes", "scenes": "Escenes",
"scenesPlayed": "Scenes Played", "scenesPlayed": "Escenes reproduïdes",
"playCount": "Total Plays", "playCount": "Total reproduccions",
"playDuration": "Time Watched", "playDuration": "Temps visionat",
"sceneSize": "Scenes Size", "sceneSize": "Tamany Escena",
"sceneDuration": "Scenes Duration", "sceneDuration": "Duració Escenes",
"images": "Images", "images": "Imatges",
"imageSize": "Images Size", "imageSize": "Mida Imatges",
"galleries": "Galleries", "galleries": "Biblioteques",
"performers": "Performers", "performers": "Intèrprets",
"studios": "Studios", "studios": "Estudis",
"movies": "Movies", "movies": "Pel·lícules",
"tags": "Tags", "tags": "Etiquetes",
"oCount": "O Count" "oCount": "O Count"
}, },
"tandoor": { "tandoor": {
"users": "Usuaris", "users": "Usuaris",
"recipes": "Recipes", "recipes": "Receptes",
"keywords": "Keywords" "keywords": "Paraules claus"
}, },
"homebox": { "homebox": {
"items": "Items", "items": "Elements",
"totalWithWarranty": "With Warranty", "totalWithWarranty": "Amb Garantia",
"locations": "Locations", "locations": "Ubicacions",
"labels": "Labels", "labels": "Etiquetes",
"users": "Usuaris", "users": "Usuaris",
"totalValue": "Total Value" "totalValue": "Valor total"
}, },
"crowdsec": { "crowdsec": {
"alerts": "Alerts", "alerts": "Alertes",
"bans": "Bans" "bans": "Prohibicions"
} }
} }

View File

@ -875,6 +875,6 @@
}, },
"crowdsec": { "crowdsec": {
"alerts": "Warnungen", "alerts": "Warnungen",
"bans": "Bans" "bans": "Banns"
} }
} }

View File

@ -15,8 +15,8 @@
"relativeDate": "{{value, relativeDate}}", "relativeDate": "{{value, relativeDate}}",
"uptime": "{{value, uptime}}", "uptime": "{{value, uptime}}",
"months": "mo", "months": "mo",
"days": "d", "days": "g",
"hours": "h", "hours": "o",
"minutes": "m", "minutes": "m",
"seconds": "s" "seconds": "s"
}, },
@ -140,7 +140,7 @@
"connectionStatusPendingDisconnect": "In attesa di disconnessione", "connectionStatusPendingDisconnect": "In attesa di disconnessione",
"connectionStatusDisconnecting": "Disconnessione in corso", "connectionStatusDisconnecting": "Disconnessione in corso",
"connectionStatusDisconnected": "Disconnesso", "connectionStatusDisconnected": "Disconnesso",
"connectionStatusConnected": "Connected", "connectionStatusConnected": "Connesso",
"uptime": "Tempo di attività", "uptime": "Tempo di attività",
"maxDown": "Max. Down", "maxDown": "Max. Down",
"maxUp": "Max. Up", "maxUp": "Max. Up",
@ -279,9 +279,9 @@
}, },
"netalertx": { "netalertx": {
"total": "Totale", "total": "Totale",
"connected": "Connected", "connected": "Connesso",
"new_devices": "New Devices", "new_devices": "Nuovi Dispositivi",
"down_alerts": "Down Alerts" "down_alerts": "Avvisi di Disservizio"
}, },
"pihole": { "pihole": {
"queries": "Richieste", "queries": "Richieste",
@ -411,8 +411,8 @@
"total": "Totale", "total": "Totale",
"free": "Libero", "free": "Libero",
"used": "In utilizzo", "used": "In utilizzo",
"days": "d", "days": "g",
"hours": "h", "hours": "o",
"crit": "Critico", "crit": "Critico",
"read": "Letti", "read": "Letti",
"write": "Scrittura", "write": "Scrittura",
@ -427,7 +427,7 @@
"custom": "Personalizzato", "custom": "Personalizzato",
"visit": "Visita", "visit": "Visita",
"url": "URL", "url": "URL",
"searchsuggestion": "Suggestion" "searchsuggestion": "Suggerimenti"
}, },
"wmo": { "wmo": {
"0-day": "Soleggiato", "0-day": "Soleggiato",
@ -546,8 +546,8 @@
"hd": "HD", "hd": "HD",
"tunerCount": "Tuners", "tunerCount": "Tuners",
"channelNumber": "Channel", "channelNumber": "Channel",
"channelNetwork": "Network", "channelNetwork": "Rete",
"signalStrength": "Strength", "signalStrength": "Intensità",
"signalQuality": "Quality", "signalQuality": "Quality",
"symbolQuality": "Quality", "symbolQuality": "Quality",
"networkRate": "Bitrate", "networkRate": "Bitrate",
@ -830,32 +830,32 @@
"totalRoms": "Total ROMs" "totalRoms": "Total ROMs"
}, },
"netdata": { "netdata": {
"warnings": "Warnings", "warnings": "Avvisi",
"criticals": "Criticals" "criticals": "Criticals"
}, },
"plantit": { "plantit": {
"events": "Events", "events": "Events",
"plants": "Plants", "plants": "Plants",
"photos": "Foto", "photos": "Foto",
"species": "Species" "species": "Specie"
}, },
"gitea": { "gitea": {
"notifications": "Notifications", "notifications": "Notifiche",
"issues": "Problemi", "issues": "Problemi",
"pulls": "Pull Requests" "pulls": "Richieste di Pull"
}, },
"stash": { "stash": {
"scenes": "Scenes", "scenes": "Scene",
"scenesPlayed": "Scenes Played", "scenesPlayed": "Scene Riprodotte",
"playCount": "Total Plays", "playCount": "Totale Riproduzioni",
"playDuration": "Time Watched", "playDuration": "Tempo Guardato",
"sceneSize": "Scenes Size", "sceneSize": "Dimensione Delle Scene",
"sceneDuration": "Scenes Duration", "sceneDuration": "Durata Delle Scene",
"images": "Images", "images": "Immagini",
"imageSize": "Images Size", "imageSize": "Images Size",
"galleries": "Galleries", "galleries": "Galleries",
"performers": "Performers", "performers": "Esecutori",
"studios": "Studios", "studios": "Studi",
"movies": "Film", "movies": "Film",
"tags": "Tag", "tags": "Tag",
"oCount": "O Count" "oCount": "O Count"

View File

@ -140,7 +140,7 @@
"connectionStatusPendingDisconnect": "Čakanje na prekinitev", "connectionStatusPendingDisconnect": "Čakanje na prekinitev",
"connectionStatusDisconnecting": "Prekinitev", "connectionStatusDisconnecting": "Prekinitev",
"connectionStatusDisconnected": "Prekinjeno", "connectionStatusDisconnected": "Prekinjeno",
"connectionStatusConnected": "Connected", "connectionStatusConnected": "Povezan",
"uptime": "Čas delovanja", "uptime": "Čas delovanja",
"maxDown": "Maks. dol", "maxDown": "Maks. dol",
"maxUp": "Maks. gor", "maxUp": "Maks. gor",
@ -279,9 +279,9 @@
}, },
"netalertx": { "netalertx": {
"total": "Skupaj", "total": "Skupaj",
"connected": "Connected", "connected": "Povezan",
"new_devices": "New Devices", "new_devices": "Nova naprave",
"down_alerts": "Down Alerts" "down_alerts": "Alarmi nedelovanja"
}, },
"pihole": { "pihole": {
"queries": "Poizvedbe", "queries": "Poizvedbe",

View File

@ -104,7 +104,7 @@
"no_active": "Inga aktiva strömmar", "no_active": "Inga aktiva strömmar",
"movies": "Movies", "movies": "Movies",
"series": "Series", "series": "Series",
"episodes": "Episodes", "episodes": "Avsnitt",
"songs": "Songs" "songs": "Songs"
}, },
"esphome": { "esphome": {
@ -423,7 +423,7 @@
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service", "service": "Service",
"search": "Search", "search": "Sök",
"custom": "Custom", "custom": "Custom",
"visit": "Visit", "visit": "Visit",
"url": "URL", "url": "URL",

View File

@ -9,7 +9,7 @@ function convertToFahrenheit(t) {
return (t * 9) / 5 + 32; return (t * 9) / 5 + 32;
} }
export default function CpuTemp({ expanded, units, refresh = 1500 }) { export default function CpuTemp({ expanded, units, refresh = 1500, tempmin = 0, tempmax = -1 }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, error } = useSWR(`/api/widgets/resources?type=cputemp`, { const { data, error } = useSWR(`/api/widgets/resources?type=cputemp`, {
@ -39,7 +39,12 @@ export default function CpuTemp({ expanded, units, refresh = 1500 }) {
} }
const unit = units === "imperial" ? "fahrenheit" : "celsius"; const unit = units === "imperial" ? "fahrenheit" : "celsius";
mainTemp = unit === "celsius" ? mainTemp : convertToFahrenheit(mainTemp); mainTemp = unit === "celsius" ? mainTemp : convertToFahrenheit(mainTemp);
const maxTemp = unit === "celsius" ? data.cputemp.max : convertToFahrenheit(data.cputemp.max);
const minTemp = tempmin < mainTemp ? tempmin : mainTemp;
let maxTemp = tempmax;
if (maxTemp < minTemp) {
maxTemp = unit === "celsius" ? data.cputemp.max : convertToFahrenheit(data.cputemp.max);
}
return ( return (
<Resource <Resource
@ -58,7 +63,7 @@ export default function CpuTemp({ expanded, units, refresh = 1500 }) {
unit, unit,
})} })}
expandedLabel={t("resources.max")} expandedLabel={t("resources.max")}
percentage={Math.round((mainTemp / maxTemp) * 100)} percentage={Math.round(((mainTemp - minTemp) / (maxTemp - minTemp)) * 100)}
expanded={expanded} expanded={expanded}
/> />
); );

View File

@ -8,7 +8,7 @@ import CpuTemp from "./cputemp";
import Uptime from "./uptime"; import Uptime from "./uptime";
export default function Resources({ options }) { export default function Resources({ options }) {
const { expanded, units, diskUnits } = options; const { expanded, units, diskUnits, tempmin, tempmax } = options;
let { refresh } = options; let { refresh } = options;
if (!refresh) refresh = 1500; if (!refresh) refresh = 1500;
refresh = Math.max(refresh, 1000); refresh = Math.max(refresh, 1000);
@ -23,7 +23,9 @@ export default function Resources({ options }) {
<Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} /> <Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />
)) ))
: options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />} : options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />}
{options.cputemp && <CpuTemp expanded={expanded} units={units} refresh={refresh} />} {options.cputemp && (
<CpuTemp expanded={expanded} units={units} refresh={refresh} tempmin={tempmin} tempmax={tempmax} />
)}
{options.uptime && <Uptime refresh={refresh} />} {options.uptime && <Uptime refresh={refresh} />}
</div> </div>
{options.label && ( {options.label && (

View File

@ -393,6 +393,11 @@ export function cleanServiceGroups(groups) {
enableBlocks, enableBlocks,
enableNowPlaying, enableNowPlaying,
// emby, jellyfin, tautulli
enableUser,
expandOneStreamToTwoRows,
showEpisodeNumber,
// glances, pihole // glances, pihole
version, version,
@ -445,6 +450,9 @@ export function cleanServiceGroups(groups) {
// proxmox // proxmox
node, node,
// speedtest
bitratePrecision,
// sonarr, radarr // sonarr, radarr
enableQueue, enableQueue,
@ -518,6 +526,13 @@ export function cleanServiceGroups(groups) {
if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = JSON.parse(enableBlocks); if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = JSON.parse(enableBlocks);
if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = JSON.parse(enableNowPlaying); if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = JSON.parse(enableNowPlaying);
} }
if (["emby", "jellyfin", "tautulli"].includes(type)) {
if (expandOneStreamToTwoRows !== undefined)
cleanedService.widget.expandOneStreamToTwoRows = !!JSON.parse(expandOneStreamToTwoRows);
if (showEpisodeNumber !== undefined)
cleanedService.widget.showEpisodeNumber = !!JSON.parse(showEpisodeNumber);
if (enableUser !== undefined) cleanedService.widget.enableUser = !!JSON.parse(enableUser);
}
if (["sonarr", "radarr"].includes(type)) { if (["sonarr", "radarr"].includes(type)) {
if (enableQueue !== undefined) cleanedService.widget.enableQueue = JSON.parse(enableQueue); if (enableQueue !== undefined) cleanedService.widget.enableQueue = JSON.parse(enableQueue);
} }
@ -576,6 +591,11 @@ export function cleanServiceGroups(groups) {
if (type === "healthchecks") { if (type === "healthchecks") {
if (uuid !== undefined) cleanedService.widget.uuid = uuid; if (uuid !== undefined) cleanedService.widget.uuid = uuid;
} }
if (type === "speedtest") {
if (bitratePrecision !== undefined) {
cleanedService.widget.bitratePrecision = parseInt(bitratePrecision, 10);
}
}
} }
return cleanedService; return cleanedService;

View File

@ -27,9 +27,26 @@ function ticksToString(ticks) {
return parts.map((part) => part.toString().padStart(2, "0")).join(":"); return parts.map((part) => part.toString().padStart(2, "0")).join(":");
} }
function SingleSessionEntry({ playCommand, session }) { function generateStreamTitle(session, enableUser, showEpisodeNumber) {
const {
NowPlayingItem: { Name, SeriesName, Type, ParentIndexNumber, IndexNumber },
UserName,
} = session;
let streamTitle = "";
if (Type === "Episode" && showEpisodeNumber) {
const seasonStr = `S${ParentIndexNumber.toString().padStart(2, "0")}`;
const episodeStr = `E${IndexNumber.toString().padStart(2, "0")}`;
streamTitle = `${SeriesName}: ${seasonStr} · ${episodeStr} - ${Name}`;
} else {
streamTitle = `${Name}${SeriesName ? ` - ${SeriesName}` : ""}`;
}
return enableUser ? `${streamTitle} (${UserName})` : streamTitle;
}
function SingleSessionEntry({ playCommand, session, enableUser, showEpisodeNumber }) {
const { const {
NowPlayingItem: { Name, SeriesName },
PlayState: { PositionTicks, IsPaused, IsMuted }, PlayState: { PositionTicks, IsPaused, IsMuted },
} = session; } = session;
@ -42,13 +59,13 @@ function SingleSessionEntry({ playCommand, session }) {
const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100; const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100;
const streamTitle = generateStreamTitle(session, enableUser, showEpisodeNumber);
return ( return (
<> <>
<div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex"> <div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex">
<div className="grow text-xs z-10 self-center ml-2 relative w-full h-4 mr-2"> <div className="grow text-xs z-10 self-center ml-2 relative w-full h-4 mr-2">
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden"> <div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden" title={streamTitle}>
{Name} {streamTitle}
{SeriesName && ` - ${SeriesName}`}
</div> </div>
</div> </div>
<div className="self-center text-xs flex justify-end mr-1.5 pl-1"> <div className="self-center text-xs flex justify-end mr-1.5 pl-1">
@ -97,9 +114,8 @@ function SingleSessionEntry({ playCommand, session }) {
); );
} }
function SessionEntry({ playCommand, session }) { function SessionEntry({ playCommand, session, enableUser, showEpisodeNumber }) {
const { const {
NowPlayingItem: { Name, SeriesName },
PlayState: { PositionTicks, IsPaused, IsMuted }, PlayState: { PositionTicks, IsPaused, IsMuted },
} = session; } = session;
@ -110,6 +126,8 @@ function SessionEntry({ playCommand, session }) {
IsVideoDirect: true, IsVideoDirect: true,
}; // if no transcodinginfo its videodirect }; // if no transcodinginfo its videodirect
const streamTitle = generateStreamTitle(session, enableUser, showEpisodeNumber);
const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100; const percent = Math.min(1, PositionTicks / RunTimeTicks) * 100;
return ( return (
@ -139,9 +157,8 @@ function SessionEntry({ playCommand, session }) {
)} )}
</div> </div>
<div className="grow text-xs z-10 self-center relative w-full h-4"> <div className="grow text-xs z-10 self-center relative w-full h-4">
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden"> <div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden" title={streamTitle}>
{Name} {streamTitle}
{SeriesName && ` - ${SeriesName}`}
</div> </div>
</div> </div>
<div className="self-center text-xs flex justify-end mr-1 z-10">{IsMuted && <BsVolumeMuteFill />}</div> <div className="self-center text-xs flex justify-end mr-1 z-10">{IsMuted && <BsVolumeMuteFill />}</div>
@ -215,6 +232,9 @@ export default function Component({ service }) {
const enableBlocks = service.widget?.enableBlocks; const enableBlocks = service.widget?.enableBlocks;
const enableNowPlaying = service.widget?.enableNowPlaying ?? true; const enableNowPlaying = service.widget?.enableNowPlaying ?? true;
const enableUser = !!service.widget?.enableUser; // default is false
const expandOneStreamToTwoRows = service.widget?.expandOneStreamToTwoRows !== false; // default is true
const showEpisodeNumber = !!service.widget?.showEpisodeNumber; // default is false
if (!sessionsData || !countData) { if (!sessionsData || !countData) {
return ( return (
@ -225,9 +245,11 @@ export default function Component({ service }) {
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">-</span> <span className="absolute left-2 text-xs mt-[2px]">-</span>
</div> </div>
{expandOneStreamToTwoRows && (
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">-</span> <span className="absolute left-2 text-xs mt-[2px]">-</span>
</div> </div>
)}
</div> </div>
)} )}
</> </>
@ -255,15 +277,17 @@ export default function Component({ service }) {
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">{t("emby.no_active")}</span> <span className="absolute left-2 text-xs mt-[2px]">{t("emby.no_active")}</span>
</div> </div>
{expandOneStreamToTwoRows && (
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">-</span> <span className="absolute left-2 text-xs mt-[2px]">-</span>
</div> </div>
)}
</div> </div>
</> </>
); );
} }
if (playing.length === 1) { if (expandOneStreamToTwoRows && playing.length === 1) {
const session = playing[0]; const session = playing[0];
return ( return (
<> <>
@ -272,13 +296,14 @@ export default function Component({ service }) {
<SingleSessionEntry <SingleSessionEntry
playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)} playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)}
session={session} session={session}
enableUser={enableUser}
showEpisodeNumber={showEpisodeNumber}
/> />
</div> </div>
</> </>
); );
} }
if (playing.length > 0)
return ( return (
<> <>
{enableBlocks && <CountBlocks service={service} countData={countData} />} {enableBlocks && <CountBlocks service={service} countData={countData} />}
@ -288,6 +313,8 @@ export default function Component({ service }) {
key={session.Id} key={session.Id}
playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)} playCommand={(currentSession, command) => handlePlayCommand(currentSession, command)}
session={session} session={session}
enableUser={enableUser}
showEpisodeNumber={showEpisodeNumber}
/> />
))} ))}
</div> </div>

View File

@ -32,7 +32,7 @@ export default function Component({ service }) {
let blockedValue = `${t("common.number", { value: parseInt(piholeData.ads_blocked_today, 10) })}`; let blockedValue = `${t("common.number", { value: parseInt(piholeData.ads_blocked_today, 10) })}`;
if (!widget.fields.includes("blocked_percent")) { if (!widget.fields.includes("blocked_percent")) {
blockedValue += ` (${t("common.percent", { value: parseFloat(piholeData.ads_percentage_today.toPrecision(3)) })})`; blockedValue += ` (${t("common.percent", { value: parseFloat(piholeData.ads_percentage_today).toPrecision(3) })})`;
} }
return ( return (
@ -41,7 +41,7 @@ export default function Component({ service }) {
<Block label="pihole.blocked" value={blockedValue} /> <Block label="pihole.blocked" value={blockedValue} />
<Block <Block
label="pihole.blocked_percent" label="pihole.blocked_percent"
value={t("common.percent", { value: parseFloat(piholeData.ads_percentage_today.toPrecision(3)) })} value={t("common.percent", { value: parseFloat(piholeData.ads_percentage_today).toPrecision(3) })}
/> />
<Block <Block
label="pihole.gravity" label="pihole.gravity"

View File

@ -1,9 +1,12 @@
import { useTranslation } from "next-i18next";
import Container from "components/services/widget/container"; import Container from "components/services/widget/container";
import Block from "components/services/widget/block"; import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) { export default function Component({ service }) {
const { widget } = service; const { widget } = service;
const { t } = useTranslation();
const { data: response, error: responseError } = useWidgetAPI(widget, "statistics"); const { data: response, error: responseError } = useWidgetAPI(widget, "statistics");
@ -24,8 +27,8 @@ export default function Component({ service }) {
const totalRoms = response.reduce((total, stat) => total + stat.rom_count, 0); const totalRoms = response.reduce((total, stat) => total + stat.rom_count, 0);
return ( return (
<Container service={service}> <Container service={service}>
<Block label="romm.platforms" value={platforms} /> <Block label="romm.platforms" value={t("common.number", { value: platforms })} />
<Block label="romm.totalRoms" value={totalRoms} /> <Block label="romm.totalRoms" value={t("common.number", { value: totalRoms })} />
</Container> </Container>
); );
} }

View File

@ -11,6 +11,11 @@ export default function Component({ service }) {
const { data: speedtestData, error: speedtestError } = useWidgetAPI(widget, "speedtest/latest"); const { data: speedtestData, error: speedtestError } = useWidgetAPI(widget, "speedtest/latest");
const bitratePrecision =
!widget?.bitratePrecision || Number.isNaN(widget?.bitratePrecision) || widget?.bitratePrecision < 0
? 0
: widget.bitratePrecision;
if (speedtestError) { if (speedtestError) {
return <Container service={service} error={speedtestError} />; return <Container service={service} error={speedtestError} />;
} }
@ -29,9 +34,18 @@ export default function Component({ service }) {
<Container service={service}> <Container service={service}>
<Block <Block
label="speedtest.download" label="speedtest.download"
value={t("common.bitrate", { value: speedtestData.data.download * 1000 * 1000 })} value={t("common.bitrate", {
value: speedtestData.data.download * 1000 * 1000,
decimals: bitratePrecision,
})}
/>
<Block
label="speedtest.upload"
value={t("common.bitrate", {
value: speedtestData.data.upload * 1000 * 1000,
decimals: bitratePrecision,
})}
/> />
<Block label="speedtest.upload" value={t("common.bitrate", { value: speedtestData.data.upload * 1000 * 1000 })} />
<Block <Block
label="speedtest.ping" label="speedtest.ping"
value={t("common.ms", { value={t("common.ms", {

View File

@ -25,14 +25,32 @@ function millisecondsToString(milliseconds) {
return parts.map((part) => part.toString().padStart(2, "0")).join(":"); return parts.map((part) => part.toString().padStart(2, "0")).join(":");
} }
function SingleSessionEntry({ session }) { function generateStreamTitle(session, enableUser, showEpisodeNumber) {
const { full_title, duration, view_offset, progress_percent, state, video_decision, audio_decision } = session; let stream_title = "";
const { media_type, parent_media_index, media_index, title, grandparent_title, full_title, friendly_name } = session;
if (media_type === "episode" && showEpisodeNumber) {
const season_str = `S${parent_media_index.toString().padStart(2, "0")}`;
const episode_str = `E${media_index.toString().padStart(2, "0")}`;
stream_title = `${grandparent_title}: ${season_str} · ${episode_str} - ${title}`;
} else {
stream_title = full_title;
}
return enableUser ? `${stream_title} (${friendly_name})` : stream_title;
}
function SingleSessionEntry({ session, enableUser, showEpisodeNumber }) {
const { duration, view_offset, progress_percent, state, video_decision, audio_decision } = session;
const stream_title = generateStreamTitle(session, enableUser, showEpisodeNumber);
return ( return (
<> <>
<div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex"> <div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex">
<div className="text-xs z-10 self-center ml-2 relative w-full h-4 grow mr-2"> <div className="text-xs z-10 self-center ml-2 relative w-full h-4 grow mr-2">
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden">{full_title}</div> <div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden" title={stream_title}>
{stream_title}
</div>
</div> </div>
<div className="self-center text-xs flex justify-end mr-1.5 pl-1"> <div className="self-center text-xs flex justify-end mr-1.5 pl-1">
{video_decision === "direct play" && audio_decision === "direct play" && ( {video_decision === "direct play" && audio_decision === "direct play" && (
@ -74,8 +92,10 @@ function SingleSessionEntry({ session }) {
); );
} }
function SessionEntry({ session }) { function SessionEntry({ session, enableUser, showEpisodeNumber }) {
const { full_title, view_offset, progress_percent, state, video_decision, audio_decision } = session; const { view_offset, progress_percent, state, video_decision, audio_decision } = session;
const stream_title = generateStreamTitle(session, enableUser, showEpisodeNumber);
return ( return (
<div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex"> <div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex">
@ -94,7 +114,9 @@ function SessionEntry({ session }) {
)} )}
</div> </div>
<div className="text-xs z-10 self-center ml-2 relative w-full h-4 grow mr-2"> <div className="text-xs z-10 self-center ml-2 relative w-full h-4 grow mr-2">
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden">{full_title}</div> <div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden" title={stream_title}>
{stream_title}
</div>
</div> </div>
<div className="self-center text-xs flex justify-end mr-1.5 pl-1 z-10"> <div className="self-center text-xs flex justify-end mr-1.5 pl-1 z-10">
{video_decision === "direct play" && audio_decision === "direct play" && ( {video_decision === "direct play" && audio_decision === "direct play" && (
@ -122,6 +144,10 @@ export default function Component({ service }) {
refreshInterval: 5000, refreshInterval: 5000,
}); });
const enableUser = !!service.widget?.enableUser; // default is false
const expandOneStreamToTwoRows = service.widget?.expandOneStreamToTwoRows !== false; // default is true
const showEpisodeNumber = !!service.widget?.showEpisodeNumber; // default is false
if (activityError || (activityData && Object.keys(activityData.response.data).length === 0)) { if (activityError || (activityData && Object.keys(activityData.response.data).length === 0)) {
return <Container service={service} error={activityError ?? { message: t("tautulli.plex_connection_error") }} />; return <Container service={service} error={activityError ?? { message: t("tautulli.plex_connection_error") }} />;
} }
@ -132,9 +158,11 @@ export default function Component({ service }) {
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">-</span> <span className="absolute left-2 text-xs mt-[2px]">-</span>
</div> </div>
{expandOneStreamToTwoRows && (
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">-</span> <span className="absolute left-2 text-xs mt-[2px]">-</span>
</div> </div>
)}
</div> </div>
); );
} }
@ -155,18 +183,20 @@ export default function Component({ service }) {
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">{t("tautulli.no_active")}</span> <span className="absolute left-2 text-xs mt-[2px]">{t("tautulli.no_active")}</span>
</div> </div>
{expandOneStreamToTwoRows && (
<div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1"> <div className="text-theme-700 dark:text-theme-200 text-xs relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1">
<span className="absolute left-2 text-xs mt-[2px]">-</span> <span className="absolute left-2 text-xs mt-[2px]">-</span>
</div> </div>
)}
</div> </div>
); );
} }
if (playing.length === 1) { if (expandOneStreamToTwoRows && playing.length === 1) {
const session = playing[0]; const session = playing[0];
return ( return (
<div className="flex flex-col pb-1 mx-1"> <div className="flex flex-col pb-1 mx-1">
<SingleSessionEntry session={session} /> <SingleSessionEntry session={session} enableUser={enableUser} showEpisodeNumber={showEpisodeNumber} />
</div> </div>
); );
} }
@ -174,7 +204,12 @@ export default function Component({ service }) {
return ( return (
<div className="flex flex-col pb-1 mx-1"> <div className="flex flex-col pb-1 mx-1">
{playing.map((session) => ( {playing.map((session) => (
<SessionEntry key={session.Id} session={session} /> <SessionEntry
key={session.Id}
session={session}
enableUser={enableUser}
showEpisodeNumber={showEpisodeNumber}
/>
))} ))}
</div> </div>
); );