mirror of
https://github.com/karl0ss/homepage.git
synced 2025-05-02 05:23:39 +01:00
Feature: Technitium DNS Widget (#3904)
--------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
parent
e2518b37d9
commit
4c6150a545
@ -113,6 +113,7 @@ You can also find a list of all available service widgets in the sidebar navigat
|
|||||||
- [Syncthing Relay Server](syncthing-relay-server.md)
|
- [Syncthing Relay Server](syncthing-relay-server.md)
|
||||||
- [Tailscale](tailscale.md)
|
- [Tailscale](tailscale.md)
|
||||||
- [Tandoor](tandoor.md)
|
- [Tandoor](tandoor.md)
|
||||||
|
- [Technitium DNS](technitium.md)
|
||||||
- [TDarr](tdarr.md)
|
- [TDarr](tdarr.md)
|
||||||
- [Traefik](traefik.md)
|
- [Traefik](traefik.md)
|
||||||
- [Transmission](transmission.md)
|
- [Transmission](transmission.md)
|
||||||
|
26
docs/widgets/services/technitium.md
Normal file
26
docs/widgets/services/technitium.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
title: Technitium DNS Server
|
||||||
|
description: Technitium DNS Server Widget Configuration
|
||||||
|
---
|
||||||
|
|
||||||
|
Learn more about [Technitium DNS Server](https://technitium.com/dns/).
|
||||||
|
|
||||||
|
Allowed fields (up to 4): `["totalQueries","totalNoError","totalServerFailure","totalNxDomain","totalRefused","totalAuthoritative","totalRecursive","totalCached","totalBlocked","totalDropped","totalClients"]`.
|
||||||
|
|
||||||
|
Defaults to: `["totalQueries", "totalAuthoritative", "totalCached", "totalServerFailure"]`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
widget:
|
||||||
|
type: technitium
|
||||||
|
url: <url to dns server>
|
||||||
|
key: biglongapitoken
|
||||||
|
range: LastDay # optional, defaults to LastHour
|
||||||
|
```
|
||||||
|
|
||||||
|
#### API Key
|
||||||
|
|
||||||
|
This can be generated via the Technitium DNS Dashboard, and should be generated from a special API specific user.
|
||||||
|
|
||||||
|
#### Range
|
||||||
|
|
||||||
|
`range` value determines how far back of statistics to pull data for. The value comes directly from Technitium API documentation found [here](https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md#dashboard-api-calls), defined as `"type"`. The value can be one of: `LastHour`, `LastDay`, `LastWeek`, `LastMonth`, `LastYear`.
|
@ -137,6 +137,7 @@ nav:
|
|||||||
- widgets/services/syncthing-relay-server.md
|
- widgets/services/syncthing-relay-server.md
|
||||||
- widgets/services/tailscale.md
|
- widgets/services/tailscale.md
|
||||||
- widgets/services/tandoor.md
|
- widgets/services/tandoor.md
|
||||||
|
- widgets/services/technitium.md
|
||||||
- widgets/services/tdarr.md
|
- widgets/services/tdarr.md
|
||||||
- widgets/services/traefik.md
|
- widgets/services/traefik.md
|
||||||
- widgets/services/transmission.md
|
- widgets/services/transmission.md
|
||||||
|
@ -323,6 +323,19 @@
|
|||||||
"seconds": "{{number}}s",
|
"seconds": "{{number}}s",
|
||||||
"ago": "{{value}} Ago"
|
"ago": "{{value}} Ago"
|
||||||
},
|
},
|
||||||
|
"technitium": {
|
||||||
|
"totalQueries": "Queries",
|
||||||
|
"totalNoError": "Success",
|
||||||
|
"totalServerFailure": "Failures",
|
||||||
|
"totalNxDomain": "NX Domains",
|
||||||
|
"totalRefused": "Refused",
|
||||||
|
"totalAuthoritative": "Authoritative",
|
||||||
|
"totalRecursive": "Recursive",
|
||||||
|
"totalCached": "Cached",
|
||||||
|
"totalBlocked": "Blocked",
|
||||||
|
"totalDropped": "Dropped",
|
||||||
|
"totalClients": "Clients"
|
||||||
|
},
|
||||||
"tdarr": {
|
"tdarr": {
|
||||||
"queue": "Queue",
|
"queue": "Queue",
|
||||||
"processed": "Processed",
|
"processed": "Processed",
|
||||||
|
@ -473,6 +473,9 @@ export function cleanServiceGroups(groups) {
|
|||||||
|
|
||||||
// wgeasy
|
// wgeasy
|
||||||
threshold,
|
threshold,
|
||||||
|
|
||||||
|
// technitium
|
||||||
|
range,
|
||||||
} = cleanedService.widget;
|
} = cleanedService.widget;
|
||||||
|
|
||||||
let fieldsList = fields;
|
let fieldsList = fields;
|
||||||
@ -617,6 +620,9 @@ export function cleanServiceGroups(groups) {
|
|||||||
if (type === "frigate") {
|
if (type === "frigate") {
|
||||||
if (enableRecentEvents !== undefined) cleanedService.widget.enableRecentEvents = enableRecentEvents;
|
if (enableRecentEvents !== undefined) cleanedService.widget.enableRecentEvents = enableRecentEvents;
|
||||||
}
|
}
|
||||||
|
if (type === "technitium") {
|
||||||
|
if (range !== undefined) cleanedService.widget.range = range;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cleanedService;
|
return cleanedService;
|
||||||
|
@ -112,6 +112,7 @@ const components = {
|
|||||||
tailscale: dynamic(() => import("./tailscale/component")),
|
tailscale: dynamic(() => import("./tailscale/component")),
|
||||||
tandoor: dynamic(() => import("./tandoor/component")),
|
tandoor: dynamic(() => import("./tandoor/component")),
|
||||||
tautulli: dynamic(() => import("./tautulli/component")),
|
tautulli: dynamic(() => import("./tautulli/component")),
|
||||||
|
technitium: dynamic(() => import("./technitium/component")),
|
||||||
tdarr: dynamic(() => import("./tdarr/component")),
|
tdarr: dynamic(() => import("./tdarr/component")),
|
||||||
traefik: dynamic(() => import("./traefik/component")),
|
traefik: dynamic(() => import("./traefik/component")),
|
||||||
transmission: dynamic(() => import("./transmission/component")),
|
transmission: dynamic(() => import("./transmission/component")),
|
||||||
|
121
src/widgets/technitium/component.jsx
Normal file
121
src/widgets/technitium/component.jsx
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
|
import Container from "components/services/widget/container";
|
||||||
|
import Block from "components/services/widget/block";
|
||||||
|
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||||
|
|
||||||
|
const MAX_ALLOWED_FIELDS = 4;
|
||||||
|
|
||||||
|
export const technitiumDefaultFields = ["totalQueries", "totalAuthoritative", "totalCached", "totalServerFailure"];
|
||||||
|
|
||||||
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { widget } = service;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
type: widget.range ?? "LastHour",
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data: statsData, error: statsError } = useWidgetAPI(widget, "stats", params);
|
||||||
|
|
||||||
|
// Default fields
|
||||||
|
if (!widget.fields?.length > 0) {
|
||||||
|
widget.fields = technitiumDefaultFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limits max number of displayed fields
|
||||||
|
if (widget.fields?.length > MAX_ALLOWED_FIELDS) {
|
||||||
|
widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statsError) {
|
||||||
|
return <Container service={service} error={statsError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!statsData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="technitium.totalQueries" />
|
||||||
|
<Block label="technitium.totalNoError" />
|
||||||
|
<Block label="technitium.totalServerFailure" />
|
||||||
|
<Block label="technitium.totalNxDomain" />
|
||||||
|
<Block label="technitium.totalRefused" />
|
||||||
|
<Block label="technitium.totalAuthoritative" />
|
||||||
|
<Block label="technitium.totalRecursive" />
|
||||||
|
<Block label="technitium.totalCached" />
|
||||||
|
<Block label="technitium.totalBlocked" />
|
||||||
|
<Block label="technitium.totalDropped" />
|
||||||
|
<Block label="technitium.totalClients" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toPercent(value, total) {
|
||||||
|
return t("common.percent", {
|
||||||
|
value: !Number.isNaN(value / total) ? value / total : 0,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="technitium.totalQueries" value={`${t("common.number", { value: statsData.totalQueries })}`} />
|
||||||
|
<Block
|
||||||
|
label="technitium.totalNoError"
|
||||||
|
value={`${t("common.number", { value: statsData.totalNoError })} (${toPercent(
|
||||||
|
statsData.totalNoError / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalServerFailure"
|
||||||
|
value={`${t("common.number", { value: statsData.totalServerFailure })} (${toPercent(
|
||||||
|
statsData.totalServerFailure / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalNxDomain"
|
||||||
|
value={`${t("common.number", { value: statsData.totalNxDomain })} (${toPercent(
|
||||||
|
statsData.totalNxDomain / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalRefused"
|
||||||
|
value={`${t("common.number", { value: statsData.totalRefused })} (${toPercent(
|
||||||
|
statsData.totalRefused / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalAuthoritative"
|
||||||
|
value={`${t("common.number", { value: statsData.totalAuthoritative })} (${toPercent(
|
||||||
|
statsData.totalAuthoritative / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalRecursive"
|
||||||
|
value={`${t("common.number", { value: statsData.totalRecursive })} (${toPercent(
|
||||||
|
statsData.totalRecursive / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalCached"
|
||||||
|
value={`${t("common.number", { value: statsData.totalCached })} (${toPercent(
|
||||||
|
statsData.totalCached / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalBlocked"
|
||||||
|
value={`${t("common.number", { value: statsData.totalBlocked })} (${toPercent(
|
||||||
|
statsData.totalBlocked / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block
|
||||||
|
label="technitium.totalDropped"
|
||||||
|
value={`${t("common.number", { value: statsData.totalDropped })} (${toPercent(
|
||||||
|
statsData.totalDropped / statsData.totalQueries,
|
||||||
|
)})`}
|
||||||
|
/>
|
||||||
|
<Block label="technitium.totalClients" value={`${t("common.number", { value: statsData.totalClients })}`} />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
17
src/widgets/technitium/widget.js
Normal file
17
src/widgets/technitium/widget.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||||
|
import { asJson } from "utils/proxy/api-helpers";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
api: "{url}/api/{endpoint}?token={key}&utc=true",
|
||||||
|
proxyHandler: genericProxyHandler,
|
||||||
|
mappings: {
|
||||||
|
stats: {
|
||||||
|
endpoint: "dashboard/stats/get",
|
||||||
|
validate: ["response", "status"],
|
||||||
|
params: ["type"],
|
||||||
|
map: (data) => asJson(data).response.stats,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
@ -103,6 +103,7 @@ import swagdashboard from "./swagdashboard/widget";
|
|||||||
import tailscale from "./tailscale/widget";
|
import tailscale from "./tailscale/widget";
|
||||||
import tandoor from "./tandoor/widget";
|
import tandoor from "./tandoor/widget";
|
||||||
import tautulli from "./tautulli/widget";
|
import tautulli from "./tautulli/widget";
|
||||||
|
import technitium from "./technitium/widget";
|
||||||
import tdarr from "./tdarr/widget";
|
import tdarr from "./tdarr/widget";
|
||||||
import traefik from "./traefik/widget";
|
import traefik from "./traefik/widget";
|
||||||
import transmission from "./transmission/widget";
|
import transmission from "./transmission/widget";
|
||||||
@ -228,6 +229,7 @@ const widgets = {
|
|||||||
tailscale,
|
tailscale,
|
||||||
tandoor,
|
tandoor,
|
||||||
tautulli,
|
tautulli,
|
||||||
|
technitium,
|
||||||
tdarr,
|
tdarr,
|
||||||
traefik,
|
traefik,
|
||||||
transmission,
|
transmission,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user