mirror of
https://github.com/karl0ss/homepage.git
synced 2025-05-03 14:03:40 +01:00
Merge branch 'benphelps:main' into main
This commit is contained in:
commit
32c4eb87e7
@ -194,7 +194,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "مطلوب",
|
||||
"queued": "في الإنتظار",
|
||||
"albums": "ألبومات"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "مطلوب",
|
||||
|
@ -132,7 +132,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Volgut",
|
||||
"queued": "En cua",
|
||||
"albums": "Àlbums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Consultes",
|
||||
|
@ -148,7 +148,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Hledané",
|
||||
"queued": "Ve frontě",
|
||||
"albums": "Alba"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Hledané",
|
||||
|
@ -16,7 +16,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Ønsket",
|
||||
"queued": "I Kø",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"available": "Tilgængelig",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Gesucht",
|
||||
"queued": "In Warteschlange",
|
||||
"albums": "Alben"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Anfragen",
|
||||
|
@ -227,7 +227,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Θέλετε",
|
||||
"queued": "Στη σειρά",
|
||||
"albums": "Δίσκοι"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Θέλετε",
|
||||
|
@ -209,7 +209,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -146,7 +146,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albumoj"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -67,16 +67,16 @@
|
||||
"wanted": "Buscando",
|
||||
"queued": "En cola",
|
||||
"series": "Series",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Poner a la cola",
|
||||
"unknown": "Desconocido"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Buscando",
|
||||
"queued": "En cola",
|
||||
"movies": "Películas",
|
||||
"missing": "Faltan",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Poner a la cola",
|
||||
"unknown": "Desconocido"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Buscando",
|
||||
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"queued": "En cola",
|
||||
"wanted": "Buscando",
|
||||
"albums": "Álbumes"
|
||||
"artists": "Artistas"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Consultas",
|
||||
|
@ -109,7 +109,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Haluttu",
|
||||
"queued": "Jonossa",
|
||||
"albums": "Albumeja"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Haluttu",
|
||||
|
@ -67,16 +67,16 @@
|
||||
"wanted": "Demande",
|
||||
"queued": "Attente",
|
||||
"series": "Séries",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Attente",
|
||||
"unknown": "Inconnu"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Demande",
|
||||
"queued": "Attente",
|
||||
"movies": "Films",
|
||||
"missing": "Manquant",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Attente",
|
||||
"unknown": "Inconnu"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Demande",
|
||||
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Demandé",
|
||||
"queued": "En queue",
|
||||
"albums": "Albums"
|
||||
"artists": "Artistes"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Requêtes",
|
||||
@ -401,7 +401,7 @@
|
||||
"queue": "À traiter",
|
||||
"processed": "Traité",
|
||||
"errored": "En erreur",
|
||||
"saved": "Gagné"
|
||||
"saved": "Libéré"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Lu",
|
||||
|
@ -109,7 +109,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "מבוקש",
|
||||
"queued": "בתור",
|
||||
"albums": "אלבומים"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "מבוקש",
|
||||
|
@ -170,7 +170,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Pending",
|
||||
|
@ -140,7 +140,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Zatraženo",
|
||||
"queued": "U redu čekanja",
|
||||
"albums": "Albumi"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Zatraženo",
|
||||
|
@ -31,9 +31,9 @@
|
||||
"healthy": "Healthy"
|
||||
},
|
||||
"lidarr": {
|
||||
"albums": "Albumok",
|
||||
"wanted": "Keresett",
|
||||
"queued": "Sorban áll"
|
||||
"queued": "Sorban áll",
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Keresett",
|
||||
|
@ -70,7 +70,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Mancanti",
|
||||
"queued": "In coda",
|
||||
"albums": "Album"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Interrogazioni",
|
||||
|
@ -63,7 +63,7 @@
|
||||
"resources": {
|
||||
"cpu": "CPU",
|
||||
"total": "合計",
|
||||
"free": "フリー",
|
||||
"free": "Free",
|
||||
"used": "使用",
|
||||
"load": "ロード",
|
||||
"mem": "MEM",
|
||||
@ -208,7 +208,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "募集中",
|
||||
"queued": "キュー",
|
||||
"albums": "アルバム"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "募集中",
|
||||
@ -609,11 +609,11 @@
|
||||
"ago": "{{value}} 前"
|
||||
},
|
||||
"qnap": {
|
||||
"cpuUsage": "CPU Usage",
|
||||
"memUsage": "MEM Usage",
|
||||
"systemTempC": "System Temp",
|
||||
"poolUsage": "Pool Usage",
|
||||
"volumeUsage": "Volume Usage",
|
||||
"cpuUsage": "CPU使用量",
|
||||
"memUsage": "MEM使用量",
|
||||
"systemTempC": "システム温度",
|
||||
"poolUsage": "プール使用量",
|
||||
"volumeUsage": "ボリューム使用量",
|
||||
"invalid": "Invalid"
|
||||
},
|
||||
"pfsense": {
|
||||
@ -633,11 +633,11 @@
|
||||
},
|
||||
"evcc": {
|
||||
"watt_hour": "Wh",
|
||||
"pv_power": "Production",
|
||||
"battery_soc": "Battery",
|
||||
"grid_power": "Grid",
|
||||
"home_power": "Consumption",
|
||||
"charge_power": "Charger"
|
||||
"pv_power": "発電量",
|
||||
"battery_soc": "バッテリー",
|
||||
"grid_power": "グリッド",
|
||||
"home_power": "消費",
|
||||
"charge_power": "チャージャー"
|
||||
},
|
||||
"pialert": {
|
||||
"total": "Total",
|
||||
|
@ -178,7 +178,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "요청",
|
||||
"queued": "대기 중",
|
||||
"albums": "앨범"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "요청",
|
||||
|
@ -169,7 +169,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albumi"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -33,8 +33,8 @@
|
||||
},
|
||||
"lidarr": {
|
||||
"queued": "Dibaris Gilir",
|
||||
"albums": "Album",
|
||||
"wanted": "Mahu"
|
||||
"wanted": "Mahu",
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Mahu",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Gezocht",
|
||||
"queued": "In de wachtrij",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
|
@ -125,7 +125,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Poszukiwane",
|
||||
"queued": "W kolejce",
|
||||
"albums": "Albumy"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Poszukiwane",
|
||||
|
@ -127,7 +127,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Desejado",
|
||||
"queued": "Na fila",
|
||||
"albums": "Álbuns"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Desejado",
|
||||
|
@ -190,7 +190,7 @@
|
||||
"lidarr": {
|
||||
"queued": "Enfileirado",
|
||||
"wanted": "Desejado",
|
||||
"albums": "Álbuns"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Consultas",
|
||||
@ -590,12 +590,12 @@
|
||||
"switches_on": "Interruptores Ligados"
|
||||
},
|
||||
"freshrss": {
|
||||
"subscriptions": "Subscriptions",
|
||||
"unread": "Unread"
|
||||
"subscriptions": "Assinaturas",
|
||||
"unread": "Não lida"
|
||||
},
|
||||
"channelsdvrserver": {
|
||||
"shows": "Shows",
|
||||
"recordings": "Recordings",
|
||||
"recordings": "Gravações",
|
||||
"scheduled": "Scheduled",
|
||||
"passes": "Passes"
|
||||
},
|
||||
@ -637,16 +637,16 @@
|
||||
},
|
||||
"caddy": {
|
||||
"upstreams": "Upstreams",
|
||||
"requests": "Current requests",
|
||||
"requests_failed": "Failed requests"
|
||||
"requests": "Solicitações atuais",
|
||||
"requests_failed": "Solicitações com falha"
|
||||
},
|
||||
"evcc": {
|
||||
"pv_power": "Production",
|
||||
"battery_soc": "Battery",
|
||||
"grid_power": "Grid",
|
||||
"home_power": "Consumption",
|
||||
"charge_power": "Charger",
|
||||
"watt_hour": "Wh"
|
||||
"pv_power": "Produção",
|
||||
"battery_soc": "Bateria",
|
||||
"grid_power": "Grade",
|
||||
"home_power": "Consumo",
|
||||
"charge_power": "Carregador",
|
||||
"watt_hour": "Kw"
|
||||
},
|
||||
"pialert": {
|
||||
"total": "Total",
|
||||
|
@ -149,7 +149,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Dorite",
|
||||
"queued": "În coadă",
|
||||
"albums": "Albume"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Dorite",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Хотел",
|
||||
"queued": "В очереди",
|
||||
"albums": "Альбомы"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Запросы",
|
||||
|
@ -288,7 +288,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -250,7 +250,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Iskano",
|
||||
"queued": "V vrsti",
|
||||
"albums": "Albumi"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Iskano",
|
||||
|
@ -132,7 +132,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
|
@ -103,7 +103,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Eftersöker",
|
||||
"queued": "I kö",
|
||||
"albums": "Album"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Eftersökt",
|
||||
|
@ -126,7 +126,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "కావలెను",
|
||||
"queued": "క్యూయూఎడ్",
|
||||
"albums": "ఆల్బములు"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"bazarr": {
|
||||
"missingEpisodes": "ఎపిసోడ్లు లేవు",
|
||||
|
@ -225,7 +225,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"ombi": {
|
||||
"pending": "Pending",
|
||||
|
@ -132,7 +132,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Aranan",
|
||||
"queued": "Kuyrukta",
|
||||
"albums": "Albümler"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Aranan",
|
||||
|
@ -233,21 +233,21 @@
|
||||
"wanted": "Розшукується",
|
||||
"queued": "У черзі",
|
||||
"series": "Серії",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Черга",
|
||||
"unknown": "Невідомо"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Розшукується",
|
||||
"missing": "Відсутній",
|
||||
"queued": "У черзі",
|
||||
"movies": "Фільми",
|
||||
"queue": "Queue",
|
||||
"unknown": "Unknown"
|
||||
"queue": "Черга",
|
||||
"unknown": "Невідомо"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Розшукується",
|
||||
"queued": "У черзі",
|
||||
"albums": "Альбоми"
|
||||
"artists": "Виконавці"
|
||||
},
|
||||
"traefik": {
|
||||
"middleware": "Проміжне програмне забезпечення",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
|
@ -109,7 +109,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "想睇",
|
||||
"queued": "排緊隊",
|
||||
"albums": "專輯"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "想睇",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "订阅",
|
||||
"queued": "队列",
|
||||
"albums": "相册"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "查询",
|
||||
|
@ -177,7 +177,7 @@
|
||||
"lidarr": {
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"albums": "專輯"
|
||||
"artists": "Artists"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "查詢",
|
||||
|
@ -3,7 +3,7 @@ import classNames from "classnames";
|
||||
import List from "components/services/list";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
export default function ServicesGroup({ services, layout, fiveColumns }) {
|
||||
export default function ServicesGroup({ group, services, layout, fiveColumns }) {
|
||||
return (
|
||||
<div
|
||||
key={services.name}
|
||||
@ -21,7 +21,7 @@ export default function ServicesGroup({ services, layout, fiveColumns }) {
|
||||
}
|
||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
|
||||
</div>
|
||||
<List services={services.services} layout={layout} />
|
||||
<List group={group} services={services.services} layout={layout} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import Kubernetes from "widgets/kubernetes/component";
|
||||
import { SettingsContext } from "utils/contexts/settings";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
export default function Item({ service }) {
|
||||
export default function Item({ service, group }) {
|
||||
const hasLink = service.href && service.href !== "#";
|
||||
const { settings } = useContext(SettingsContext);
|
||||
const showStats = (service.showStats === false) ? false : settings.showStats;
|
||||
@ -77,7 +77,7 @@ export default function Item({ service }) {
|
||||
<div className="absolute top-0 right-0 w-1/2 flex flex-row justify-end gap-2 mr-2">
|
||||
{service.ping && (
|
||||
<div className="flex-shrink-0 flex items-center justify-center cursor-pointer">
|
||||
<Ping service={service} />
|
||||
<Ping group={group} service={service.name} />
|
||||
<span className="sr-only">Ping status</span>
|
||||
</div>
|
||||
)}
|
||||
|
@ -14,7 +14,7 @@ const columnMap = [
|
||||
"grid-cols-1 md:grid-cols-2 lg:grid-cols-8",
|
||||
];
|
||||
|
||||
export default function List({ services, layout }) {
|
||||
export default function List({ group, services, layout }) {
|
||||
return (
|
||||
<ul
|
||||
className={classNames(
|
||||
@ -23,7 +23,7 @@ export default function List({ services, layout }) {
|
||||
)}
|
||||
>
|
||||
{services.map((service) => (
|
||||
<Item key={service.container ?? service.app ?? service.name} service={service} />
|
||||
<Item key={service.container ?? service.app ?? service.name} service={service} group={group} />
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import useSWR from "swr";
|
||||
|
||||
export default function Ping({ service }) {
|
||||
export default function Ping({ group, service }) {
|
||||
const { t } = useTranslation();
|
||||
const { data, error } = useSWR(`/api/ping?${new URLSearchParams({ping: service.ping}).toString()}`, {
|
||||
const { data, error } = useSWR(`/api/ping?${new URLSearchParams({ group, service }).toString()}`, {
|
||||
refreshInterval: 30000
|
||||
});
|
||||
|
||||
@ -23,7 +23,7 @@ export default function Ping({ service }) {
|
||||
);
|
||||
}
|
||||
|
||||
const statusText = `${service.ping}: HTTP status ${data.status}`;
|
||||
const statusText = `${service}: HTTP status ${data.status}`;
|
||||
|
||||
if (data.status > 403) {
|
||||
return (
|
||||
|
@ -9,10 +9,12 @@ function displayData(data) {
|
||||
return (data.type === 'Buffer') ? Buffer.from(data).toString() : JSON.stringify(data, 4);
|
||||
}
|
||||
|
||||
export default function Error({ error: err }) {
|
||||
export default function Error({ error }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { error } = err?.data ?? { error: err };
|
||||
if (error?.data?.error) {
|
||||
error = error.data.error; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
return (
|
||||
<details className="px-1 pb-1">
|
||||
|
@ -1,12 +1,22 @@
|
||||
import { performance } from "perf_hooks";
|
||||
|
||||
import { getServiceItem } from "utils/config/service-helpers";
|
||||
import createLogger from "utils/logger";
|
||||
import { httpProxy } from "utils/proxy/http";
|
||||
|
||||
const logger = createLogger("ping");
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const { ping: pingURL } = req.query;
|
||||
const { group, service } = req.query;
|
||||
const serviceItem = await getServiceItem(group, service);
|
||||
if (!serviceItem) {
|
||||
logger.debug(`No service item found for group ${group} named ${service}`);
|
||||
return res.status(400).send({
|
||||
error: "Unable to find service, see log for details.",
|
||||
});
|
||||
}
|
||||
|
||||
const { ping: pingURL } = serviceItem;
|
||||
|
||||
if (!pingURL) {
|
||||
logger.debug("No ping URL specified");
|
||||
|
@ -252,7 +252,7 @@ function Home({ initialSettings }) {
|
||||
/>
|
||||
<meta name="theme-color" content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]} />
|
||||
</Head>
|
||||
<div className="relative container m-auto flex flex-col justify-between z-10 h-full">
|
||||
<div className="relative container m-auto flex flex-col justify-start z-10 h-full">
|
||||
<div
|
||||
className={classNames(
|
||||
"flex flex-row flex-wrap justify-between",
|
||||
@ -289,7 +289,7 @@ function Home({ initialSettings }) {
|
||||
{services?.length > 0 && (
|
||||
<div className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
|
||||
{services.map((group) => (
|
||||
<ServicesGroup key={group.name} services={group} layout={initialSettings.layout?.[group.name]} fiveColumns={settings.fiveColumns} />
|
||||
<ServicesGroup key={group.name} group={group.name} services={group} layout={initialSettings.layout?.[group.name]} fiveColumns={settings.fiveColumns} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
@ -302,14 +302,16 @@ function Home({ initialSettings }) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex p-8 pb-0 w-full justify-end">
|
||||
{!initialSettings?.color && <ColorToggle />}
|
||||
<Revalidate />
|
||||
{!initialSettings?.theme && <ThemeToggle />}
|
||||
</div>
|
||||
<div className="flex flex-col mt-auto p-8 w-full">
|
||||
<div className="flex w-full justify-end">
|
||||
{!initialSettings?.color && <ColorToggle />}
|
||||
<Revalidate />
|
||||
{!initialSettings?.theme && <ThemeToggle />}
|
||||
</div>
|
||||
|
||||
<div className="flex p-8 pt-4 w-full justify-end">
|
||||
{!initialSettings?.hideVersion && <Version />}
|
||||
<div className="flex mt-4 w-full justify-end">
|
||||
{!initialSettings?.hideVersion && <Version />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
@ -328,16 +328,13 @@ export function cleanServiceGroups(groups) {
|
||||
}));
|
||||
}
|
||||
|
||||
export default async function getServiceWidget(group, service) {
|
||||
export async function getServiceItem(group, service) {
|
||||
const configuredServices = await servicesFromConfig();
|
||||
|
||||
const serviceGroup = configuredServices.find((g) => g.name === group);
|
||||
if (serviceGroup) {
|
||||
const serviceEntry = serviceGroup.services.find((s) => s.name === service);
|
||||
if (serviceEntry) {
|
||||
const { widget } = serviceEntry;
|
||||
return widget;
|
||||
}
|
||||
if (serviceEntry) return serviceEntry;
|
||||
}
|
||||
|
||||
const discoveredServices = await servicesFromDocker();
|
||||
@ -345,20 +342,24 @@ export default async function getServiceWidget(group, service) {
|
||||
const dockerServiceGroup = discoveredServices.find((g) => g.name === group);
|
||||
if (dockerServiceGroup) {
|
||||
const dockerServiceEntry = dockerServiceGroup.services.find((s) => s.name === service);
|
||||
if (dockerServiceEntry) {
|
||||
const { widget } = dockerServiceEntry;
|
||||
return widget;
|
||||
}
|
||||
if (dockerServiceEntry) return dockerServiceEntry;
|
||||
}
|
||||
|
||||
const kubernetesServices = await servicesFromKubernetes();
|
||||
const kubernetesServiceGroup = kubernetesServices.find((g) => g.name === group);
|
||||
if (kubernetesServiceGroup) {
|
||||
const kubernetesServiceEntry = kubernetesServiceGroup.services.find((s) => s.name === service);
|
||||
if (kubernetesServiceEntry) {
|
||||
const { widget } = kubernetesServiceEntry;
|
||||
return widget;
|
||||
}
|
||||
if (kubernetesServiceEntry) return kubernetesServiceEntry;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export default async function getServiceWidget(group, service) {
|
||||
const serviceItem = await getServiceItem(group, service);
|
||||
if (serviceItem) {
|
||||
const { widget } = serviceItem;
|
||||
return widget;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -16,7 +16,7 @@ export default function Component({ service }) {
|
||||
`/api/kubernetes/stats/${widget.namespace}/${widget.app}?${podSelectorString}`);
|
||||
|
||||
if (statsError || statusError) {
|
||||
return <Container service={service} error={t("widget.api_error")} />;
|
||||
return <Container service={service} error={statsError ?? statusError} />;
|
||||
}
|
||||
|
||||
if (statusData && statusData.status !== "running") {
|
||||
|
@ -9,23 +9,21 @@ export default function Component({ service }) {
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
// album API endpoint can get massive, so we prevent calling if not included in fields see https://github.com/benphelps/homepage/discussions/1577
|
||||
const showAlbums = widget.fields?.includes('albums') || !widget.fields;
|
||||
const { data: albumsData, error: albumsError } = useWidgetAPI(widget, showAlbums ? "album" : "");
|
||||
const { data: artistsData, error: artistsError } = useWidgetAPI(widget, "artist");
|
||||
const { data: wantedData, error: wantedError } = useWidgetAPI(widget, "wanted/missing");
|
||||
const { data: queueData, error: queueError } = useWidgetAPI(widget, "queue/status");
|
||||
|
||||
if (albumsError || wantedError || queueError) {
|
||||
const finalError = albumsError ?? wantedError ?? queueError;
|
||||
if (artistsError || wantedError || queueError) {
|
||||
const finalError = artistsError ?? wantedError ?? queueError;
|
||||
return <Container service={service} error={finalError} />;
|
||||
}
|
||||
|
||||
if ((showAlbums && !albumsData) || !wantedData || !queueData) {
|
||||
if (!artistsData || !wantedData || !queueData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="lidarr.wanted" />
|
||||
<Block label="lidarr.queued" />
|
||||
<Block label="lidarr.albums" />
|
||||
<Block label="lidarr.artists" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@ -34,7 +32,7 @@ export default function Component({ service }) {
|
||||
<Container service={service}>
|
||||
<Block label="lidarr.wanted" value={t("common.number", { value: wantedData.totalRecords })} />
|
||||
<Block label="lidarr.queued" value={t("common.number", { value: queueData.totalCount })} />
|
||||
{showAlbums && <Block label="lidarr.albums" value={t("common.number", { value: albumsData?.have })} />}
|
||||
<Block label="lidarr.artists" value={t("common.number", { value: artistsData.length })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
import { jsonArrayFilter } from "utils/proxy/api-helpers";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/v1/{endpoint}?apikey={key}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
album: {
|
||||
endpoint: "album",
|
||||
map: (data) => ({
|
||||
have: jsonArrayFilter(data, (item) => item?.statistics?.percentOfTracks === 100).length,
|
||||
}),
|
||||
artist: {
|
||||
endpoint: "artist",
|
||||
},
|
||||
"wanted/missing": {
|
||||
endpoint: "wanted/missing",
|
||||
|
@ -1,12 +1,8 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data: containersData, error: containersError } = useWidgetAPI(widget, "docker/containers/json", {
|
||||
@ -27,8 +23,9 @@ export default function Component({ service }) {
|
||||
);
|
||||
}
|
||||
|
||||
if (containersData.error) {
|
||||
return <Container service={service} error={t("widget.api_error")} />;
|
||||
if (containersData.error || containersData.message) {
|
||||
// containersData can be itself an error object e.g. if environment fails
|
||||
return <Container service={service} error={ containersData?.error ?? containersData } />;
|
||||
}
|
||||
|
||||
const running = containersData.filter((c) => c.State === "running").length;
|
||||
|
Loading…
x
Reference in New Issue
Block a user