diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 3cdf1b45..49a85047 100755 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -232,6 +232,10 @@ "stopped": "Stopped", "total": "Total" }, + "tailscale": { + "private_ip": "Private IP", + "status": "Status" + }, "tdarr": { "queue": "Queue", "processed": "Processed", diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js index 93cdb995..5d4b7e3b 100644 --- a/src/utils/proxy/handlers/credentialed.js +++ b/src/utils/proxy/handlers/credentialed.js @@ -32,6 +32,7 @@ export default async function credentialedProxyHandler(req, res, map) { "authentik", "cloudflared", "ghostfolio", + "tailscale", "truenas", "pterodactyl", ].includes(widget.type)) diff --git a/src/widgets/components.js b/src/widgets/components.js index f8828f3b..c909bfe0 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -71,6 +71,7 @@ const components = { sonarr: dynamic(() => import("./sonarr/component")), speedtest: dynamic(() => import("./speedtest/component")), strelaysrv: dynamic(() => import("./strelaysrv/component")), + tailscale: dynamic(() => import("./tailscale/component")), tautulli: dynamic(() => import("./tautulli/component")), tdarr: dynamic(() => import("./tdarr/component")), traefik: dynamic(() => import("./traefik/component")), diff --git a/src/widgets/tailscale/component.jsx b/src/widgets/tailscale/component.jsx new file mode 100644 index 00000000..e80f9e8c --- /dev/null +++ b/src/widgets/tailscale/component.jsx @@ -0,0 +1,37 @@ +import Container from "components/services/widget/container"; +import Block from "components/services/widget/block"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +export default function Component({ service }) { + const { widget } = service; + + const { data: statsData, error: statsError } = useWidgetAPI(widget, "device"); + + if (statsError) { + return ; + } + + if (!statsData) { + return ( + + + + + ); + } + + const getStatus = () => { + const { endpoints, latency } = statsData.clientConnectivity + return (endpoints.length === 0 || Object.keys(latency).length === 0) ? "Offline" : "Online" + } + + + const privateIP = statsData.addresses[0] + + return ( + + + + + ); +} diff --git a/src/widgets/tailscale/widget.js b/src/widgets/tailscale/widget.js new file mode 100644 index 00000000..7891ca80 --- /dev/null +++ b/src/widgets/tailscale/widget.js @@ -0,0 +1,14 @@ +import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; + +const widget = { + api: "https://api.tailscale.com/api/v2/{endpoint}/{deviceid}?fields=all", + proxyHandler: credentialedProxyHandler, + + mappings: { + device: { + endpoint: "device" + }, + }, +}; + +export default widget; \ No newline at end of file diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 9e155383..20f36a2b 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -65,6 +65,7 @@ import scrutiny from "./scrutiny/widget"; import sonarr from "./sonarr/widget"; import speedtest from "./speedtest/widget"; import strelaysrv from "./strelaysrv/widget"; +import tailscale from "./tailscale/widget"; import tautulli from "./tautulli/widget"; import tdarr from "./tdarr/widget"; import traefik from "./traefik/widget"; @@ -147,6 +148,7 @@ const widgets = { sonarr, speedtest, strelaysrv, + tailscale, tautulli, tdarr, traefik,