diff --git a/public/locales/es/common.json b/public/locales/es/common.json index a680a695..827b6cc4 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -18,13 +18,13 @@ "load": "Carga", "cpu": "CPU", "mem": "MEM", - "temp": "TEMP", - "max": "Max", - "uptime": "UP", - "months": "mo", - "days": "d", - "hours": "h", - "minutes": "m" + "temp": "TEMPORAL", + "max": "Máximo", + "uptime": "ARRIBA", + "months": "Meses", + "days": "Días", + "hours": "Horas", + "minutes": "Minutos" }, "docker": { "rx": "Recibido", @@ -234,10 +234,10 @@ "cpu": "Procesador", "mem": "Memoria", "wait": "Espere por favor", - "temp": "TEMP", - "uptime": "UP", - "days": "d", - "hours": "h" + "temp": "TEMPORAL", + "uptime": "ARRIBA", + "days": "Días", + "hours": "Horas" }, "changedetectionio": { "totalObserved": "Total Observados", diff --git a/public/locales/ko/common.json b/public/locales/ko/common.json index 1293ce9c..ebafd10b 100644 --- a/public/locales/ko/common.json +++ b/public/locales/ko/common.json @@ -42,13 +42,13 @@ "free": "남음", "used": "사용", "load": "부하", - "temp": "TEMP", - "max": "Max", - "uptime": "UP", - "months": "mo", - "days": "d", - "hours": "h", - "minutes": "m" + "temp": "온도", + "max": "최대", + "uptime": "가동", + "months": "달", + "days": "일", + "hours": "시간", + "minutes": "분" }, "unifi": { "users": "사용자", diff --git a/public/locales/uk/common.json b/public/locales/uk/common.json index b3394925..0cdf4d7b 100644 --- a/public/locales/uk/common.json +++ b/public/locales/uk/common.json @@ -131,11 +131,11 @@ "mem": "Пам'ять", "temp": "TEMP", "max": "Max", - "uptime": "UP", - "months": "mo", - "days": "d", - "hours": "h", - "minutes": "m" + "uptime": "Відправка", + "months": "міс", + "days": "д", + "hours": "г", + "minutes": "хв" }, "unifi": { "users": "Користувачі", @@ -359,9 +359,9 @@ "mem": "Пам'ять", "wait": "Будь ласка, зачекайте", "temp": "TEMP", - "uptime": "UP", - "days": "d", - "hours": "h" + "uptime": "Відправка", + "days": "д", + "hours": "г" }, "quicklaunch": { "bookmark": "Закладка", diff --git a/public/locales/zh-CN/common.json b/public/locales/zh-CN/common.json index 1d646d6d..6d65f709 100644 --- a/public/locales/zh-CN/common.json +++ b/public/locales/zh-CN/common.json @@ -18,13 +18,13 @@ "load": "负载", "cpu": "处理器", "mem": "内存", - "temp": "TEMP", - "max": "Max", - "uptime": "UP", - "months": "mo", - "days": "d", - "hours": "h", - "minutes": "m" + "temp": "温度", + "max": "最大", + "uptime": "运行时间", + "months": "月", + "days": "天", + "hours": "时", + "minutes": "分" }, "docker": { "rx": "接收", @@ -236,8 +236,8 @@ "wait": "请稍等", "temp": "TEMP", "uptime": "UP", - "days": "d", - "hours": "h" + "days": "天", + "hours": "时" }, "changedetectionio": { "totalObserved": "观察到的总数", diff --git a/src/components/widgets/glances/glances.jsx b/src/components/widgets/glances/glances.jsx index b0acdaa0..a6f4dfa8 100644 --- a/src/components/widgets/glances/glances.jsx +++ b/src/components/widgets/glances/glances.jsx @@ -6,6 +6,12 @@ import { useTranslation } from "next-i18next"; import UsageBar from "../resources/usage-bar"; +const cpuSensorLabels = ["cpu_thermal", "Core"]; + +function convertToFahrenheit(t) { + return t * 9/5 + 32 +} + export default function Widget({ options }) { const { t, i18n } = useTranslation(); @@ -65,10 +71,22 @@ export default function Widget({ options }) { } const unit = options.units === "imperial" ? "fahrenheit" : "celsius"; - let mainTemp; - if (options.cputemp && data.sensors) { - mainTemp = unit === "celsius" ? data.sensors.find(s => s.label.includes("cpu_thermal")).value : data.sensors.find(s => s.label.includes("cpu_thermal")).value * 5/9 + 32; + let mainTemp = 0; + let maxTemp = 80; + const cpuSensors = data.sensors?.filter(s => cpuSensorLabels.some(label => s.label.startsWith(label)) && s.type === "temperature_core"); + if (options.cputemp && cpuSensors) { + try { + mainTemp = cpuSensors.reduce((acc, s) => acc + s.value, 0) / cpuSensors.length; + maxTemp = Math.max(cpuSensors.reduce((acc, s) => acc + s.warning, 0) / cpuSensors.length, maxTemp); + if (unit === "fahrenheit") { + mainTemp = convertToFahrenheit(mainTemp); + maxTemp = convertToFahrenheit(maxTemp); + } + } catch (e) { + // cpu sensor retrieval failed + } } + const tempPercent = Math.round((mainTemp / maxTemp) * 100); return (
@@ -107,7 +125,7 @@ export default function Widget({ options }) {
- {options.cputemp && mainTemp && + {options.cputemp && mainTemp > 0 && (
@@ -122,6 +140,7 @@ export default function Widget({ options }) {
{t("glances.temp")}
+
)} {options.uptime && data.uptime && @@ -134,6 +153,7 @@ export default function Widget({ options }) {
{t("glances.uptime")}
+ )} diff --git a/src/components/widgets/resources/cputemp.jsx b/src/components/widgets/resources/cputemp.jsx index d5cb6100..92c684e5 100644 --- a/src/components/widgets/resources/cputemp.jsx +++ b/src/components/widgets/resources/cputemp.jsx @@ -3,6 +3,12 @@ import { FaThermometerHalf } from "react-icons/fa"; import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import UsageBar from "./usage-bar"; + +function convertToFahrenheit(t) { + return t * 9/5 + 32 +} + export default function CpuTemp({ expanded, units }) { const { t } = useTranslation(); @@ -21,7 +27,7 @@ export default function CpuTemp({ expanded, units }) { ); } - if (!data) { + if (!data || !data.cputemp) { return (
@@ -41,9 +47,16 @@ export default function CpuTemp({ expanded, units }) { ); } + let minTemp = 0; + let mainTemp = data.cputemp.main; + if (data.cputemp.cores?.length) { + mainTemp = data.cputemp.cores.reduce((a, b) => a + b) / data.cputemp.cores.length; + minTemp = Math.min(...data.cputemp.cores); + } const unit = units === "imperial" ? "fahrenheit" : "celsius"; - const mainTemp = (unit === "celsius") ? data.cputemp.main : data.cputemp.main * 5/9 + 32; - const maxTemp = (unit === "celsius") ? data.cputemp.max : data.cputemp.max * 5/9 + 32; + mainTemp = (unit === "celsius") ? mainTemp : convertToFahrenheit(mainTemp); + const maxTemp = (unit === "celsius") ? data.cputemp.max : convertToFahrenheit(data.cputemp.max); + const percent = Math.round(((mainTemp - minTemp) / (maxTemp - minTemp)) * 100); return (
@@ -73,6 +86,7 @@ export default function CpuTemp({ expanded, units }) {
{t("resources.max")}
)} +
); diff --git a/src/components/widgets/resources/disk.jsx b/src/components/widgets/resources/disk.jsx index dbc41b1c..ca09c095 100644 --- a/src/components/widgets/resources/disk.jsx +++ b/src/components/widgets/resources/disk.jsx @@ -44,7 +44,8 @@ export default function Disk({ options, expanded }) { ); } - const percent = Math.round((data.drive.used / data.drive.size) * 100); + // data.drive.used not accurate? + const percent = Math.round(((data.drive.size - data.drive.available) / data.drive.size) * 100); return (
diff --git a/src/components/widgets/resources/memory.jsx b/src/components/widgets/resources/memory.jsx index 2ee0a15e..30b7c8eb 100644 --- a/src/components/widgets/resources/memory.jsx +++ b/src/components/widgets/resources/memory.jsx @@ -44,7 +44,7 @@ export default function Memory({ expanded }) { ); } - const percent = Math.round((data.memory.used / data.memory.total) * 100); + const percent = Math.round((data.memory.active / data.memory.total) * 100); return (
@@ -52,7 +52,7 @@ export default function Memory({ expanded }) {
- {t("common.bytes", { value: data.memory.free, maximumFractionDigits: 1, binary: true })} + {t("common.bytes", { value: data.memory.available, maximumFractionDigits: 1, binary: true })}
{t("resources.free")}
diff --git a/src/components/widgets/resources/uptime.jsx b/src/components/widgets/resources/uptime.jsx index 2624bef1..3bf785b1 100644 --- a/src/components/widgets/resources/uptime.jsx +++ b/src/components/widgets/resources/uptime.jsx @@ -3,6 +3,8 @@ import { FaRegClock } from "react-icons/fa"; import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import UsageBar from "./usage-bar"; + export default function Uptime() { const { t } = useTranslation(); @@ -45,6 +47,8 @@ export default function Uptime() { else if (d > 0) uptime = `${d}${t("resources.days")} ${h}${t("resources.hours")}`; else uptime = `${h}${t("resources.hours")} ${m}${t("resources.minutes")}`; + const percent = Math.round((new Date().getSeconds() / 60) * 100); + return (
@@ -55,6 +59,7 @@ export default function Uptime() {
{t("resources.uptime")}
+
); diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js index 0ca30f00..e27cd35c 100644 --- a/src/pages/api/docker/stats/[...service].js +++ b/src/pages/api/docker/stats/[...service].js @@ -30,7 +30,7 @@ export default async function handler(req, res) { }); } - const containerNames = containers.map((container) => container.Names[0].replace(/^\//, "")); + const containerNames = containers.map((container) => container.Names[0]?.replace(/^\//, "")); const containerExists = containerNames.includes(containerName); if (containerExists) { @@ -75,7 +75,7 @@ export default async function handler(req, res) { } } - return res.status(200).send({ + return res.status(404).send({ error: "not found", }); } catch (e) { diff --git a/src/pages/api/docker/status/[...service].js b/src/pages/api/docker/status/[...service].js index 2bcc0a8a..bb03a637 100644 --- a/src/pages/api/docker/status/[...service].js +++ b/src/pages/api/docker/status/[...service].js @@ -30,7 +30,7 @@ export default async function handler(req, res) { }); } - const containerNames = containers.map((container) => container.Names[0].replace(/^\//, "")); + const containerNames = containers.map((container) => container.Names[0]?.replace(/^\//, "")); const containerExists = containerNames.includes(containerName); if (containerExists) { diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index 317c0f3c..f739f05f 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -249,7 +249,8 @@ export function cleanServiceGroups(groups) { podSelector, wan, // opnsense widget, enableBlocks, // emby/jellyfin - enableNowPlaying + enableNowPlaying, + volume // diskstation widget } = cleanedService.widget; const fieldsList = typeof fields === 'string' ? JSON.parse(fields) : fields; @@ -281,8 +282,11 @@ export function cleanServiceGroups(groups) { if (wan) cleanedService.widget.wan = wan; } if (type === "emby" || type === "jellyfin") { - if (enableBlocks) cleanedService.widget.enableBlocks = enableBlocks === 'true'; - if (enableNowPlaying) cleanedService.widget.enableNowPlaying = enableNowPlaying === 'true'; + if (enableBlocks) cleanedService.widget.enableBlocks = enableBlocks; + if (enableNowPlaying) cleanedService.widget.enableNowPlaying = enableNowPlaying; + } + if (type === "diskstation") { + if (volume) cleanedService.widget.volume = volume; } } diff --git a/src/widgets/diskstation/component.jsx b/src/widgets/diskstation/component.jsx index 3195a62d..afc41ae4 100644 --- a/src/widgets/diskstation/component.jsx +++ b/src/widgets/diskstation/component.jsx @@ -33,8 +33,7 @@ export default function Component({ service }) { const uptime = `${ t("common.number", { value: days }) } ${ t("diskstation.days") }`; // storage info - // TODO: figure out how to display info for more than one volume - const volume = storageData.data.vol_info?.[0]; + const volume = widget.volume ? storageData.data.vol_info?.find(vol => vol.name === widget.volume) : storageData.data.vol_info?.[0]; const usedBytes = parseFloat(volume?.used_size); const totalBytes = parseFloat(volume?.total_size); const freeBytes = totalBytes - usedBytes;