diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 8f9fc1fb..a121a7e3 100755
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -38,7 +38,12 @@
"used": "Used",
"load": "Load",
"temp": "TEMP",
- "max": "Max"
+ "max": "Max",
+ "uptime": "UP",
+ "months": "mo",
+ "days": "d",
+ "hours": "h",
+ "minutes": "m"
},
"unifi": {
"users": "Users",
diff --git a/src/components/widgets/resources/resources.jsx b/src/components/widgets/resources/resources.jsx
index 2238d2cc..4ff0c81c 100644
--- a/src/components/widgets/resources/resources.jsx
+++ b/src/components/widgets/resources/resources.jsx
@@ -2,6 +2,7 @@ import Disk from "./disk";
import Cpu from "./cpu";
import Memory from "./memory";
import CpuTemp from "./cputemp";
+import Uptime from "./uptime";
export default function Resources({ options }) {
const { expanded, units } = options;
@@ -14,6 +15,7 @@ export default function Resources({ options }) {
? options.disk.map((disk) => )
: options.disk && }
{options.cputemp && }
+ {options.uptime && }
{options.label && (
{options.label}
diff --git a/src/components/widgets/resources/uptime.jsx b/src/components/widgets/resources/uptime.jsx
new file mode 100644
index 00000000..2624bef1
--- /dev/null
+++ b/src/components/widgets/resources/uptime.jsx
@@ -0,0 +1,61 @@
+import useSWR from "swr";
+import { FaRegClock } from "react-icons/fa";
+import { BiError } from "react-icons/bi";
+import { useTranslation } from "next-i18next";
+
+export default function Uptime() {
+ const { t } = useTranslation();
+
+ const { data, error } = useSWR(`/api/widgets/resources?type=uptime`, {
+ refreshInterval: 1500,
+ });
+
+ if (error || data?.error) {
+ return (
+
+
+
+ {t("widget.api_error")}
+
+
+ );
+ }
+
+ if (!data) {
+ return (
+
+
+
+
+ -
+ {t("resources.temp")}
+
+
+
+ );
+ }
+
+ const mo = Math.floor(data.uptime / (3600 * 24 * 31));
+ const d = Math.floor(data.uptime % (3600 * 24 * 31) / (3600 * 24));
+ const h = Math.floor(data.uptime % (3600 * 24) / 3600);
+ const m = Math.floor(data.uptime % 3600 / 60);
+
+ let uptime;
+ if (mo > 0) uptime = `${mo}${t("resources.months")} ${d}${t("resources.days")}`;
+ else if (d > 0) uptime = `${d}${t("resources.days")} ${h}${t("resources.hours")}`;
+ else uptime = `${h}${t("resources.hours")} ${m}${t("resources.minutes")}`;
+
+ return (
+
+
+
+
+
+ {uptime}
+
+ {t("resources.uptime")}
+
+
+
+ );
+}
diff --git a/src/pages/api/widgets/resources.js b/src/pages/api/widgets/resources.js
index 31257ff0..ae53bf14 100644
--- a/src/pages/api/widgets/resources.js
+++ b/src/pages/api/widgets/resources.js
@@ -41,6 +41,13 @@ export default async function handler(req, res) {
});
}
+ if (type === "uptime") {
+ const timeData = await si.time();
+ return res.status(200).json({
+ uptime: timeData.uptime
+ });
+ }
+
return res.status(400).json({
error: "invalid type",
});