mirror of
https://github.com/karl0ss/homepage.git
synced 2025-04-29 12:03:41 +01:00
Enhancement: resources network widget (#4327)
This commit is contained in:
parent
a06964dd17
commit
897309a47c
@ -175,6 +175,7 @@ data:
|
|||||||
expanded: true
|
expanded: true
|
||||||
cpu: true
|
cpu: true
|
||||||
memory: true
|
memory: true
|
||||||
|
network: default
|
||||||
- search:
|
- search:
|
||||||
provider: duckduckgo
|
provider: duckduckgo
|
||||||
target: _blank
|
target: _blank
|
||||||
@ -370,7 +371,7 @@ prevent unnecessary re-renders on page loads and window / tab focusing. The
|
|||||||
procedure for enabling sticky sessions depends on your Ingress controller. Below
|
procedure for enabling sticky sessions depends on your Ingress controller. Below
|
||||||
is an example using Traefik as the Ingress controller.
|
is an example using Traefik as the Ingress controller.
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: IngressRoute
|
kind: IngressRoute
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -24,9 +24,10 @@ _Note: unfortunately, the package used for getting CPU temp ([systeminformation]
|
|||||||
tempmin: 0 # optional, minimum cpu temp
|
tempmin: 0 # optional, minimum cpu temp
|
||||||
tempmax: 100 # optional, maximum cpu temp
|
tempmax: 100 # optional, maximum cpu temp
|
||||||
uptime: true
|
uptime: true
|
||||||
units: imperial # only used by cpu temp
|
units: imperial # only used by cpu temp, options: 'imperial' or 'metric'
|
||||||
refresh: 3000 # optional, in ms
|
refresh: 3000 # optional, in ms
|
||||||
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
|
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
|
||||||
|
network: true # optional, uses 'default' if true or specify a network interface name
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also pass a `label` option, which allows you to group resources under named sections,
|
You can also pass a `label` option, which allows you to group resources under named sections,
|
||||||
|
47
src/components/widgets/resources/network.jsx
Normal file
47
src/components/widgets/resources/network.jsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import useSWR from "swr";
|
||||||
|
import { FaNetworkWired } from "react-icons/fa";
|
||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
|
import Resource from "../widget/resource";
|
||||||
|
import Error from "../widget/error";
|
||||||
|
|
||||||
|
export default function Network({ options, refresh = 1500 }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
if (options.network === true) options.network = "default";
|
||||||
|
|
||||||
|
const { data, error } = useSWR(`/api/widgets/resources?type=network&interfaceName=${options.network}`, {
|
||||||
|
refreshInterval: refresh,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error || data?.error) {
|
||||||
|
return <Error />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data || !data.network) {
|
||||||
|
return (
|
||||||
|
<Resource
|
||||||
|
icon={FaNetworkWired}
|
||||||
|
value="- ↑"
|
||||||
|
label="- ↓"
|
||||||
|
expandedValue="- ↑"
|
||||||
|
expandedLabel="- ↓"
|
||||||
|
percentage="0"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Resource
|
||||||
|
icon={FaNetworkWired}
|
||||||
|
value={`${t("common.byterate", { value: data.network.tx_sec })} ↑`}
|
||||||
|
label={`${t("common.byterate", { value: data.network.rx_sec })} ↓`}
|
||||||
|
expandedValue={`${t("common.bytes", { value: data.network.tx_bytes })} ↑`}
|
||||||
|
expandedLabel={`${t("common.bytes", { value: data.network.rx_bytes })} ↓`}
|
||||||
|
expanded={options.expanded}
|
||||||
|
wide
|
||||||
|
percentage={(100 * data.network.rx_sec) / (data.network.rx_sec + data.network.tx_sec)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -6,6 +6,7 @@ import Cpu from "./cpu";
|
|||||||
import Memory from "./memory";
|
import Memory from "./memory";
|
||||||
import CpuTemp from "./cputemp";
|
import CpuTemp from "./cputemp";
|
||||||
import Uptime from "./uptime";
|
import Uptime from "./uptime";
|
||||||
|
import Network from "./network";
|
||||||
|
|
||||||
export default function Resources({ options }) {
|
export default function Resources({ options }) {
|
||||||
const { expanded, units, diskUnits, tempmin, tempmax } = options;
|
const { expanded, units, diskUnits, tempmin, tempmax } = options;
|
||||||
@ -23,6 +24,7 @@ export default function Resources({ options }) {
|
|||||||
<Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />
|
<Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />
|
||||||
))
|
))
|
||||||
: options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />}
|
: options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />}
|
||||||
|
{options.network && <Network options={options} refresh={refresh} />}
|
||||||
{options.cputemp && (
|
{options.cputemp && (
|
||||||
<CpuTemp expanded={expanded} units={units} refresh={refresh} tempmin={tempmin} tempmax={tempmax} />
|
<CpuTemp expanded={expanded} units={units} refresh={refresh} tempmin={tempmin} tempmax={tempmax} />
|
||||||
)}
|
)}
|
||||||
|
@ -10,6 +10,7 @@ export default function Resource({
|
|||||||
percentage,
|
percentage,
|
||||||
expanded = false,
|
expanded = false,
|
||||||
additionalClassNames = "",
|
additionalClassNames = "",
|
||||||
|
wide = false,
|
||||||
}) {
|
}) {
|
||||||
const Icon = icon;
|
const Icon = icon;
|
||||||
|
|
||||||
@ -18,7 +19,11 @@ export default function Resource({
|
|||||||
className={`flex-none flex flex-row items-center mr-3 py-1.5 information-widget-resource ${additionalClassNames}`}
|
className={`flex-none flex flex-row items-center mr-3 py-1.5 information-widget-resource ${additionalClassNames}`}
|
||||||
>
|
>
|
||||||
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon" />
|
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon" />
|
||||||
<div className={`flex flex-col ml-3 text-left min-w-[85px] ${expanded ? " expanded" : ""}`}>
|
<div
|
||||||
|
className={`flex flex-col ml-3 text-left ${expanded ? " expanded" : ""} ${
|
||||||
|
wide ? " min-w-[120px]" : "min-w-[85px]"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
|
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
|
||||||
<div className="pl-0.5">{value}</div>
|
<div className="pl-0.5">{value}</div>
|
||||||
<div className="pr-1">{label}</div>
|
<div className="pr-1">{label}</div>
|
||||||
|
@ -7,7 +7,7 @@ const logger = createLogger("resources");
|
|||||||
const si = require("systeminformation");
|
const si = require("systeminformation");
|
||||||
|
|
||||||
export default async function handler(req, res) {
|
export default async function handler(req, res) {
|
||||||
const { type, target } = req.query;
|
const { type, target, interfaceName = "default" } = req.query;
|
||||||
|
|
||||||
if (type === "cpu") {
|
if (type === "cpu") {
|
||||||
const load = await si.currentLoad();
|
const load = await si.currentLoad();
|
||||||
@ -57,6 +57,32 @@ export default async function handler(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === "network") {
|
||||||
|
let networkData = await si.networkStats();
|
||||||
|
let interfaceDefault;
|
||||||
|
logger.debug("networkData:", JSON.stringify(networkData));
|
||||||
|
if (interfaceName && interfaceName !== "default") {
|
||||||
|
networkData = networkData.filter((network) => network.iface === interfaceName).at(0);
|
||||||
|
if (!networkData) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: "Interface not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
interfaceDefault = await si.networkInterfaceDefault();
|
||||||
|
networkData = networkData.filter((network) => network.iface === interfaceDefault).at(0);
|
||||||
|
if (!networkData) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: "Default interface not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.status(200).json({
|
||||||
|
network: networkData,
|
||||||
|
interface: interfaceName !== "default" ? interfaceName : interfaceDefault,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
error: "invalid type",
|
error: "invalid type",
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user