diff --git a/src/components/widgets/datetime/datetime.jsx b/src/components/widgets/datetime/datetime.jsx
index 869834736..454d004dc 100644
--- a/src/components/widgets/datetime/datetime.jsx
+++ b/src/components/widgets/datetime/datetime.jsx
@@ -1,6 +1,9 @@
import { useState, useEffect } from "react";
import { useTranslation } from "next-i18next";
+import Container from "../widget/container";
+import Raw from "../widget/raw";
+
const textSizes = {
"4xl": "text-4xl",
"3xl": "text-3xl",
@@ -17,7 +20,7 @@ export default function DateTime({ options }) {
const { i18n } = useTranslation();
const [date, setDate] = useState("");
const dateLocale = locale ?? i18n.language;
-
+
useEffect(() => {
const dateFormat = new Intl.DateTimeFormat(dateLocale, { ...format });
const interval = setInterval(() => {
@@ -27,12 +30,14 @@ export default function DateTime({ options }) {
}, [date, setDate, dateLocale, format]);
return (
-
+
+
+
+
+ {date}
+
+
+
+
);
}
diff --git a/src/components/widgets/glances/glances.jsx b/src/components/widgets/glances/glances.jsx
index 85dd44c0c..b45dfefeb 100644
--- a/src/components/widgets/glances/glances.jsx
+++ b/src/components/widgets/glances/glances.jsx
@@ -1,11 +1,13 @@
import useSWR from "swr";
import { useContext } from "react";
-import { BiError } from "react-icons/bi";
import { FaMemory, FaRegClock, FaThermometerHalf } from "react-icons/fa";
import { FiCpu, FiHardDrive } from "react-icons/fi";
import { useTranslation } from "next-i18next";
-import UsageBar from "../resources/usage-bar";
+import Error from "../widget/error";
+import Resource from "../widget/resource";
+import Resources from "../widget/resources";
+import WidgetLabel from "../widget/widget_label";
import { SettingsContext } from "utils/contexts/settings";
@@ -26,52 +28,17 @@ export default function Widget({ options }) {
);
if (error || data?.error) {
- return (
-
-
-
-
-
- {t("widget.api_error")}
-
-
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
-
-
-
- {t("glances.wait")}
-
-
-
-
-
-
-
-
-
-
- {t("glances.wait")}
-
-
-
-
-
-
- {options.label && (
-
{options.label}
- )}
-
- );
+ return
+
+
+ { options.cputemp && }
+ { options.uptime && }
+ { options.label && }
+ ;
}
const unit = options.units === "imperial" ? "fahrenheit" : "celsius";
@@ -101,131 +68,84 @@ export default function Widget({ options }) {
}
return (
-
-
-
-
-
-
-
- {t("common.number", {
- value: data.cpu.total,
- style: "unit",
- unit: "percent",
- maximumFractionDigits: 0,
- })}
-
-
{t("glances.cpu")}
-
- {options.expanded && (
-
-
- {t("common.number", {
- value: data.load.min15,
- style: "unit",
- unit: "percent",
- maximumFractionDigits: 0,
- })}
-
- {t("glances.load")}
-
- )}
-
-
-
-
-
-
-
-
- {t("common.bytes", {
- value: data.mem.free,
- maximumFractionDigits: 1,
- binary: true,
- })}
-
-
{t("glances.free")}
-
- {options.expanded && (
-
-
- {t("common.bytes", {
- value: data.mem.total,
- maximumFractionDigits: 1,
- binary: true,
- })}
-
- {t("glances.total")}
-
- )}
-
-
-
- {disks.map((disk) => (
-
-
-
-
- {t("common.bytes", { value: disk.free })}
- {t("glances.free")}
-
- {options.expanded && (
-
- {t("common.bytes", { value: disk.size })}
- {t("glances.total")}
-
- )}
-
-
-
))}
- {options.cputemp && mainTemp > 0 &&
- (
-
-
-
-
- {t("common.number", {
- value: mainTemp,
- maximumFractionDigits: 1,
- style: "unit",
- unit
- })}
-
- {t("glances.temp")}
-
- {options.expanded && (
-
-
- {t("common.number", {
- value: maxTemp,
- maximumFractionDigits: 1,
- style: "unit",
- unit
- })}
-
- {t("glances.warn")}
-
- )}
-
-
-
)}
- {options.uptime && data.uptime &&
- (
-
-
-
-
- {data.uptime.replace(" days,", t("glances.days")).replace(/:\d\d:\d\d$/g, t("glances.hours"))}
-
- {t("glances.uptime")}
-
-
-
-
)}
-
- {options.label && (
- {options.label}
- )}
-
+
+
+
+ {disks.map((disk) => (
+
+ ))}
+ {options.cputemp && mainTemp > 0 &&
+
+ }
+ {options.uptime && data.uptime &&
+
+ }
+ {options.label && }
+
);
}
diff --git a/src/components/widgets/greeting/greeting.jsx b/src/components/widgets/greeting/greeting.jsx
index da0f063d1..11de571c8 100644
--- a/src/components/widgets/greeting/greeting.jsx
+++ b/src/components/widgets/greeting/greeting.jsx
@@ -1,3 +1,6 @@
+import Container from "../widget/container";
+import Raw from "../widget/raw";
+
const textSizes = {
"4xl": "text-4xl",
"3xl": "text-3xl",
@@ -11,12 +14,12 @@ const textSizes = {
export default function Greeting({ options }) {
if (options.text) {
- return (
-
+ return
+
{options.text}
-
- );
+
+ ;
}
}
diff --git a/src/components/widgets/kubernetes/kubernetes.jsx b/src/components/widgets/kubernetes/kubernetes.jsx
index 78c4caaf9..2d1f55e4b 100644
--- a/src/components/widgets/kubernetes/kubernetes.jsx
+++ b/src/components/widgets/kubernetes/kubernetes.jsx
@@ -1,12 +1,15 @@
import useSWR from "swr";
-import { BiError } from "react-icons/bi";
import { useTranslation } from "next-i18next";
+import Error from "../widget/error";
+import Container from "../widget/container";
+import Raw from "../widget/raw";
+
import Node from "./node";
export default function Widget({ options }) {
const { cluster, nodes } = options;
- const { t, i18n } = useTranslation();
+ const { i18n } = useTranslation();
const defaultData = {
cpu: {
@@ -18,7 +21,7 @@ export default function Widget({ options }) {
used: 0,
total: 0,
free: 0,
- precent: 0
+ percent: 0
}
};
@@ -29,23 +32,12 @@ export default function Widget({ options }) {
);
if (error || data?.error) {
- return (
-
-
-
-
-
- {t("widget.api_error")}
-
-
-
-
- );
+ return
}
if (!data) {
- return (
-
+ return
+
{cluster.show &&
@@ -54,12 +46,12 @@ export default function Widget({ options }) {
}
-
- );
+
+ ;
}
- return (
-
+ return
+
{cluster.show &&
@@ -69,6 +61,6 @@ export default function Widget({ options }) {
)
}
-
- );
+
+ ;
}
diff --git a/src/components/widgets/kubernetes/node.jsx b/src/components/widgets/kubernetes/node.jsx
index 7a7c322d4..cc864be68 100644
--- a/src/components/widgets/kubernetes/node.jsx
+++ b/src/components/widgets/kubernetes/node.jsx
@@ -3,8 +3,7 @@ import { FiAlertTriangle, FiCpu, FiServer } from "react-icons/fi";
import { SiKubernetes } from "react-icons/si";
import { useTranslation } from "next-i18next";
-import UsageBar from "./usage-bar";
-
+import UsageBar from "../resources/usage-bar";
export default function Node({ type, options, data }) {
const { t } = useTranslation();
@@ -29,7 +28,7 @@ export default function Node({ type, options, data }) {
{t("common.number", {
- value: data.cpu.percent,
+ value: data?.cpu?.percent ?? 0,
style: "unit",
unit: "percent",
maximumFractionDigits: 0
@@ -37,18 +36,18 @@ export default function Node({ type, options, data }) {
-
+
{t("common.bytes", {
- value: data.memory.free,
+ value: data?.memory?.free ?? 0,
maximumFractionDigits: 0,
binary: true
})}
-
+
{options.showLabel && (
{type === "cluster" ? options.label : data.name}
)}
diff --git a/src/components/widgets/kubernetes/usage-bar.jsx b/src/components/widgets/kubernetes/usage-bar.jsx
deleted file mode 100644
index c817db4c4..000000000
--- a/src/components/widgets/kubernetes/usage-bar.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-export default function UsageBar({ percent }) {
- return (
-
- );
-}
diff --git a/src/components/widgets/logo/logo.jsx b/src/components/widgets/logo/logo.jsx
index 96e8569fc..3a4a25651 100644
--- a/src/components/widgets/logo/logo.jsx
+++ b/src/components/widgets/logo/logo.jsx
@@ -1,9 +1,13 @@
+import Container from "../widget/container";
+import Raw from "../widget/raw";
+
import ResolvedIcon from "components/resolvedicon"
export default function Logo({ options }) {
return (
-
- {options.icon ?
+
+
+ {options.icon ?
:
// fallback to homepage logo
}
-
+
+
)
}
diff --git a/src/components/widgets/longhorn/longhorn.jsx b/src/components/widgets/longhorn/longhorn.jsx
index 9fcb21b4a..c0169ceb9 100644
--- a/src/components/widgets/longhorn/longhorn.jsx
+++ b/src/components/widgets/longhorn/longhorn.jsx
@@ -1,37 +1,31 @@
import useSWR from "swr";
-import { BiError } from "react-icons/bi";
-import { useTranslation } from "next-i18next";
+
+import Error from "../widget/error";
+import Container from "../widget/container";
+import Raw from "../widget/raw";
import Node from "./node";
export default function Longhorn({ options }) {
const { expanded, total, labels, include, nodes } = options;
- const { t } = useTranslation();
const { data, error } = useSWR(`/api/widgets/longhorn`, {
refreshInterval: 1500
});
if (error || data?.error) {
- return (
-
-
-
- {t("widget.api_error")}
-
-
- );
+ return
}
if (!data) {
- return (
-
- );
+
+ ;
}
- return (
-
+ return
+
{data.nodes
.filter((node) => {
@@ -52,6 +46,6 @@ export default function Longhorn({ options }) {
)}
-
- );
+
+ ;
}
diff --git a/src/components/widgets/longhorn/node.jsx b/src/components/widgets/longhorn/node.jsx
index e0ee69afb..5235698a4 100644
--- a/src/components/widgets/longhorn/node.jsx
+++ b/src/components/widgets/longhorn/node.jsx
@@ -1,32 +1,20 @@
-import { FiHardDrive } from "react-icons/fi";
import { useTranslation } from "next-i18next";
+import { FaThermometerHalf } from "react-icons/fa";
-import UsageBar from "../resources/usage-bar";
+import Resource from "../widget/resource";
+import WidgetLabel from "../widget/widget_label";
export default function Node({ data, expanded, labels }) {
const { t } = useTranslation();
- return (
- <>
-
-
-
-
- {t("common.bytes", { value: data.node.available })}
- {t("resources.free")}
-
- {expanded && (
-
- {t("common.bytes", { value: data.node.maximum })}
- {t("resources.total")}
-
- )}
-
-
-
- {labels && (
- {data.node.id}
- )}
- >
- );
+ return { labels && }
+
}
diff --git a/src/components/widgets/openmeteo/openmeteo.jsx b/src/components/widgets/openmeteo/openmeteo.jsx
index 0d29aef53..040a3b6b1 100644
--- a/src/components/widgets/openmeteo/openmeteo.jsx
+++ b/src/components/widgets/openmeteo/openmeteo.jsx
@@ -1,10 +1,16 @@
import useSWR from "swr";
import { useState } from "react";
-import { BiError } from "react-icons/bi";
import { WiCloudDown } from "react-icons/wi";
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
import { useTranslation } from "next-i18next";
+import Error from "../widget/error";
+import Container from "../widget/container";
+import ContainerButton from "../widget/container_button";
+import WidgetIcon from "../widget/widget_icon";
+import PrimaryText from "../widget/primary_text";
+import SecondaryText from "../widget/secondary_text";
+
import Icon from "./icon";
function Widget({ options }) {
@@ -15,60 +21,35 @@ function Widget({ options }) {
);
if (error || data?.error) {
- return (
-
-
-
-
-
- {t("widget.api_error")}
- -
-
-
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
-
-
- {t("weather.updating")}
- {t("weather.wait")}
-
-
-
- );
+ return
+ {t("weather.updating")}
+ {t("weather.wait")}
+
+ ;
}
const unit = options.units === "metric" ? "celsius" : "fahrenheit";
- const timeOfDay = data.current_weather.time > data.daily.sunrise[0] && data.current_weather.time < data.daily.sunset[0] ? "day" : "night";
+ const weatherInfo = {
+ condition: data.current_weather.weathercode,
+ timeOfDay: data.current_weather.time > data.daily.sunrise[0] && data.current_weather.time < data.daily.sunset[0] ? "day" : "night"
+ };
- return (
-
-
-
-
-
-
-
- {options.label && `${options.label}, `}
- {t("common.number", {
- value: data.current_weather.temperature,
- style: "unit",
- unit,
- })}
-
- {t(`wmo.${data.current_weather.weathercode}-${timeOfDay}`)}
-
-
-
- );
+ return
+
+ {options.label && `${options.label}, `}
+ {t("common.number", {
+ value: data.current_weather.temperature,
+ style: "unit",
+ unit,
+ })}
+
+ {t(`wmo.${data.current_weather.weathercode}-${weatherInfo.timeOfDay}`)}
+
+ ;
}
export default function OpenMeteo({ options }) {
@@ -103,27 +84,11 @@ export default function OpenMeteo({ options }) {
// if (!requesting && !location) requestLocation();
if (!location) {
- return (
-
- );
+ return
+ {t("weather.current")}
+ {t("weather.allow")}
+
+ ;
}
return ;
diff --git a/src/components/widgets/openweathermap/weather.jsx b/src/components/widgets/openweathermap/weather.jsx
index 49f428a04..305315139 100644
--- a/src/components/widgets/openweathermap/weather.jsx
+++ b/src/components/widgets/openweathermap/weather.jsx
@@ -1,12 +1,19 @@
import useSWR from "swr";
import { useState } from "react";
-import { BiError } from "react-icons/bi";
import { WiCloudDown } from "react-icons/wi";
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
import { useTranslation } from "next-i18next";
+import Error from "../widget/error";
+import Container from "../widget/container";
+import ContainerButton from "../widget/container_button";
+import PrimaryText from "../widget/primary_text";
+import SecondaryText from "../widget/secondary_text";
+import WidgetIcon from "../widget/widget_icon";
+
import Icon from "./icon";
+
function Widget({ options }) {
const { t, i18n } = useTranslation();
@@ -15,58 +22,30 @@ function Widget({ options }) {
);
if (error || data?.cod === 401 || data?.error) {
- return (
-
-
-
-
-
- {t("widget.api_error")}
- -
-
-
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
-
-
- {t("weather.updating")}
- {t("weather.wait")}
-
-
-
- );
+ return
+ {t("weather.updating")}
+ {t("weather.wait")}
+
+ ;
}
const unit = options.units === "metric" ? "celsius" : "fahrenheit";
- return (
-
-
-
- data.sys.sunrise && data.dt < data.sys.sunset ? "day" : "night"}
- />
-
-
-
- {options.label && `${options.label}, `}
- {t("common.number", { value: data.main.temp, style: "unit", unit })}
-
- {data.weather[0].description}
-
-
-
- );
+ const weatherInfo = {
+ condition: data.weather[0].id,
+ timeOfDay: data.dt > data.sys.sunrise && data.dt < data.sys.sunset ? "day" : "night"
+ };
+
+ return
+ {options.label && `${options.label}, `}
+ {t("common.number", { value: data.main.temp, style: "unit", unit })}
+ {data.weather[0].description}
+
+ ;
}
export default function OpenWeatherMap({ options }) {
@@ -98,30 +77,12 @@ export default function OpenWeatherMap({ options }) {
}
};
- // if (!requesting && !location) requestLocation();
-
if (!location) {
- return (
-
- );
+ return
+ {t("weather.current")}
+ {t("weather.allow")}
+
+ ;
}
return ;
diff --git a/src/components/widgets/resources/cpu.jsx b/src/components/widgets/resources/cpu.jsx
index 7069e3c4a..12972fe89 100644
--- a/src/components/widgets/resources/cpu.jsx
+++ b/src/components/widgets/resources/cpu.jsx
@@ -1,9 +1,9 @@
import useSWR from "swr";
import { FiCpu } from "react-icons/fi";
-import { BiError } from "react-icons/bi";
import { useTranslation } from "next-i18next";
-import UsageBar from "./usage-bar";
+import Resource from "../widget/resource";
+import Error from "../widget/error";
export default function Cpu({ expanded }) {
const { t } = useTranslation();
@@ -13,67 +13,29 @@ export default function Cpu({ expanded }) {
});
if (error || data?.error) {
- return (
-
-
-
- {t("widget.api_error")}
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
-
-
-
{t("resources.cpu")}
-
- {expanded && (
-
-
-
-
{t("resources.load")}
-
- )}
-
-
-
- );
+ return
}
- const percent = data.cpu.usage;
-
- return (
-
-
-
-
-
- {t("common.number", {
- value: data.cpu.usage,
- style: "unit",
- unit: "percent",
- maximumFractionDigits: 0,
- })}
-
-
{t("resources.cpu")}
-
- {expanded && (
-
-
- {t("common.number", {
- value: data.cpu.load,
- maximumFractionDigits: 2,
- })}
-
-
{t("resources.load")}
-
- )}
-
-
-
- );
+ return
}
diff --git a/src/components/widgets/resources/cputemp.jsx b/src/components/widgets/resources/cputemp.jsx
index 571e6c8a7..ba6d9b730 100644
--- a/src/components/widgets/resources/cputemp.jsx
+++ b/src/components/widgets/resources/cputemp.jsx
@@ -1,9 +1,9 @@
import useSWR from "swr";
import { FaThermometerHalf } from "react-icons/fa";
-import { BiError } from "react-icons/bi";
import { useTranslation } from "next-i18next";
-import UsageBar from "./usage-bar";
+import Resource from "../widget/resource";
+import Error from "../widget/error";
function convertToFahrenheit(t) {
return t * 9/5 + 32
@@ -17,34 +17,18 @@ export default function CpuTemp({ expanded, units }) {
});
if (error || data?.error) {
- return (
-
-
-
- {t("widget.api_error")}
-
-
- );
+ return
}
if (!data || !data.cputemp) {
- return (
-
-
-
-
- -
- {t("resources.temp")}
-
- {expanded && (
-
- -
- {t("resources.max")}
-
- )}
-
-
- );
+ return ;
}
let mainTemp = data.cputemp.main;
@@ -54,38 +38,24 @@ export default function CpuTemp({ expanded, units }) {
const unit = units === "imperial" ? "fahrenheit" : "celsius";
mainTemp = (unit === "celsius") ? mainTemp : convertToFahrenheit(mainTemp);
const maxTemp = (unit === "celsius") ? data.cputemp.max : convertToFahrenheit(data.cputemp.max);
- const percent = Math.round((mainTemp / maxTemp) * 100);
- return (
-
-
-
-
-
- {t("common.number", {
- value: mainTemp,
- maximumFractionDigits: 1,
- style: "unit",
- unit
- })}
-
- {t("resources.temp")}
-
- {expanded && (
-
-
- {t("common.number", {
- value: maxTemp,
- maximumFractionDigits: 1,
- style: "unit",
- unit
- })}
-
- {t("resources.max")}
-
- )}
-
-
-
- );
+ return ;
}
diff --git a/src/components/widgets/resources/disk.jsx b/src/components/widgets/resources/disk.jsx
index ca09c0958..ab56624d9 100644
--- a/src/components/widgets/resources/disk.jsx
+++ b/src/components/widgets/resources/disk.jsx
@@ -1,9 +1,9 @@
import useSWR from "swr";
import { FiHardDrive } from "react-icons/fi";
-import { BiError } from "react-icons/bi";
import { useTranslation } from "next-i18next";
-import UsageBar from "./usage-bar";
+import Resource from "../widget/resource";
+import Error from "../widget/error";
export default function Disk({ options, expanded }) {
const { t } = useTranslation();
@@ -13,56 +13,31 @@ export default function Disk({ options, expanded }) {
});
if (error || data?.error) {
- return (
-
-
-
- {t("widget.api_error")}
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
- -
- {t("resources.free")}
-
- {expanded && (
-
- -
- {t("resources.total")}
-
- )}
-
-
-
- );
+ return ;
}
// data.drive.used not accurate?
const percent = Math.round(((data.drive.size - data.drive.available) / data.drive.size) * 100);
- return (
-
-
-
-
- {t("common.bytes", { value: data.drive.available })}
- {t("resources.free")}
-
- {expanded && (
-
- {t("common.bytes", { value: data.drive.size })}
- {t("resources.total")}
-
- )}
-
-
-
- );
+ return ;
}
diff --git a/src/components/widgets/resources/memory.jsx b/src/components/widgets/resources/memory.jsx
index 30b7c8eb8..19ae86879 100644
--- a/src/components/widgets/resources/memory.jsx
+++ b/src/components/widgets/resources/memory.jsx
@@ -1,9 +1,9 @@
import useSWR from "swr";
import { FaMemory } from "react-icons/fa";
-import { BiError } from "react-icons/bi";
import { useTranslation } from "next-i18next";
-import UsageBar from "./usage-bar";
+import Resource from "../widget/resource";
+import Error from "../widget/error";
export default function Memory({ expanded }) {
const { t } = useTranslation();
@@ -13,63 +13,30 @@ export default function Memory({ expanded }) {
});
if (error || data?.error) {
- return (
-
-
-
- {t("widget.api_error")}
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
- -
- {t("resources.free")}
-
- {expanded && (
-
- -
- {t("resources.total")}
-
- )}
-
-
-
- );
+ return ;
}
const percent = Math.round((data.memory.active / data.memory.total) * 100);
- return (
-
-
-
-
-
- {t("common.bytes", { value: data.memory.available, maximumFractionDigits: 1, binary: true })}
-
- {t("resources.free")}
-
- {expanded && (
-
-
- {t("common.bytes", {
- value: data.memory.total,
- maximumFractionDigits: 1,
- binary: true,
- })}
-
- {t("resources.total")}
-
- )}
-
-
-
- );
+ return ;
}
diff --git a/src/components/widgets/resources/resources.jsx b/src/components/widgets/resources/resources.jsx
index 4ff0c81cd..0cc2c3013 100644
--- a/src/components/widgets/resources/resources.jsx
+++ b/src/components/widgets/resources/resources.jsx
@@ -1,3 +1,6 @@
+import Container from "../widget/container";
+import Raw from "../widget/raw";
+
import Disk from "./disk";
import Cpu from "./cpu";
import Memory from "./memory";
@@ -6,8 +9,8 @@ import Uptime from "./uptime";
export default function Resources({ options }) {
const { expanded, units } = options;
- return (
-
+ return
+
{options.cpu &&
}
{options.memory &&
}
@@ -20,6 +23,6 @@ export default function Resources({ options }) {
{options.label && (
{options.label}
)}
-
- );
+
+ ;
}
diff --git a/src/components/widgets/resources/uptime.jsx b/src/components/widgets/resources/uptime.jsx
index 3bf785b1e..3984975f1 100644
--- a/src/components/widgets/resources/uptime.jsx
+++ b/src/components/widgets/resources/uptime.jsx
@@ -1,9 +1,9 @@
import useSWR from "swr";
import { FaRegClock } from "react-icons/fa";
-import { BiError } from "react-icons/bi";
import { useTranslation } from "next-i18next";
-import UsageBar from "./usage-bar";
+import Resource from "../widget/resource";
+import Error from "../widget/error";
export default function Uptime() {
const { t } = useTranslation();
@@ -13,54 +13,24 @@ export default function Uptime() {
});
if (error || data?.error) {
- return (
-
-
-
- {t("widget.api_error")}
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
- -
- {t("resources.temp")}
-
-
-
- );
+ return
;
}
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")}`;
- const percent = Math.round((new Date().getSeconds() / 60) * 100);
+ const percent = Math.round((new Date().getSeconds() / 60) * 100).toString();
- return (
-
-
-
-
-
- {uptime}
-
- {t("resources.uptime")}
-
-
-
-
- );
+ return
;
}
diff --git a/src/components/widgets/search/search.jsx b/src/components/widgets/search/search.jsx
index 4689567f3..1bac4a619 100644
--- a/src/components/widgets/search/search.jsx
+++ b/src/components/widgets/search/search.jsx
@@ -1,10 +1,13 @@
-import { useState, useEffect, Fragment } from "react";
+import { useState, useEffect, useCallback, Fragment } from "react";
import { useTranslation } from "next-i18next";
import { FiSearch } from "react-icons/fi";
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
import { Listbox, Transition } from "@headlessui/react";
import classNames from "classnames";
+import ContainerForm from "../widget/container_form";
+import Raw from "../widget/raw";
+
export const searchProviders = {
google: {
name: "Google",
@@ -76,14 +79,9 @@ export default function Search({ options }) {
setSelectedProvider(storedProvider);
}
}, [availableProviderIds]);
-
- if (!availableProviderIds) {
- return null;
- }
- function handleSubmit(event) {
+ const submitCallback = useCallback(event => {
const q = encodeURIComponent(query);
-
const { url } = selectedProvider;
if (url) {
window.open(`${url}${q}`, options.target || "_blank");
@@ -94,6 +92,10 @@ export default function Search({ options }) {
event.preventDefault();
event.target.reset();
setQuery("");
+ }, [options.target, options.url, query, selectedProvider]);
+
+ if (!availableProviderIds) {
+ return null;
}
const onChangeProvider = (provider) => {
@@ -101,77 +103,79 @@ export default function Search({ options }) {
localStorage.setItem(localStorageKey, provider.name);
}
- return (
-
+
+
}
diff --git a/src/components/widgets/weather/weather.jsx b/src/components/widgets/weather/weather.jsx
index 20bf3dec2..702ea6693 100644
--- a/src/components/widgets/weather/weather.jsx
+++ b/src/components/widgets/weather/weather.jsx
@@ -1,10 +1,16 @@
import useSWR from "swr";
import { useState } from "react";
-import { BiError } from "react-icons/bi";
import { WiCloudDown } from "react-icons/wi";
import { MdLocationDisabled, MdLocationSearching } from "react-icons/md";
import { useTranslation } from "next-i18next";
+import Error from "../widget/error";
+import Container from "../widget/container";
+import PrimaryText from "../widget/primary_text";
+import SecondaryText from "../widget/secondary_text";
+import WidgetIcon from "../widget/widget_icon";
+import ContainerButton from "../widget/container_button";
+
import Icon from "./icon";
function Widget({ options }) {
@@ -15,59 +21,35 @@ function Widget({ options }) {
);
if (error || data?.error) {
- return (
-
-
-
-
-
- {t("widget.api_error")}
- -
-
-
-
-
- );
+ return
}
if (!data) {
- return (
-
-
-
-
-
-
- {t("weather.updating")}
- {t("weather.wait")}
-
-
-
- );
+ return
+ {t("weather.updating")}
+ {t("weather.wait")}
+
+ ;
}
const unit = options.units === "metric" ? "celsius" : "fahrenheit";
+ const weatherInfo = {
+ condition: data.current.condition.code,
+ timeOfDay: data.current.is_day ? "day" : "night",
+ };
- return (
-
-
-
-
-
-
-
- {options.label && `${options.label}, `}
- {t("common.number", {
- value: options.units === "metric" ? data.current.temp_c : data.current.temp_f,
- style: "unit",
- unit,
- })}
-
- {data.current.condition.text}
-
-
-
- );
+ return
+
+ {options.label && `${options.label}, `}
+ {t("common.number", {
+ value: options.units === "metric" ? data.current.temp_c : data.current.temp_f,
+ style: "unit",
+ unit,
+ })}
+
+ {data.current.condition.text}
+
+ ;
}
export default function WeatherApi({ options }) {
@@ -99,30 +81,12 @@ export default function WeatherApi({ options }) {
}
};
- // if (!requesting && !location) requestLocation();
-
if (!location) {
- return (
-
- );
+ return
+ {t("weather.current")}
+ {t("weather.allow")}
+
+ ;
}
return ;
diff --git a/src/components/widgets/widget.jsx b/src/components/widgets/widget.jsx
index 471418872..b4fdb1434 100644
--- a/src/components/widgets/widget.jsx
+++ b/src/components/widgets/widget.jsx
@@ -17,13 +17,13 @@ const widgetMappings = {
kubernetes: dynamic(() => import("components/widgets/kubernetes/kubernetes")),
};
-export default function Widget({ widget }) {
+export default function Widget({ widget, style }) {
const InfoWidget = widgetMappings[widget.type];
if (InfoWidget) {
return (
-
+
);
}
diff --git a/src/components/widgets/widget/container.jsx b/src/components/widgets/widget/container.jsx
new file mode 100644
index 000000000..3a4a9f57e
--- /dev/null
+++ b/src/components/widgets/widget/container.jsx
@@ -0,0 +1,42 @@
+import classNames from "classnames";
+
+import WidgetIcon from "./widget_icon";
+import PrimaryText from "./primary_text";
+import SecondaryText from "./secondary_text";
+import Raw from "./raw";
+
+export function getAllClasses(options, additionalClassNames = '') {
+ return classNames(
+ "flex flex-col justify-center first:ml-0 ml-4 mr-2",
+ additionalClassNames,
+ options?.style === "boxedWidgets" && " ml-4 mt-2 m:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-2 pl-3",
+ );
+}
+
+export function getInnerBlock(children) {
+ // children won't be an array if it's Raw component
+ return Array.isArray(children) &&
+
{children.find(child => child.type === WidgetIcon)}
+
+ {children.find(child => child.type === PrimaryText)}
+ {children.find(child => child.type === SecondaryText)}
+
+
;
+}
+
+export function getBottomBlock(children) {
+ if (children.type !== Raw) {
+ return children.find(child => child.type === Raw) || [];
+ }
+
+ return [children];
+}
+
+export default function Container({ children = [], options, additionalClassNames = '' }) {
+ return (
+
+ {getInnerBlock(children)}
+ {getBottomBlock(children)}
+
+ );
+}
diff --git a/src/components/widgets/widget/container_button.jsx b/src/components/widgets/widget/container_button.jsx
new file mode 100644
index 000000000..92d8a4166
--- /dev/null
+++ b/src/components/widgets/widget/container_button.jsx
@@ -0,0 +1,10 @@
+import { getAllClasses, getInnerBlock, getBottomBlock } from "./container";
+
+export default function ContainerButton ({ children = [], options, additionalClassNames = '', callback }) {
+ return (
+
+ );
+}
diff --git a/src/components/widgets/widget/container_form.jsx b/src/components/widgets/widget/container_form.jsx
new file mode 100644
index 000000000..7d28a1bb3
--- /dev/null
+++ b/src/components/widgets/widget/container_form.jsx
@@ -0,0 +1,10 @@
+import { getAllClasses, getInnerBlock, getBottomBlock } from "./container";
+
+export default function ContainerForm ({ children = [], options, additionalClassNames = '', callback }) {
+ return (
+
+ );
+}
diff --git a/src/components/widgets/widget/container_link.jsx b/src/components/widgets/widget/container_link.jsx
new file mode 100644
index 000000000..8ef0e80aa
--- /dev/null
+++ b/src/components/widgets/widget/container_link.jsx
@@ -0,0 +1,10 @@
+import { getAllClasses, getInnerBlock, getBottomBlock } from "./container";
+
+export default function ContainerLink ({ children = [], options, additionalClassNames = '', target }) {
+ return (
+
+ {getInnerBlock(children)}
+ {getBottomBlock(children)}
+
+ );
+}
diff --git a/src/components/widgets/widget/error.jsx b/src/components/widgets/widget/error.jsx
new file mode 100644
index 000000000..a3dbab85e
--- /dev/null
+++ b/src/components/widgets/widget/error.jsx
@@ -0,0 +1,15 @@
+import { useTranslation } from "react-i18next";
+import { BiError } from "react-icons/bi";
+
+import Container from "./container";
+import PrimaryText from "./primary_text";
+import WidgetIcon from "./widget_icon";
+
+export default function Error({ options }) {
+ const { t } = useTranslation();
+
+ return
+ {t("widget.api_error")}
+
+ ;
+}
diff --git a/src/components/widgets/widget/primary_text.jsx b/src/components/widgets/widget/primary_text.jsx
new file mode 100644
index 000000000..3418b92c7
--- /dev/null
+++ b/src/components/widgets/widget/primary_text.jsx
@@ -0,0 +1,5 @@
+export default function PrimaryText({ children }) {
+ return (
+ {children}
+ );
+}
diff --git a/src/components/widgets/widget/raw.jsx b/src/components/widgets/widget/raw.jsx
new file mode 100644
index 000000000..44e3dddc4
--- /dev/null
+++ b/src/components/widgets/widget/raw.jsx
@@ -0,0 +1,7 @@
+export default function Raw({ children }) {
+ if (children.type === Raw) {
+ return [children];
+ }
+
+ return children;
+}
diff --git a/src/components/widgets/widget/resource.jsx b/src/components/widgets/widget/resource.jsx
new file mode 100644
index 000000000..e77bcb5a7
--- /dev/null
+++ b/src/components/widgets/widget/resource.jsx
@@ -0,0 +1,22 @@
+import UsageBar from "../resources/usage-bar";
+
+export default function Resource({ children, icon, value, label, expandedValue, expandedLabel, percentage, key, expanded = false }) {
+ const Icon = icon;
+
+ return
+
+
+
+ { expanded &&
+
{expandedValue}
+
{expandedLabel}
+
+ }
+ { percentage &&
}
+ { children }
+
+
;
+}
diff --git a/src/components/widgets/widget/resources.jsx b/src/components/widgets/widget/resources.jsx
new file mode 100644
index 000000000..19fb021de
--- /dev/null
+++ b/src/components/widgets/widget/resources.jsx
@@ -0,0 +1,15 @@
+import ContainerLink from "./container_link";
+import Resource from "./resource";
+import Raw from "./raw";
+import WidgetLabel from "./widget_label";
+
+export default function Resources({ options, children, target }) {
+ return
+
+
+ { children.filter(child => child && child.type === Resource) }
+
+ { children.filter(child => child && child.type === WidgetLabel) }
+
+ ;
+}
diff --git a/src/components/widgets/widget/secondary_text.jsx b/src/components/widgets/widget/secondary_text.jsx
new file mode 100644
index 000000000..363d1bd04
--- /dev/null
+++ b/src/components/widgets/widget/secondary_text.jsx
@@ -0,0 +1,5 @@
+export default function SecondaryText({ children }) {
+ return (
+ {children}
+ );
+}
diff --git a/src/components/widgets/widget/widget_icon.jsx b/src/components/widgets/widget/widget_icon.jsx
new file mode 100644
index 000000000..9766a8791
--- /dev/null
+++ b/src/components/widgets/widget/widget_icon.jsx
@@ -0,0 +1,18 @@
+export default function WidgetIcon({ icon, size = "s", pulse = false, weatherInfo = {} }) {
+ const Icon = icon;
+ const { condition, timeOfDay } = weatherInfo;
+ let additionalClasses = "text-theme-800 dark:text-theme-200 ";
+
+ switch (size) {
+ case "m": additionalClasses += "w-6 h-6 "; break;
+ case "l": additionalClasses += "w-8 h-8 "; break;
+ case "xl": additionalClasses += "w-10 h-10 "; break;
+ default: additionalClasses += "w-5 h-5 ";
+ }
+
+ if (pulse) {
+ additionalClasses += "animate-pulse ";
+ }
+
+ return ;
+}
diff --git a/src/components/widgets/widget/widget_label.jsx b/src/components/widgets/widget/widget_label.jsx
new file mode 100644
index 000000000..dcb9b9e96
--- /dev/null
+++ b/src/components/widgets/widget/widget_label.jsx
@@ -0,0 +1,3 @@
+export default function WidgetLabel({ label = "" }) {
+ return {label}
+}
diff --git a/src/pages/api/widgets/longhorn.js b/src/pages/api/widgets/longhorn.js
index a6b6781c8..d23a7f61b 100644
--- a/src/pages/api/widgets/longhorn.js
+++ b/src/pages/api/widgets/longhorn.js
@@ -46,7 +46,7 @@ function parseLonghornData(data) {
export default async function handler(req, res) {
const settings = getSettings();
- const longhornSettings = settings?.providers?.longhorn;
+ const longhornSettings = settings?.providers?.longhorn || {};
const {url, username, password} = longhornSettings;
if (!url) {
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index e170d4e1d..006456f9d 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -160,6 +160,7 @@ const headerStyles = {
"m-4 mb-0 sm:m-8 sm:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-3",
underlined: "m-4 mb-0 sm:m-8 sm:mb-1 border-b-2 pb-4 border-theme-800 dark:border-theme-200/50",
clean: "m-4 mb-0 sm:m-8 sm:mb-0",
+ boxedWidgets: "m-4 mb-0 sm:m-8 sm:mb-0 sm:mt-1",
};
function Home({ initialSettings }) {
@@ -208,6 +209,7 @@ function Home({ initialSettings }) {
searchProvider = searchProviders[searchWidget.options?.provider];
}
}
+ const headerStyle = initialSettings?.headerStyle || "underlined";
useEffect(() => {
function handleKeyDown(e) {
@@ -256,7 +258,7 @@ function Home({ initialSettings }) {
!rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
-
+
))}
-
+
{widgets
.filter((widget) => rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
-
+
))}
>