Compare commits

..

17 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
12 changed files with 142 additions and 133 deletions

View File

@@ -1,25 +1,25 @@
{
"resources": {
"used": "Used",
"load": "Load",
"used": "χρησιμοποιημένο",
"load": "Φόρτωση",
"cpu": "CPU",
"mem": "MEM",
"temp": "TEMP",
"total": "Total",
"free": "Free",
"max": "Max",
"uptime": "UP",
"temp": "ΘΕΡΜΟΚΡΑΣΪΑ",
"total": "Σύνολο",
"free": "Δωρεάν",
"max": "Μέγιστο",
"uptime": "ΠΑΝΩ",
"months": "mo",
"days": "d",
"hours": "h",
"minutes": "m"
},
"omada": {
"activeUser": "Active devices",
"alerts": "Alerts",
"connectedAp": "Connected APs",
"connectedGateway": "Connected gateways",
"connectedSwitches": "Connected switches"
"activeUser": "Ενεργές συσκευές",
"alerts": "Ειδοποιήσεις",
"connectedAp": "Συνδεδεμένα APs",
"connectedGateway": "Συνδεδεμένα gateways",
"connectedSwitches": "Συνδεδεμένα switches"
},
"wmo": {
"0-night": "Clear",
@@ -84,120 +84,120 @@
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
},
"widget": {
"missing_type": "Missing Widget Type: {{type}}",
"api_error": "API Error",
"information": "Information",
"status": "Status",
"missing_type": "Λείπει ο τύπος widget: {{type}}",
"api_error": "Σφάλμα API",
"information": "Πληροφορία",
"status": "Κατάσταση",
"url": "URL",
"raw_error": "Raw Error",
"response_data": "Response Data"
"raw_error": "Ανεπεξέργαστο σφάλμα",
"response_data": "Δεδομένα απόκρισης"
},
"weather": {
"current": "Current Location",
"allow": "Click to allow",
"updating": "Updating",
"wait": "Please wait"
"current": "Τωρινή τοποθεσία",
"allow": "Κάντε κλικ για να επιτρέψετε",
"updating": "Ενημέρωση",
"wait": "Παρακαλώ περιμένετε"
},
"search": {
"placeholder": "Search…"
"placeholder": "Αναζήτηση…"
},
"unifi": {
"users": "Users",
"uptime": "System Uptime",
"days": "Days",
"users": "Χρήστες",
"uptime": "Χρόνος λειτουργίας συστήματος",
"days": "Ημέρες",
"wan": "WAN",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Devices",
"lan_devices": "LAN Devices",
"wlan_devices": "WLAN Devices",
"lan_users": "LAN Users",
"wlan_users": "WLAN Users",
"up": "UP",
"down": "DOWN",
"wait": "Please wait",
"empty_data": "Subsystem status unknown"
"devices": "Συσκευές",
"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": "Running",
"offline": "Offline",
"error": "Error",
"unknown": "Unknown",
"healthy": "Healthy",
"exited": "Exited",
"starting": "Starting",
"partial": "Partial",
"unhealthy": "Unhealthy",
"not_found": "Not Found"
"running": "Τρέχων",
"offline": "Εκτός σύνδεσης",
"error": "Σφάλμα",
"unknown": "Άγνωστο",
"healthy": "Υγειές",
"exited": "Έκλεισε",
"starting": "Ξεκινάει",
"partial": "Μερικό",
"unhealthy": "Άρρωστο",
"not_found": "Δεν βρέθηκε"
},
"ping": {
"error": "Error",
"error": "Σφάλμα",
"ping": "Ping"
},
"emby": {
"playing": "Playing",
"transcoding": "Transcoding",
"bitrate": "Bitrate",
"no_active": "No Active Streams",
"movies": "Movies",
"series": "Series",
"episodes": "Episodes",
"songs": "Songs"
"playing": "Παίζει",
"transcoding": "Διακωδικοποίηση",
"bitrate": "Ρυθμός bit",
"no_active": "Δεν υπάρχουν ενεργές ροές",
"movies": "Ταινίες",
"series": "Σειρές",
"episodes": "Επεισόδια",
"songs": "Τραγούδια"
},
"flood": {
"download": "Download",
"upload": "Upload",
"leech": "Leech",
"seed": "Seed"
"download": "Κατέβασμα",
"upload": "Ανέβασμα",
"leech": "Αφαίμαξη",
"seed": "Σπείρε"
},
"changedetectionio": {
"totalObserved": "Total Observed",
"diffsDetected": "Diffs Detected"
"totalObserved": "Συνολικά παρατηρηθείσα",
"diffsDetected": "Εντοπίστηκαν διαφορές"
},
"tautulli": {
"playing": "Playing",
"transcoding": "Transcoding",
"bitrate": "Bitrate",
"no_active": "No Active Streams"
"playing": "Παίζει",
"transcoding": "Διακωδικοποίηση",
"bitrate": "Ρυθμός bit",
"no_active": "Δεν υπάρχουν ενεργές ροές"
},
"nzbget": {
"rate": "Rate",
"remaining": "Remaining",
"downloaded": "Downloaded"
"rate": "βαθμός",
"remaining": "Υπόλοιπο",
"downloaded": "Κατεβασμένο"
},
"plex": {
"streams": "Active Streams",
"movies": "Movies",
"tv": "TV Shows"
"streams": "Ενεργά Streams",
"movies": "Ταινίες",
"tv": "Σειρές"
},
"sabnzbd": {
"rate": "Rate",
"queue": "Queue",
"timeleft": "Time Left"
"rate": "Βαθμός",
"queue": "Ουρά",
"timeleft": "Χρόνος που απομένει"
},
"rutorrent": {
"active": "Active",
"upload": "Upload",
"download": "Download"
"active": "Ενεργό",
"upload": "Ανέβασμα",
"download": "Κατέβασμα"
},
"transmission": {
"download": "Download",
"upload": "Upload",
"download": "Κατέβασμα",
"upload": "Ανέβασμα",
"leech": "Leech",
"seed": "Seed"
},
"qbittorrent": {
"download": "Download",
"upload": "Upload",
"download": "Κατέβασμα",
"upload": "Ανέβασμα",
"leech": "Leech",
"seed": "Seed"
},
"deluge": {
"download": "Download",
"download": "Κατέβασμα",
"upload": "Upload",
"leech": "Leech",
"seed": "Seed"
@@ -561,6 +561,6 @@
"podcasts": "Podcasts",
"books": "Books",
"podcastsDuration": "Duration",
"booksDuration": "Duration"
"booksDuration": "Διάρκεια"
}
}

View File

@@ -158,7 +158,7 @@
"transmission": {
"download": "Bajada",
"upload": "Subida",
"leech": "Sanguijuela",
"leech": "Compañeros",
"seed": "Semillas"
},
"jackett": {
@@ -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",
@@ -233,7 +233,7 @@
"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": "Todos los flujos",
"streams_active": "Flujos activos",
"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",
"temp_bed": "Temperatura de la plataforma",
"printer_state": "Estado",
"temp_tool": "Temperatura de herramienta",
"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

@@ -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 2xl:basis-1/5",
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

@@ -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

@@ -236,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)) {
@@ -297,8 +298,8 @@ export function cleanServiceGroups(groups) {
if (wan) cleanedService.widget.wan = wan;
}
if (type === "emby" || type === "jellyfin") {
if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = enableBlocks;
if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = enableNowPlaying;
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

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