From c5b6dcc1e08eb6fd1a8c01c776970a9f873545b5 Mon Sep 17 00:00:00 2001 From: Denis Papec Date: Sun, 16 Apr 2023 00:05:50 +0100 Subject: [PATCH 1/4] Add optional boxed styling and error component to information widgets Signed-off-by: Denis Papec --- src/components/widgets/datetime/datetime.jsx | 8 +++-- src/components/widgets/error.jsx | 23 +++++++++++++ src/components/widgets/glances/glances.jsx | 30 +++++++--------- src/components/widgets/greeting/greeting.jsx | 7 +++- .../widgets/kubernetes/kubernetes.jsx | 29 +++++++--------- src/components/widgets/logo/logo.jsx | 7 +++- src/components/widgets/longhorn/longhorn.jsx | 25 +++++++------- .../widgets/openmeteo/openmeteo.jsx | 34 +++++++++---------- .../widgets/openweathermap/weather.jsx | 33 +++++++++--------- .../widgets/resources/resources.jsx | 7 +++- src/components/widgets/search/search.jsx | 11 +++--- .../widgets/unifi_console/unifi_console.jsx | 26 +++++++------- src/components/widgets/weather/weather.jsx | 33 +++++++++--------- src/pages/api/widgets/longhorn.js | 2 +- 14 files changed, 153 insertions(+), 122 deletions(-) create mode 100644 src/components/widgets/error.jsx diff --git a/src/components/widgets/datetime/datetime.jsx b/src/components/widgets/datetime/datetime.jsx index 869834736..fc883ec35 100644 --- a/src/components/widgets/datetime/datetime.jsx +++ b/src/components/widgets/datetime/datetime.jsx @@ -1,5 +1,6 @@ import { useState, useEffect } from "react"; import { useTranslation } from "next-i18next"; +import classNames from "classnames"; const textSizes = { "4xl": "text-4xl", @@ -17,7 +18,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,7 +28,10 @@ export default function DateTime({ options }) { }, [date, setDate, dateLocale, format]); return ( -
+
{date} diff --git a/src/components/widgets/error.jsx b/src/components/widgets/error.jsx new file mode 100644 index 000000000..92e0076a1 --- /dev/null +++ b/src/components/widgets/error.jsx @@ -0,0 +1,23 @@ +import { useTranslation } from "react-i18next"; +import { BiError } from "react-icons/bi"; +import classNames from "classnames"; + +export default function Error({ options }) { + const { t } = useTranslation(); + + return ( +
+
+
+ +
+ {t("widget.api_error")} +
+
+
+
+ ); +} diff --git a/src/components/widgets/glances/glances.jsx b/src/components/widgets/glances/glances.jsx index 85dd44c0c..b6daba7b7 100644 --- a/src/components/widgets/glances/glances.jsx +++ b/src/components/widgets/glances/glances.jsx @@ -1,11 +1,12 @@ 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 classNames from "classnames"; import UsageBar from "../resources/usage-bar"; +import Error from "../error"; import { SettingsContext } from "utils/contexts/settings"; @@ -26,23 +27,15 @@ export default function Widget({ options }) { ); if (error || data?.error) { - return ( -
-
-
- -
- {t("widget.api_error")} -
-
-
-
- ); + return } if (!data) { return ( -
+
@@ -101,7 +94,10 @@ export default function Widget({ options }) { } return ( - +
@@ -184,7 +180,7 @@ export default function Widget({ options }) {
- {t("common.number", { + {t("common.number", { value: mainTemp, maximumFractionDigits: 1, style: "unit", @@ -196,7 +192,7 @@ export default function Widget({ options }) { {options.expanded && (
- {t("common.number", { + {t("common.number", { value: maxTemp, maximumFractionDigits: 1, style: "unit", diff --git a/src/components/widgets/greeting/greeting.jsx b/src/components/widgets/greeting/greeting.jsx index da0f063d1..2e129560c 100644 --- a/src/components/widgets/greeting/greeting.jsx +++ b/src/components/widgets/greeting/greeting.jsx @@ -1,3 +1,5 @@ +import classNames from "classnames"; + const textSizes = { "4xl": "text-4xl", "3xl": "text-3xl", @@ -12,7 +14,10 @@ const textSizes = { export default function Greeting({ options }) { if (options.text) { return ( -
+
{options.text} diff --git a/src/components/widgets/kubernetes/kubernetes.jsx b/src/components/widgets/kubernetes/kubernetes.jsx index 78c4caaf9..514993da3 100644 --- a/src/components/widgets/kubernetes/kubernetes.jsx +++ b/src/components/widgets/kubernetes/kubernetes.jsx @@ -1,12 +1,14 @@ import useSWR from "swr"; -import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import classNames from "classnames"; + +import Error from "../error"; import Node from "./node"; export default function Widget({ options }) { const { cluster, nodes } = options; - const { t, i18n } = useTranslation(); + const { i18n } = useTranslation(); const defaultData = { cpu: { @@ -29,23 +31,15 @@ export default function Widget({ options }) { ); if (error || data?.error) { - return ( -
-
-
- -
- {t("widget.api_error")} -
-
-
-
- ); + return } if (!data) { return ( -
+
{cluster.show && @@ -59,7 +53,10 @@ export default function Widget({ options }) { } return ( -
+
{cluster.show && diff --git a/src/components/widgets/logo/logo.jsx b/src/components/widgets/logo/logo.jsx index 96e8569fc..6cba17bf7 100644 --- a/src/components/widgets/logo/logo.jsx +++ b/src/components/widgets/logo/logo.jsx @@ -1,8 +1,13 @@ +import classNames from "classnames"; + import ResolvedIcon from "components/resolvedicon" export default function Logo({ options }) { return ( -
+
{options.icon ? : // fallback to homepage logo diff --git a/src/components/widgets/longhorn/longhorn.jsx b/src/components/widgets/longhorn/longhorn.jsx index 9fcb21b4a..5139f00ad 100644 --- a/src/components/widgets/longhorn/longhorn.jsx +++ b/src/components/widgets/longhorn/longhorn.jsx @@ -1,37 +1,36 @@ import useSWR from "swr"; -import { BiError } from "react-icons/bi"; -import { useTranslation } from "next-i18next"; +import classNames from "classnames"; + +import Error from "../error"; 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 ( -
+
{data.nodes .filter((node) => { diff --git a/src/components/widgets/openmeteo/openmeteo.jsx b/src/components/widgets/openmeteo/openmeteo.jsx index 0d29aef53..1381cc55a 100644 --- a/src/components/widgets/openmeteo/openmeteo.jsx +++ b/src/components/widgets/openmeteo/openmeteo.jsx @@ -1,9 +1,11 @@ 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 classNames from "classnames"; + +import Error from "../error"; import Icon from "./icon"; @@ -15,24 +17,15 @@ function Widget({ options }) { ); if (error || data?.error) { - return ( -
-
-
- -
- {t("widget.api_error")} - - -
-
-
-
- ); + return } if (!data) { return ( -
+
@@ -50,7 +43,10 @@ function Widget({ options }) { const timeOfDay = data.current_weather.time > data.daily.sunrise[0] && data.current_weather.time < data.daily.sunset[0] ? "day" : "night"; return ( -
+
@@ -107,8 +103,10 @@ export default function OpenMeteo({ options }) { - ); + 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 b404039ff..305315139 100644 --- a/src/components/widgets/openweathermap/weather.jsx +++ b/src/components/widgets/openweathermap/weather.jsx @@ -3,12 +3,17 @@ import { useState } from "react"; import { WiCloudDown } from "react-icons/wi"; import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; import { useTranslation } from "next-i18next"; -import classNames from "classnames"; -import Error from "../error"; +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(); @@ -21,48 +26,26 @@ function Widget({ options }) { } 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 }) { @@ -94,33 +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..242e7a3db 100644 --- a/src/components/widgets/resources/cpu.jsx +++ b/src/components/widgets/resources/cpu.jsx @@ -1,8 +1,13 @@ import useSWR from "swr"; import { FiCpu } from "react-icons/fi"; -import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import SingleResource from "../widget/single_resource"; +import WidgetIcon from "../widget/widget_icon"; +import ResourceValue from "../widget/resource_value"; +import ResourceLabel from "../widget/resource_label"; +import Error from "../widget/error"; + import UsageBar from "./usage-bar"; export default function Cpu({ expanded }) { @@ -13,67 +18,38 @@ 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 + + - + {t("resources.cpu")} + - + {t("resources.load")} + + } - 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 + + + {t("common.number", { + value: data.cpu.usage, + style: "unit", + unit: "percent", + maximumFractionDigits: 0, + })} + + {t("resources.cpu")} + + {t("common.number", { + value: data.cpu.load, + maximumFractionDigits: 2, + })} + + {t("resources.load")} + + } diff --git a/src/components/widgets/resources/cputemp.jsx b/src/components/widgets/resources/cputemp.jsx index 571e6c8a7..1a62aa31c 100644 --- a/src/components/widgets/resources/cputemp.jsx +++ b/src/components/widgets/resources/cputemp.jsx @@ -1,8 +1,13 @@ import useSWR from "swr"; import { FaThermometerHalf } from "react-icons/fa"; -import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import SingleResource from "../widget/single_resource"; +import WidgetIcon from "../widget/widget_icon"; +import ResourceValue from "../widget/resource_value"; +import ResourceLabel from "../widget/resource_label"; +import Error from "../widget/error"; + import UsageBar from "./usage-bar"; function convertToFahrenheit(t) { @@ -17,34 +22,17 @@ 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 + + - + {t("resources.temp")} + - + {t("resources.max")} + } let mainTemp = data.cputemp.main; @@ -54,38 +42,27 @@ 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 + + + {t("common.number", { + value: mainTemp, + maximumFractionDigits: 1, + style: "unit", + unit + })} + + {t("resources.temp")} + + {t("common.number", { + value: maxTemp, + maximumFractionDigits: 1, + style: "unit", + unit + })} + + {t("resources.max")} + + ; } diff --git a/src/components/widgets/resources/disk.jsx b/src/components/widgets/resources/disk.jsx index ca09c0958..742ff9d7d 100644 --- a/src/components/widgets/resources/disk.jsx +++ b/src/components/widgets/resources/disk.jsx @@ -1,8 +1,13 @@ import useSWR from "swr"; import { FiHardDrive } from "react-icons/fi"; -import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import SingleResource from "../widget/single_resource"; +import WidgetIcon from "../widget/widget_icon"; +import ResourceValue from "../widget/resource_value"; +import ResourceLabel from "../widget/resource_label"; +import Error from "../widget/error"; + import UsageBar from "./usage-bar"; export default function Disk({ options, expanded }) { @@ -13,56 +18,29 @@ 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 + + - + {t("resources.free")} + - + {t("resources.total")} + + ; } // 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 + + {t("common.bytes", { value: data.drive.available })} + {t("resources.free")} + {t("common.bytes", { value: data.drive.size })} + {t("resources.total")} + + ; } diff --git a/src/components/widgets/resources/memory.jsx b/src/components/widgets/resources/memory.jsx index 30b7c8eb8..97c74acce 100644 --- a/src/components/widgets/resources/memory.jsx +++ b/src/components/widgets/resources/memory.jsx @@ -1,8 +1,13 @@ import useSWR from "swr"; import { FaMemory } from "react-icons/fa"; -import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import SingleResource from "../widget/single_resource"; +import WidgetIcon from "../widget/widget_icon"; +import ResourceValue from "../widget/resource_value"; +import ResourceLabel from "../widget/resource_label"; +import Error from "../widget/error"; + import UsageBar from "./usage-bar"; export default function Memory({ expanded }) { @@ -13,63 +18,34 @@ 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 + + - + {t("resources.free")} + - + {t("resources.total")} + + ; } 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 + + {t("common.bytes", { value: data.memory.available, maximumFractionDigits: 1, binary: true })} + {t("resources.free")} + + {t("common.bytes", { + value: data.memory.total, + maximumFractionDigits: 1, + binary: true, + })} + + {t("resources.total")} + + ; } diff --git a/src/components/widgets/resources/resources.jsx b/src/components/widgets/resources/resources.jsx index 5727a2a00..0cc2c3013 100644 --- a/src/components/widgets/resources/resources.jsx +++ b/src/components/widgets/resources/resources.jsx @@ -1,4 +1,5 @@ -import classNames from "classnames"; +import Container from "../widget/container"; +import Raw from "../widget/raw"; import Disk from "./disk"; import Cpu from "./cpu"; @@ -8,11 +9,8 @@ import Uptime from "./uptime"; export default function Resources({ options }) { const { expanded, units } = options; - return ( -
+ return +
{options.cpu && } {options.memory && } @@ -25,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..6cc2b8c5e 100644 --- a/src/components/widgets/resources/uptime.jsx +++ b/src/components/widgets/resources/uptime.jsx @@ -1,8 +1,13 @@ import useSWR from "swr"; import { FaRegClock } from "react-icons/fa"; -import { BiError } from "react-icons/bi"; import { useTranslation } from "next-i18next"; +import SingleResource from "../widget/single_resource"; +import WidgetIcon from "../widget/widget_icon"; +import ResourceValue from "../widget/resource_value"; +import ResourceLabel from "../widget/resource_label"; +import Error from "../widget/error"; + import UsageBar from "./usage-bar"; export default function Uptime() { @@ -13,35 +18,22 @@ export default function Uptime() { }); if (error || data?.error) { - return ( -
- -
- {t("widget.api_error")} -
-
- ); + return } if (!data) { - return ( -
- -
- -
-
-
{t("resources.temp")}
-
-
-
- ); + return + + - + {t("resources.uptime")} + ; } 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")}`; @@ -49,18 +41,10 @@ export default function Uptime() { const percent = Math.round((new Date().getSeconds() / 60) * 100); - return ( -
- -
- -
- {uptime} -
-
{t("resources.uptime")}
-
- -
-
- ); + return + + {uptime} + {t("resources.uptime")} + + ; } diff --git a/src/components/widgets/search/search.jsx b/src/components/widgets/search/search.jsx index bca3eb58b..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", @@ -77,13 +80,8 @@ export default function Search({ options }) { } }, [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,80 +103,79 @@ export default function Search({ options }) { localStorage.setItem(localStorageKey, provider.name); } - return ( - -
- setQuery(s.currentTarget.value)} - required - autoCapitalize="off" - autoCorrect="off" - autoComplete="off" - // eslint-disable-next-line jsx-a11y/no-autofocus - autoFocus={options.focus} - /> - -
- - - {t("search.search")} - -
- - + +
+
+ setQuery(s.currentTarget.value)} + required + autoCapitalize="off" + autoCorrect="off" + autoComplete="off" + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus={options.focus} + /> + +
+ + + {t("search.search")} + +
+ -
- {availableProviderIds.map((providerId) => { - const p = searchProviders[providerId]; - return ( - - {({ active }) => ( -
  • - -
  • - )} -
    - ); - })} -
    - -
    -
    - - ); + +
    + {availableProviderIds.map((providerId) => { + const p = searchProviders[providerId]; + return ( + + {({ active }) => ( +
  • + +
  • + )} +
    + ); + })} +
    +
    + + +
    + + ; } diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx index 1896771f8..dad92cc78 100644 --- a/src/components/widgets/unifi_console/unifi_console.jsx +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -2,9 +2,12 @@ import { BiError, BiWifi, BiCheckCircle, BiXCircle, BiNetworkChart } from "react import { MdSettingsEthernet } from "react-icons/md"; import { useTranslation } from "next-i18next"; import { SiUbiquiti } from "react-icons/si"; -import classNames from "classnames"; -import Error from "../error"; +import Error from "../widget/error"; +import Container from "../widget/container"; +import Raw from "../widget/raw"; +import WidgetIcon from "../widget/widget_icon"; +import PrimaryText from "../widget/primary_text"; import useWidgetAPI from "utils/proxy/use-widget-api"; @@ -22,21 +25,10 @@ export default function Widget({ options }) { const defaultSite = options.site ? statsData?.data.find(s => s.desc === options.site) : statsData?.data?.find(s => s.name === "default"); if (!defaultSite) { - return ( -
    -
    -
    - -
    -
    - {t("unifi.wait")} -
    -
    -
    - ); + return + {t("unifi.wait")} + + ; } const wan = defaultSite.health.find(h => h.subsystem === "wan"); @@ -51,11 +43,9 @@ export default function Widget({ options }) { const dataEmpty = !(wan.show || lan.show || wlan.show || uptime); - return ( -
    + return + +
    @@ -139,6 +129,7 @@ export default function Widget({ options }) {
    }
    -
    - ); +
    +
    + } diff --git a/src/components/widgets/weather/weather.jsx b/src/components/widgets/weather/weather.jsx index 518014552..702ea6693 100644 --- a/src/components/widgets/weather/weather.jsx +++ b/src/components/widgets/weather/weather.jsx @@ -3,9 +3,13 @@ import { useState } from "react"; import { WiCloudDown } from "react-icons/wi"; import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; import { useTranslation } from "next-i18next"; -import classNames from "classnames"; -import Error from "../error"; +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"; @@ -21,49 +25,31 @@ function Widget({ options }) { } 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 }) { @@ -95,33 +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 ( +
    + {getInnerBlock(children)} + {getBottomBlock(children)} +
    + ); +} 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_label.jsx b/src/components/widgets/widget/resource_label.jsx new file mode 100644 index 000000000..87f2ad22b --- /dev/null +++ b/src/components/widgets/widget/resource_label.jsx @@ -0,0 +1,5 @@ +export default function ResourceLabel({ children }) { + return ( +
    {children}
    + ); +} diff --git a/src/components/widgets/widget/resource_value.jsx b/src/components/widgets/widget/resource_value.jsx new file mode 100644 index 000000000..8971c748d --- /dev/null +++ b/src/components/widgets/widget/resource_value.jsx @@ -0,0 +1,5 @@ +export default function ResourceValue({ children }) { + return ( +
    {children}
    + ); +} diff --git a/src/components/widgets/widget/resources.jsx b/src/components/widgets/widget/resources.jsx new file mode 100644 index 000000000..0771ec5e8 --- /dev/null +++ b/src/components/widgets/widget/resources.jsx @@ -0,0 +1,15 @@ +import ContainerLink from "./container_link"; +import SingleResource from "./single_resource"; +import Raw from "./raw"; +import WidgetLabel from "./widget_label"; + +export default function Resources({ options, children, target }) { + return + +
    + {children.filter(child => child && child.type === SingleResource)} +
    + {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/single_resource.jsx b/src/components/widgets/widget/single_resource.jsx new file mode 100644 index 000000000..7a83d8bed --- /dev/null +++ b/src/components/widgets/widget/single_resource.jsx @@ -0,0 +1,28 @@ +import UsageBar from "../resources/usage-bar"; + +import WidgetIcon from "./widget_icon"; +import ResourceValue from "./resource_value"; +import ResourceLabel from "./resource_label"; +import Raw from "./raw"; + +export default function SingleResource({ children, key, expanded = false }) { + const values = children.filter(child => child.type === ResourceValue); + const labels = children.filter(child => child.type === ResourceLabel); + + return
    + {children.find(child => child.type === WidgetIcon)} +
    +
    + {values.pop()} + {labels.pop()} +
    + { expanded &&
    + {values.pop()} + {labels.pop()} +
    + } + {children.find(child => child.type === UsageBar)} +
    + {children.find(child => child.type === Raw)} +
    ; +} 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/index.jsx b/src/pages/index.jsx index 6180ff51e..7611aed54 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) => ( - + ))}
    From 6f750dd83cfdfb2c5784811e1c091fa814b68ff4 Mon Sep 17 00:00:00 2001 From: Denis Papec Date: Mon, 5 Jun 2023 23:18:18 +0100 Subject: [PATCH 3/4] Further improvements to simplify information widgets Signed-off-by: Denis Papec --- src/components/widgets/glances/glances.jsx | 130 ++++++++---------- src/components/widgets/longhorn/node.jsx | 25 ++-- src/components/widgets/resources/cpu.jsx | 54 +++----- src/components/widgets/resources/cputemp.jsx | 63 ++++----- src/components/widgets/resources/disk.jsx | 41 +++--- src/components/widgets/resources/memory.jsx | 47 +++---- src/components/widgets/resources/uptime.jsx | 22 +-- src/components/widgets/widget/resource.jsx | 22 +++ .../widgets/widget/resource_label.jsx | 5 - .../widgets/widget/resource_value.jsx | 5 - src/components/widgets/widget/resources.jsx | 6 +- .../widgets/widget/single_resource.jsx | 28 ---- 12 files changed, 181 insertions(+), 267 deletions(-) create mode 100644 src/components/widgets/widget/resource.jsx delete mode 100644 src/components/widgets/widget/resource_label.jsx delete mode 100644 src/components/widgets/widget/resource_value.jsx delete mode 100644 src/components/widgets/widget/single_resource.jsx diff --git a/src/components/widgets/glances/glances.jsx b/src/components/widgets/glances/glances.jsx index debb09c73..b45dfefeb 100644 --- a/src/components/widgets/glances/glances.jsx +++ b/src/components/widgets/glances/glances.jsx @@ -4,12 +4,8 @@ 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 SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +import Resource from "../widget/resource"; import Resources from "../widget/resources"; import WidgetLabel from "../widget/widget_label"; @@ -37,31 +33,11 @@ export default function Widget({ options }) { if (!data) { return - - - {t("glances.wait")} - - - - - {t("glances.wait")} - - - {options.cputemp && - - - {t("glances.wait")} - - - } - {options.uptime && - - - {t("glances.wait")} - - - } - {options.label && } + + + { options.cputemp && } + { options.uptime && } + { options.label && } ; } @@ -93,77 +69,81 @@ export default function Widget({ options }) { return ( - - - {t("common.number", { + - {t("glances.cpu")} - {t("common.number", { + })} + label={t("glances.cpu")} + expandedValue={t("common.number", { value: data.load.min15, style: "unit", unit: "percent", - maximumFractionDigits: 0, - })} - {t("glances.load")} - - - - - {t("common.bytes", { + maximumFractionDigits: 0 + })} + expandedLabel={t("glances.load")} + percentage={data.cpu.total} + expanded={options.expanded} + /> + - {t("glances.free")} - {t("common.bytes", { + })} + label={t("glances.free")} + expandedValue={t("common.bytes", { value: data.mem.total, maximumFractionDigits: 1, binary: true, - })} - {t("glances.total")} - - + })} + expandedLabel={t("glances.total")} + percentage={data.mem.percent} + expanded={options.expanded} + /> {disks.map((disk) => ( - - - {t("common.bytes", { value: disk.free })} - {t("glances.free")} - {t("common.bytes", { value: disk.size })} - {t("glances.total")} - - + ))} {options.cputemp && mainTemp > 0 && - - - {t("common.number", { + - {t("glances.temp")} - {t("common.number", { + })} + label={t("glances.temp")} + expandedValue={t("common.number", { value: maxTemp, maximumFractionDigits: 1, style: "unit", unit - })} - {t("glances.warn")} - - + })} + expandedLabel={t("glances.warn")} + percentage={tempPercent} + expanded={options.expanded} + /> } {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 && } diff --git a/src/components/widgets/longhorn/node.jsx b/src/components/widgets/longhorn/node.jsx index 9983486e3..5235698a4 100644 --- a/src/components/widgets/longhorn/node.jsx +++ b/src/components/widgets/longhorn/node.jsx @@ -1,23 +1,20 @@ import { useTranslation } from "next-i18next"; import { FaThermometerHalf } from "react-icons/fa"; -import UsageBar from "../resources/usage-bar"; -import SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +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")} - {t("common.bytes", { value: data.node.maximum })} - {t("resources.total")} - - { labels && } - + return { labels && } + } diff --git a/src/components/widgets/resources/cpu.jsx b/src/components/widgets/resources/cpu.jsx index 242e7a3db..12972fe89 100644 --- a/src/components/widgets/resources/cpu.jsx +++ b/src/components/widgets/resources/cpu.jsx @@ -2,14 +2,9 @@ import useSWR from "swr"; import { FiCpu } from "react-icons/fi"; import { useTranslation } from "next-i18next"; -import SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +import Resource from "../widget/resource"; import Error from "../widget/error"; -import UsageBar from "./usage-bar"; - export default function Cpu({ expanded }) { const { t } = useTranslation(); @@ -22,34 +17,25 @@ export default function Cpu({ expanded }) { } if (!data) { - return - - - - {t("resources.cpu")} - - - {t("resources.load")} - - + return } - return - - - {t("common.number", { - value: data.cpu.usage, - style: "unit", - unit: "percent", - maximumFractionDigits: 0, - })} - - {t("resources.cpu")} - - {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 1a62aa31c..ba6d9b730 100644 --- a/src/components/widgets/resources/cputemp.jsx +++ b/src/components/widgets/resources/cputemp.jsx @@ -2,14 +2,9 @@ import useSWR from "swr"; import { FaThermometerHalf } from "react-icons/fa"; import { useTranslation } from "next-i18next"; -import SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +import Resource from "../widget/resource"; import Error from "../widget/error"; -import UsageBar from "./usage-bar"; - function convertToFahrenheit(t) { return t * 9/5 + 32 } @@ -26,13 +21,14 @@ export default function CpuTemp({ expanded, units }) { } if (!data || !data.cputemp) { - return - - - - {t("resources.temp")} - - - {t("resources.max")} - + return ; } let mainTemp = data.cputemp.main; @@ -43,26 +39,23 @@ export default function CpuTemp({ expanded, units }) { mainTemp = (unit === "celsius") ? mainTemp : convertToFahrenheit(mainTemp); const maxTemp = (unit === "celsius") ? data.cputemp.max : convertToFahrenheit(data.cputemp.max); - return - - - {t("common.number", { - value: mainTemp, - maximumFractionDigits: 1, - style: "unit", - unit - })} - - {t("resources.temp")} - - {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 742ff9d7d..ab56624d9 100644 --- a/src/components/widgets/resources/disk.jsx +++ b/src/components/widgets/resources/disk.jsx @@ -2,14 +2,9 @@ import useSWR from "swr"; import { FiHardDrive } from "react-icons/fi"; import { useTranslation } from "next-i18next"; -import SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +import Resource from "../widget/resource"; import Error from "../widget/error"; -import UsageBar from "./usage-bar"; - export default function Disk({ options, expanded }) { const { t } = useTranslation(); @@ -22,25 +17,27 @@ export default function Disk({ options, expanded }) { } if (!data) { - return - - - - {t("resources.free")} - - - {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")} - {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 97c74acce..19ae86879 100644 --- a/src/components/widgets/resources/memory.jsx +++ b/src/components/widgets/resources/memory.jsx @@ -2,14 +2,9 @@ import useSWR from "swr"; import { FaMemory } from "react-icons/fa"; import { useTranslation } from "next-i18next"; -import SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +import Resource from "../widget/resource"; import Error from "../widget/error"; -import UsageBar from "./usage-bar"; - export default function Memory({ expanded }) { const { t } = useTranslation(); @@ -22,30 +17,26 @@ export default function Memory({ expanded }) { } if (!data) { - return - - - - {t("resources.free")} - - - {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")} - - {t("common.bytes", { - value: data.memory.total, - maximumFractionDigits: 1, - binary: true, - })} - - {t("resources.total")} - - ; + return ; } diff --git a/src/components/widgets/resources/uptime.jsx b/src/components/widgets/resources/uptime.jsx index 6cc2b8c5e..3984975f1 100644 --- a/src/components/widgets/resources/uptime.jsx +++ b/src/components/widgets/resources/uptime.jsx @@ -2,14 +2,9 @@ import useSWR from "swr"; import { FaRegClock } from "react-icons/fa"; import { useTranslation } from "next-i18next"; -import SingleResource from "../widget/single_resource"; -import WidgetIcon from "../widget/widget_icon"; -import ResourceValue from "../widget/resource_value"; -import ResourceLabel from "../widget/resource_label"; +import Resource from "../widget/resource"; import Error from "../widget/error"; -import UsageBar from "./usage-bar"; - export default function Uptime() { const { t } = useTranslation(); @@ -22,11 +17,7 @@ export default function Uptime() { } if (!data) { - return - - - - {t("resources.uptime")} - ; + return ; } const mo = Math.floor(data.uptime / (3600 * 24 * 31)); @@ -39,12 +30,7 @@ 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); + const percent = Math.round((new Date().getSeconds() / 60) * 100).toString(); - return - - {uptime} - {t("resources.uptime")} - - ; + return ; } 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
    + +
    +
    +
    {value}
    +
    {label}
    +
    + { expanded &&
    +
    {expandedValue}
    +
    {expandedLabel}
    +
    + } + { percentage && } + { children } +
    +
    ; +} diff --git a/src/components/widgets/widget/resource_label.jsx b/src/components/widgets/widget/resource_label.jsx deleted file mode 100644 index 87f2ad22b..000000000 --- a/src/components/widgets/widget/resource_label.jsx +++ /dev/null @@ -1,5 +0,0 @@ -export default function ResourceLabel({ children }) { - return ( -
    {children}
    - ); -} diff --git a/src/components/widgets/widget/resource_value.jsx b/src/components/widgets/widget/resource_value.jsx deleted file mode 100644 index 8971c748d..000000000 --- a/src/components/widgets/widget/resource_value.jsx +++ /dev/null @@ -1,5 +0,0 @@ -export default function ResourceValue({ children }) { - return ( -
    {children}
    - ); -} diff --git a/src/components/widgets/widget/resources.jsx b/src/components/widgets/widget/resources.jsx index 0771ec5e8..19fb021de 100644 --- a/src/components/widgets/widget/resources.jsx +++ b/src/components/widgets/widget/resources.jsx @@ -1,5 +1,5 @@ import ContainerLink from "./container_link"; -import SingleResource from "./single_resource"; +import Resource from "./resource"; import Raw from "./raw"; import WidgetLabel from "./widget_label"; @@ -7,9 +7,9 @@ export default function Resources({ options, children, target }) { return
    - {children.filter(child => child && child.type === SingleResource)} + { children.filter(child => child && child.type === Resource) }
    - {children.filter(child => child && child.type === WidgetLabel)} + { children.filter(child => child && child.type === WidgetLabel) }
    ; } diff --git a/src/components/widgets/widget/single_resource.jsx b/src/components/widgets/widget/single_resource.jsx deleted file mode 100644 index 7a83d8bed..000000000 --- a/src/components/widgets/widget/single_resource.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import UsageBar from "../resources/usage-bar"; - -import WidgetIcon from "./widget_icon"; -import ResourceValue from "./resource_value"; -import ResourceLabel from "./resource_label"; -import Raw from "./raw"; - -export default function SingleResource({ children, key, expanded = false }) { - const values = children.filter(child => child.type === ResourceValue); - const labels = children.filter(child => child.type === ResourceLabel); - - return
    - {children.find(child => child.type === WidgetIcon)} -
    -
    - {values.pop()} - {labels.pop()} -
    - { expanded &&
    - {values.pop()} - {labels.pop()} -
    - } - {children.find(child => child.type === UsageBar)} -
    - {children.find(child => child.type === Raw)} -
    ; -} From 1622069063691bebefb37202d3383ddfe81b67fb Mon Sep 17 00:00:00 2001 From: Denis Papec Date: Mon, 12 Jun 2023 00:23:01 +0100 Subject: [PATCH 4/4] Fixes for existing header styles, fix for glances Signed-off-by: Denis Papec --- src/components/widgets/glances/glances.jsx | 2 ++ .../widgets/openweathermap/weather.jsx | 3 +-- src/components/widgets/widget/container.jsx | 22 ++++++++++++++----- src/components/widgets/widget/resource.jsx | 4 ++-- src/components/widgets/widget/resources.jsx | 6 +++-- .../widgets/widget/widget_label.jsx | 2 +- src/pages/index.jsx | 11 ++++++---- 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/components/widgets/glances/glances.jsx b/src/components/widgets/glances/glances.jsx index b45dfefeb..e5cf3fbdc 100644 --- a/src/components/widgets/glances/glances.jsx +++ b/src/components/widgets/glances/glances.jsx @@ -36,6 +36,8 @@ export default function Widget({ options }) { { options.cputemp && } + { options.disk && !Array.isArray(options.disk) && } + { options.disk && Array.isArray(options.disk) && options.disk.map((disk) => )} { options.uptime && } { options.label && } ; diff --git a/src/components/widgets/openweathermap/weather.jsx b/src/components/widgets/openweathermap/weather.jsx index 305315139..a857f13a2 100644 --- a/src/components/widgets/openweathermap/weather.jsx +++ b/src/components/widgets/openweathermap/weather.jsx @@ -41,8 +41,7 @@ function Widget({ options }) { }; return - {options.label && `${options.label}, `} - {t("common.number", { value: data.main.temp, style: "unit", unit })} + {options.label && `${options.label}, ` }{t("common.number", { value: data.main.temp, style: "unit", unit })} {data.weather[0].description} ; diff --git a/src/components/widgets/widget/container.jsx b/src/components/widgets/widget/container.jsx index 3a4a9f57e..59ea56841 100644 --- a/src/components/widgets/widget/container.jsx +++ b/src/components/widgets/widget/container.jsx @@ -6,10 +6,22 @@ import SecondaryText from "./secondary_text"; import Raw from "./raw"; export function getAllClasses(options, additionalClassNames = '') { + if (options?.style?.header === "boxedWidgets") { + return classNames( + "flex flex-col justify-center first:ml-0 ml-2 mr-2", + "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 pr-3", + additionalClassNames + ); + } + + let widgetAlignedClasses = "flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap"; + if (options?.style?.isRightAligned) { + widgetAlignedClasses = "flex flex-col justify-center first:ml-auto ml-2 mr-2 "; + } + 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", + widgetAlignedClasses, + additionalClassNames ); } @@ -18,8 +30,8 @@ export function getInnerBlock(children) { return Array.isArray(children) &&
    {children.find(child => child.type === WidgetIcon)}
    - {children.find(child => child.type === PrimaryText)} - {children.find(child => child.type === SecondaryText)} + {children.find(child => child.type === PrimaryText)} + {children.find(child => child.type === SecondaryText)}
    ; } diff --git a/src/components/widgets/widget/resource.jsx b/src/components/widgets/widget/resource.jsx index e77bcb5a7..18e7c8004 100644 --- a/src/components/widgets/widget/resource.jsx +++ b/src/components/widgets/widget/resource.jsx @@ -1,9 +1,9 @@ import UsageBar from "../resources/usage-bar"; -export default function Resource({ children, icon, value, label, expandedValue, expandedLabel, percentage, key, expanded = false }) { +export default function Resource({ children, icon, value, label, expandedValue = "", expandedLabel = "", percentage, expanded = false }) { const Icon = icon; - return
    + return
    diff --git a/src/components/widgets/widget/resources.jsx b/src/components/widgets/widget/resources.jsx index 19fb021de..394a3058a 100644 --- a/src/components/widgets/widget/resources.jsx +++ b/src/components/widgets/widget/resources.jsx @@ -4,12 +4,14 @@ import Raw from "./raw"; import WidgetLabel from "./widget_label"; export default function Resources({ options, children, target }) { + const widgetParts = [].concat(...children); + return
    - { children.filter(child => child && child.type === Resource) } + { widgetParts.filter(child => child && child.type === Resource) }
    - { children.filter(child => child && child.type === WidgetLabel) } + { widgetParts.filter(child => child && child.type === WidgetLabel) }
    ; } diff --git a/src/components/widgets/widget/widget_label.jsx b/src/components/widgets/widget/widget_label.jsx index dcb9b9e96..5fc6ced09 100644 --- a/src/components/widgets/widget/widget_label.jsx +++ b/src/components/widgets/widget/widget_label.jsx @@ -1,3 +1,3 @@ export default function WidgetLabel({ label = "" }) { - return
    {label}
    + return
    {label}
    } diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 7611aed54..d91a83398 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -274,14 +274,17 @@ function Home({ initialSettings }) { {widgets .filter((widget) => !rightAlignedWidgets.includes(widget.type)) .map((widget, i) => ( - + ))} -
    +
    {widgets .filter((widget) => rightAlignedWidgets.includes(widget.type)) .map((widget, i) => ( - + ))}
    @@ -361,7 +364,7 @@ export default function Wrapper({ initialSettings, fallback }) { style={wrappedStyle} >