diff --git a/docs/widgets/services/gatus.md b/docs/widgets/services/gatus.md new file mode 100644 index 000000000..3918b9f3d --- /dev/null +++ b/docs/widgets/services/gatus.md @@ -0,0 +1,12 @@ +--- +title: Gatus +description: Gatus Widget Configuration +--- + +Allowed fields: `["up", "down", "uptime"]`. + +```yaml +widget: + type: gatus + url: http://gatus.host.or.ip:port +``` diff --git a/mkdocs.yml b/mkdocs.yml index a9beba06e..572d36b4c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -55,6 +55,7 @@ nav: - widgets/services/freshrss.md - widgets/services/fritzbox.md - widgets/services/gamedig.md + - widgets/services/gatus.md - widgets/services/ghostfolio.md - widgets/services/glances.md - widgets/services/gluetun.md diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2192a7de7..b0f60a6d4 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -694,6 +694,11 @@ "targets_down": "Targets Down", "targets_total": "Total Targets" }, + "gatus": { + "up": "Sites Up", + "down": "Sites Down", + "uptime": "Uptime" + }, "ghostfolio": { "gross_percent_today": "Today", "gross_percent_1y": "One year", diff --git a/src/widgets/components.js b/src/widgets/components.js index 3cdfc261a..497d64077 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -29,6 +29,7 @@ const components = { freshrss: dynamic(() => import("./freshrss/component")), fritzbox: dynamic(() => import("./fritzbox/component")), gamedig: dynamic(() => import("./gamedig/component")), + gatus: dynamic(() => import("./gatus/component")), ghostfolio: dynamic(() => import("./ghostfolio/component")), glances: dynamic(() => import("./glances/component")), gluetun: dynamic(() => import("./gluetun/component")), diff --git a/src/widgets/gatus/component.jsx b/src/widgets/gatus/component.jsx new file mode 100644 index 000000000..86b85ff3b --- /dev/null +++ b/src/widgets/gatus/component.jsx @@ -0,0 +1,51 @@ +import { useTranslation } from "next-i18next"; + +import Container from "components/services/widget/container"; +import useWidgetAPI from "utils/proxy/use-widget-api"; +import Block from "components/services/widget/block"; + +export default function Component({ service }) { + const { t } = useTranslation(); + + const { widget } = service; + + const { data: statusData, error: statusError } = useWidgetAPI(widget, "status"); + + if (statusError) { + return ; + } + + if (!statusData) { + return ( + + + + + + ); + } + + let sitesUp = 0; + let sitesDown = 0; + Object.values(statusData).forEach((site) => { + const lastResult = site.results[site.results.length - 1]; + if (lastResult?.success === true) { + sitesUp += 1; + } else { + sitesDown += 1; + } + }); + + // Adapted from https://github.com/bastienwirtz/homer/blob/b7cd8f9482e6836a96b354b11595b03b9c3d67cd/src/components/services/UptimeKuma.vue#L105 + const resultsList = Object.values(statusData).reduce((a, b) => a.concat(b.results), []); + const percent = resultsList.reduce((a, b) => a + (b?.success === true ? 1 : 0), 0) / resultsList.length; + const uptime = (percent * 100).toFixed(1); + + return ( + + + + + + ); +} diff --git a/src/widgets/gatus/widget.js b/src/widgets/gatus/widget.js new file mode 100644 index 000000000..8963ac199 --- /dev/null +++ b/src/widgets/gatus/widget.js @@ -0,0 +1,15 @@ +// import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; +import genericProxyHandler from "utils/proxy/handlers/generic"; + +const widget = { + api: "{url}/{endpoint}", + proxyHandler: genericProxyHandler, + + mappings: { + status: { + endpoint: "api/v1/endpoints/statuses", + }, + }, +}; + +export default widget; diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 128a7dedf..553ce626a 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -23,6 +23,7 @@ import flood from "./flood/widget"; import freshrss from "./freshrss/widget"; import fritzbox from "./fritzbox/widget"; import gamedig from "./gamedig/widget"; +import gatus from "./gatus/widget"; import ghostfolio from "./ghostfolio/widget"; import glances from "./glances/widget"; import gluetun from "./gluetun/widget"; @@ -128,6 +129,7 @@ const widgets = { freshrss, fritzbox, gamedig, + gatus, ghostfolio, glances, gluetun,