diff --git a/src/widgets/glances/chart.jsx b/src/widgets/glances/chart.jsx
deleted file mode 100644
index 448bb99b..00000000
--- a/src/widgets/glances/chart.jsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { PureComponent } from "react";
-import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
-
-import CustomTooltip from "./custom_tooltip";
-
-class Chart extends PureComponent {
- render() {
- const { dataPoints, formatter, label } = this.props;
-
- return (
-
-
-
-
-
-
-
-
-
-
- }
- classNames="rounded-md text-xs p-0.5"
- contentStyle={{
- backgroundColor: "rgb(var(--color-800))",
- color: "rgb(var(--color-100))"
- }}
- />
-
-
-
- );
- }
-}
-
-export default Chart;
diff --git a/src/widgets/glances/chart_dual.jsx b/src/widgets/glances/chart_dual.jsx
deleted file mode 100644
index ceecacba..00000000
--- a/src/widgets/glances/chart_dual.jsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { PureComponent } from "react";
-import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
-
-import CustomTooltip from "./custom_tooltip";
-
-class ChartDual extends PureComponent {
- render() {
- const { dataPoints, formatter, stack, label } = this.props;
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- classNames="rounded-md text-xs p-0.5"
- contentStyle={{
- backgroundColor: "rgb(var(--color-800))",
- color: "rgb(var(--color-100))"
- }}
-
- />
-
-
-
- );
- }
-}
-
-export default ChartDual;
diff --git a/src/widgets/glances/component.jsx b/src/widgets/glances/component.jsx
index 5eeff280..4fa1a9ff 100644
--- a/src/widgets/glances/component.jsx
+++ b/src/widgets/glances/component.jsx
@@ -1,9 +1,9 @@
-import Memory from "./memory";
-import Cpu from "./cpu";
-import Sensor from "./sensor";
-import Net from "./net";
-import Process from "./process";
-import Disk from "./disk";
+import Memory from "./metrics/memory";
+import Cpu from "./metrics/cpu";
+import Sensor from "./metrics/sensor";
+import Net from "./metrics/net";
+import Process from "./metrics/process";
+import Disk from "./metrics/disk";
export default function Component({ service }) {
const { widget } = service;
diff --git a/src/widgets/glances/components/block.jsx b/src/widgets/glances/components/block.jsx
new file mode 100644
index 00000000..73cf86c9
--- /dev/null
+++ b/src/widgets/glances/components/block.jsx
@@ -0,0 +1,9 @@
+export default function Block({ position, children }) {
+ const positionClasses = Object.entries(position).map(([key, value]) => `${key}-${value}`).join(' ');
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/widgets/glances/components/chart.jsx b/src/widgets/glances/components/chart.jsx
new file mode 100644
index 00000000..2cd01107
--- /dev/null
+++ b/src/widgets/glances/components/chart.jsx
@@ -0,0 +1,48 @@
+import { PureComponent } from "react";
+import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
+
+import CustomTooltip from "./custom_tooltip";
+
+class Chart extends PureComponent {
+ render() {
+ const { dataPoints, formatter, label } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ }
+ classNames="rounded-md text-xs p-0.5"
+ contentStyle={{
+ backgroundColor: "rgb(var(--color-800))",
+ color: "rgb(var(--color-100))"
+ }}
+ />
+
+
+
+
+ );
+ }
+}
+
+export default Chart;
diff --git a/src/widgets/glances/components/chart_dual.jsx b/src/widgets/glances/components/chart_dual.jsx
new file mode 100644
index 00000000..14f5e4e6
--- /dev/null
+++ b/src/widgets/glances/components/chart_dual.jsx
@@ -0,0 +1,63 @@
+import { PureComponent } from "react";
+import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
+
+import CustomTooltip from "./custom_tooltip";
+
+class ChartDual extends PureComponent {
+ render() {
+ const { dataPoints, formatter, stack, label } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ classNames="rounded-md text-xs p-0.5"
+ contentStyle={{
+ backgroundColor: "rgb(var(--color-800))",
+ color: "rgb(var(--color-100))"
+ }}
+
+ />
+
+
+
+
+ );
+ }
+}
+
+export default ChartDual;
diff --git a/src/widgets/glances/components/container.jsx b/src/widgets/glances/components/container.jsx
new file mode 100644
index 00000000..d141cab6
--- /dev/null
+++ b/src/widgets/glances/components/container.jsx
@@ -0,0 +1,8 @@
+export default function Container({ children }) {
+ return (
+
+ );
+}
diff --git a/src/widgets/glances/custom_tooltip.jsx b/src/widgets/glances/components/custom_tooltip.jsx
similarity index 100%
rename from src/widgets/glances/custom_tooltip.jsx
rename to src/widgets/glances/components/custom_tooltip.jsx
diff --git a/src/widgets/glances/components/error.jsx b/src/widgets/glances/components/error.jsx
new file mode 100644
index 00000000..6e3b4da0
--- /dev/null
+++ b/src/widgets/glances/components/error.jsx
@@ -0,0 +1,9 @@
+import { useTranslation } from "next-i18next";
+
+export default function Error() {
+ const { t } = useTranslation();
+
+ return
+ {t("widget.api_error")}
+
;
+}
diff --git a/src/widgets/glances/cpu.jsx b/src/widgets/glances/cpu.jsx
deleted file mode 100644
index daec91e0..00000000
--- a/src/widgets/glances/cpu.jsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import dynamic from "next/dynamic";
-import { useState, useEffect } from "react";
-import { useTranslation } from "next-i18next";
-
-import useWidgetAPI from "utils/proxy/use-widget-api";
-
-const Chart = dynamic(() => import("./chart"), { ssr: false });
-
-const pointsLimit = 15;
-
-export default function Component({ service }) {
- const { t } = useTranslation();
-
- const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
-
- const { data, error } = useWidgetAPI(service.widget, 'cpu', {
- refreshInterval: 1000,
- });
-
- const { data: systemData, error: systemError } = useWidgetAPI(service.widget, 'system');
-
- useEffect(() => {
- if (data) {
- setDataPoints((prevDataPoints) => {
- const newDataPoints = [...prevDataPoints, { value: data.total }];
- if (newDataPoints.length > pointsLimit) {
- newDataPoints.shift();
- }
- return newDataPoints;
- });
- }
- }, [data]);
-
- if (error) {
- return
-
-
- {t("widget.api_error")}
-
-
-
;
- }
-
- if (!data) {
- return ;
- }
-
- return (
- <>
-
- t("common.number", {
- value,
- style: "unit",
- unit: "percent",
- maximumFractionDigits: 0,
- })}
- />
-
-
- {systemData && !systemError && (
- <>
- {systemData.linux_distro && (
-
- {systemData.linux_distro}
-
- )}
- {systemData.os_version && (
-
- {systemData.os_version}
-
- )}
- {systemData.hostname && (
-
- {systemData.hostname}
-
- )}
- >
- )}
-
-
- {t("common.number", {
- value: data.total,
- style: "unit",
- unit: "percent",
- maximumFractionDigits: 0,
- })} {t("resources.used")}
-
-
- >
- );
-}
diff --git a/src/widgets/glances/memory.jsx b/src/widgets/glances/memory.jsx
deleted file mode 100644
index 0e6002ee..00000000
--- a/src/widgets/glances/memory.jsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import dynamic from "next/dynamic";
-import { useState, useEffect } from "react";
-import { useTranslation } from "next-i18next";
-
-import useWidgetAPI from "utils/proxy/use-widget-api";
-
-const ChartDual = dynamic(() => import("./chart_dual"), { ssr: false });
-
-const pointsLimit = 15;
-
-export default function Component({ service }) {
- const { t } = useTranslation();
-
- const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
-
- const { data, error } = useWidgetAPI(service.widget, 'mem', {
- refreshInterval: 1000,
- });
-
- useEffect(() => {
- if (data) {
- setDataPoints((prevDataPoints) => {
- const newDataPoints = [...prevDataPoints, { a: data.used, b: data.free }];
- if (newDataPoints.length > pointsLimit) {
- newDataPoints.shift();
- }
- return newDataPoints;
- });
- }
- }, [data]);
-
- if (error) {
- return
-
-
- {t("widget.api_error")}
-
-
-
;
- }
- if (!data) {
- return ;
- }
-
- return (
- <>
-
- t("common.bytes", {
- value,
- maximumFractionDigits: 0,
- })}
- />
-
-
- {data && !error && (
- <>
- {data.free && (
-
- {t("common.bytes", {
- value: data.free,
- maximumFractionDigits: 0,
- })} {t("resources.free")}
-
- )}
-
- {data.total && (
-
- {t("common.bytes", {
- value: data.total,
- maximumFractionDigits: 0,
- })} {t("resources.total")}
-
- )}
- >
- )}
-
-
- {t("common.bytes", {
- value: data.used,
- maximumFractionDigits: 0,
- })} {t("resources.used")}
-
-
- >
- );
-}
diff --git a/src/widgets/glances/metrics/cpu.jsx b/src/widgets/glances/metrics/cpu.jsx
new file mode 100644
index 00000000..a93abbc7
--- /dev/null
+++ b/src/widgets/glances/metrics/cpu.jsx
@@ -0,0 +1,91 @@
+import dynamic from "next/dynamic";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
+
+import Error from "../components/error";
+import Container from "../components/container";
+import Block from "../components/block";
+
+import useWidgetAPI from "utils/proxy/use-widget-api";
+
+const Chart = dynamic(() => import("../components/chart"), { ssr: false });
+
+const pointsLimit = 15;
+
+export default function Component({ service }) {
+ const { t } = useTranslation();
+
+ const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
+
+ const { data, error } = useWidgetAPI(service.widget, 'cpu', {
+ refreshInterval: 1000,
+ });
+
+ const { data: systemData, error: systemError } = useWidgetAPI(service.widget, 'system');
+
+ useEffect(() => {
+ if (data) {
+ setDataPoints((prevDataPoints) => {
+ const newDataPoints = [...prevDataPoints, { value: data.total }];
+ if (newDataPoints.length > pointsLimit) {
+ newDataPoints.shift();
+ }
+ return newDataPoints;
+ });
+ }
+ }, [data]);
+
+ if (error) {
+ return ;
+ }
+
+ if (!data) {
+ return -;
+ }
+
+ return (
+
+ t("common.number", {
+ value,
+ style: "unit",
+ unit: "percent",
+ maximumFractionDigits: 0,
+ })}
+ />
+
+ {systemData && !systemError && (
+
+ {systemData.linux_distro && (
+
+ {systemData.linux_distro}
+
+ )}
+ {systemData.os_version && (
+
+ {systemData.os_version}
+
+ )}
+ {systemData.hostname && (
+
+ {systemData.hostname}
+
+ )}
+
+ )}
+
+
+
+ {t("common.number", {
+ value: data.total,
+ style: "unit",
+ unit: "percent",
+ maximumFractionDigits: 0,
+ })} {t("resources.used")}
+
+
+
+ );
+}
diff --git a/src/widgets/glances/disk.jsx b/src/widgets/glances/metrics/disk.jsx
similarity index 50%
rename from src/widgets/glances/disk.jsx
rename to src/widgets/glances/metrics/disk.jsx
index 7ad783ac..dcb1dc71 100644
--- a/src/widgets/glances/disk.jsx
+++ b/src/widgets/glances/metrics/disk.jsx
@@ -2,9 +2,13 @@ import dynamic from "next/dynamic";
import { useState, useEffect } from "react";
import { useTranslation } from "next-i18next";
+import Error from "../components/error";
+import Container from "../components/container";
+import Block from "../components/block";
+
import useWidgetAPI from "utils/proxy/use-widget-api";
-const ChartDual = dynamic(() => import("./chart_dual"), { ssr: false });
+const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
const pointsLimit = 15;
@@ -44,70 +48,55 @@ export default function Component({ service }) {
}, [dataPoints]);
if (error) {
- return
-
-
- {t("widget.api_error")}
-
-
-
;
+ return ;
}
if (!data) {
- return ;
+ return -;
}
const diskData = data.find((item) => item.disk_name === diskName);
if (!diskData) {
- return ;
+ return -;
}
const diskRates = calculateRates(dataPoints);
const currentRate = diskRates[diskRates.length - 1];
return (
- <>
-
+
t("common.bitrate", {
- value,
- })}
- />
-
-
- {currentRate && !error && (
- <>
-
- {t("common.bitrate", {
- value: currentRate.a,
- })} {t("glances.read")}
-
-
- {t("common.bitrate", {
- value: currentRate.b,
- })} {t("glances.write")}
-
- >
- )}
-
-
- {t("common.bitrate", {
- value: currentRate.a + currentRate.b,
- })}
-
-
- >
+ dataPoints={ratePoints}
+ label={[t("glances.read"), t("glances.write")]}
+ max={diskData.critical}
+ formatter={(value) => t("common.bitrate", {
+ value,
+ })}
+ />
+
+ {currentRate && !error && (
+
+
+ {t("common.bitrate", {
+ value: currentRate.a,
+ })} {t("glances.read")}
+
+
+ {t("common.bitrate", {
+ value: currentRate.b,
+ })} {t("glances.write")}
+
+
+ )}
+
+
+
+ {t("common.bitrate", {
+ value: currentRate.a + currentRate.b,
+ })}
+
+
+
);
}
diff --git a/src/widgets/glances/metrics/memory.jsx b/src/widgets/glances/metrics/memory.jsx
new file mode 100644
index 00000000..f9d0cd15
--- /dev/null
+++ b/src/widgets/glances/metrics/memory.jsx
@@ -0,0 +1,88 @@
+import dynamic from "next/dynamic";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
+
+import Error from "../components/error";
+import Container from "../components/container";
+import Block from "../components/block";
+
+import useWidgetAPI from "utils/proxy/use-widget-api";
+
+const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
+
+const pointsLimit = 15;
+
+export default function Component({ service }) {
+ const { t } = useTranslation();
+
+ const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
+
+ const { data, error } = useWidgetAPI(service.widget, 'mem', {
+ refreshInterval: 1000,
+ });
+
+ useEffect(() => {
+ if (data) {
+ setDataPoints((prevDataPoints) => {
+ const newDataPoints = [...prevDataPoints, { a: data.used, b: data.free }];
+ if (newDataPoints.length > pointsLimit) {
+ newDataPoints.shift();
+ }
+ return newDataPoints;
+ });
+ }
+ }, [data]);
+
+ if (error) {
+ return ;
+ }
+
+ if (!data) {
+ return -;
+ }
+
+ return (
+
+ t("common.bytes", {
+ value,
+ maximumFractionDigits: 0,
+ })}
+ />
+
+ {data && !error && (
+
+ {data.free && (
+
+ {t("common.bytes", {
+ value: data.free,
+ maximumFractionDigits: 0,
+ })} {t("resources.free")}
+
+ )}
+
+ {data.total && (
+
+ {t("common.bytes", {
+ value: data.total,
+ maximumFractionDigits: 0,
+ })} {t("resources.total")}
+
+ )}
+
+ )}
+
+
+
+ {t("common.bytes", {
+ value: data.used,
+ maximumFractionDigits: 0,
+ })} {t("resources.used")}
+
+
+
+ );
+}
diff --git a/src/widgets/glances/net.jsx b/src/widgets/glances/metrics/net.jsx
similarity index 50%
rename from src/widgets/glances/net.jsx
rename to src/widgets/glances/metrics/net.jsx
index a630ae74..15233b42 100644
--- a/src/widgets/glances/net.jsx
+++ b/src/widgets/glances/metrics/net.jsx
@@ -2,9 +2,13 @@ import dynamic from "next/dynamic";
import { useState, useEffect } from "react";
import { useTranslation } from "next-i18next";
+import Error from "../components/error";
+import Container from "../components/container";
+import Block from "../components/block";
+
import useWidgetAPI from "utils/proxy/use-widget-api";
-const ChartDual = dynamic(() => import("./chart_dual"), { ssr: false });
+const ChartDual = dynamic(() => import("../components/chart_dual"), { ssr: false });
const pointsLimit = 15;
@@ -36,61 +40,53 @@ export default function Component({ service }) {
}, [data, interfaceName]);
if (error) {
- return
-
-
- {t("widget.api_error")}
-
-
-
;
+ return ;
}
+
if (!data) {
- return ;
+ return -;
}
+
const interfaceData = data.find((item) => item[item.key] === interfaceName);
if (!interfaceData) {
- return ;
+ return -;
}
return (
- <>
-
- t("common.byterate", {
- value,
- maximumFractionDigits: 0,
- })}
- />
-
-
+
+ t("common.byterate", {
+ value,
+ maximumFractionDigits: 0,
+ })}
+ />
+
+
{interfaceData && interfaceData.interface_name && (
-
+
{interfaceData.interface_name}
)}
- {t("common.bitrate", {
- value: interfaceData.tx,
- maximumFractionDigits: 0,
- })} {t("docker.tx")}
-
-
- {t("common.bitrate", {
- value: interfaceData.rx,
- maximumFractionDigits: 0,
- })} {t("docker.rx")}
-
-
- >
+
+
+ {t("common.bitrate", {
+ value: interfaceData.tx,
+ maximumFractionDigits: 0,
+ })} {t("docker.tx")}
+
+
+
+
+
+ {t("common.bitrate", {
+ value: interfaceData.rx,
+ maximumFractionDigits: 0,
+ })} {t("docker.rx")}
+
+
+
);
}
diff --git a/src/widgets/glances/process.jsx b/src/widgets/glances/metrics/process.jsx
similarity index 60%
rename from src/widgets/glances/process.jsx
rename to src/widgets/glances/metrics/process.jsx
index 7d9785e6..bf606a75 100644
--- a/src/widgets/glances/process.jsx
+++ b/src/widgets/glances/metrics/process.jsx
@@ -1,5 +1,9 @@
import { useTranslation } from "next-i18next";
+import Error from "../components/error";
+import Container from "../components/container";
+import Block from "../components/block";
+
import useWidgetAPI from "utils/proxy/use-widget-api";
import ResolvedIcon from "components/resolvedicon";
@@ -21,52 +25,42 @@ export default function Component({ service }) {
});
if (error) {
- return
-
-
- {t("widget.api_error")}
-
-
-
;
+ return
;
}
if (!data) {
- return
;
+ return
-;
}
data.splice(5);
return (
- <>
-
+
+
{t("resources.cpu")}
{t("resources.mem")}
-
-
- { data.map((item) =>
+
+
+
+
+ { data.map((item) =>
-
+
{statusMap[item.status]}
-
{item.name}
-
{item.cpu_percent.toFixed(1)}%
-
{t("common.bytes", {
+
{item.name}
+
{item.cpu_percent.toFixed(1)}%
+
{t("common.bytes", {
value: item.memory_info[0],
maximumFractionDigits: 0,
})}
) }
-
-
- >
+
+
+
);
}
diff --git a/src/widgets/glances/metrics/sensor.jsx b/src/widgets/glances/metrics/sensor.jsx
new file mode 100644
index 00000000..9be5666f
--- /dev/null
+++ b/src/widgets/glances/metrics/sensor.jsx
@@ -0,0 +1,88 @@
+import dynamic from "next/dynamic";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
+
+import Error from "../components/error";
+import Container from "../components/container";
+import Block from "../components/block";
+
+import useWidgetAPI from "utils/proxy/use-widget-api";
+
+const Chart = dynamic(() => import("../components/chart"), { ssr: false });
+
+const pointsLimit = 15;
+
+export default function Component({ service }) {
+ const { t } = useTranslation();
+ const { widget } = service;
+ const [, sensorName] = widget.metric.split(':');
+
+ const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
+
+ const { data, error } = useWidgetAPI(service.widget, 'sensors', {
+ refreshInterval: 1000,
+ });
+
+ useEffect(() => {
+ if (data) {
+ const sensorData = data.find((item) => item.label === sensorName);
+ setDataPoints((prevDataPoints) => {
+ const newDataPoints = [...prevDataPoints, { value: sensorData.value }];
+ if (newDataPoints.length > pointsLimit) {
+ newDataPoints.shift();
+ }
+ return newDataPoints;
+ });
+ }
+ }, [data, sensorName]);
+
+ if (error) {
+ return
;
+ }
+
+ if (!data) {
+ return
-;
+ }
+
+ const sensorData = data.find((item) => item.label === sensorName);
+
+ if (!sensorData) {
+ return
-;
+ }
+
+ return (
+
+ t("common.number", {
+ value,
+ })}
+ />
+
+ {sensorData && !error && (
+
+ {sensorData.warning && (
+
+ {sensorData.warning}{sensorData.unit} {t("glances.warn")}
+
+ )}
+ {sensorData.critical && (
+
+ {sensorData.critical} {sensorData.unit} {t("glances.crit")}
+
+ )}
+
+ )}
+
+
+
+ {t("common.number", {
+ value: sensorData.value,
+ })} {sensorData.unit}
+
+
+
+ );
+}
diff --git a/src/widgets/glances/sensor.jsx b/src/widgets/glances/sensor.jsx
deleted file mode 100644
index 32d01eb2..00000000
--- a/src/widgets/glances/sensor.jsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import dynamic from "next/dynamic";
-import { useState, useEffect } from "react";
-import { useTranslation } from "next-i18next";
-
-import useWidgetAPI from "utils/proxy/use-widget-api";
-
-const Chart = dynamic(() => import("./chart"), { ssr: false });
-
-const pointsLimit = 15;
-
-export default function Component({ service }) {
- const { t } = useTranslation();
- const { widget } = service;
- const [, sensorName] = widget.metric.split(':');
-
- const [dataPoints, setDataPoints] = useState(new Array(pointsLimit).fill({ value: 0 }, 0, pointsLimit));
-
- const { data, error } = useWidgetAPI(service.widget, 'sensors', {
- refreshInterval: 1000,
- });
-
- useEffect(() => {
- if (data) {
- const sensorData = data.find((item) => item.label === sensorName);
- setDataPoints((prevDataPoints) => {
- const newDataPoints = [...prevDataPoints, { value: sensorData.value }];
- if (newDataPoints.length > pointsLimit) {
- newDataPoints.shift();
- }
- return newDataPoints;
- });
- }
- }, [data, sensorName]);
-
- if (error) {
- return
-
-
- {t("widget.api_error")}
-
-
-
;
- }
-
- if (!data) {
- return
;
- }
-
- const sensorData = data.find((item) => item.label === sensorName);
-
- if (!sensorData) {
- return
;
- }
-
- return (
- <>
-
- t("common.number", {
- value,
- })}
- />
-
-
- {sensorData && !error && (
- <>
- {sensorData.warning && (
-
- {sensorData.warning}{sensorData.unit} {t("glances.warn")}
-
- )}
- {sensorData.critical && (
-
- {sensorData.critical} {sensorData.unit} {t("glances.crit")}
-
- )}
- >
- )}
-
-
- {t("common.number", {
- value: sensorData.value,
- })} {sensorData.unit}
-
-
- >
- );
-}