From 3acbdda45efc3bd21498828cbfb6a5244a73d79d Mon Sep 17 00:00:00 2001
From: Jon Maddox <jon@jonmaddox.com>
Date: Wed, 19 Apr 2023 16:24:02 -0400
Subject: [PATCH] add Channels DVR Server widget

---
 public/locales/en/common.json               |  6 ++++
 src/widgets/channelsdvrserver/component.jsx | 36 +++++++++++++++++++++
 src/widgets/channelsdvrserver/widget.js     | 14 ++++++++
 src/widgets/components.js                   |  1 +
 src/widgets/widgets.js                      |  4 ++-
 5 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 src/widgets/channelsdvrserver/component.jsx
 create mode 100644 src/widgets/channelsdvrserver/widget.js

diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index adcda8ff..2da02110 100755
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -106,6 +106,12 @@
         "totalObserved": "Total Observed",
         "diffsDetected": "Diffs Detected"
     },
+    "channelsdvrserver": {
+        "shows": "Shows",
+        "recordings": "Recordings",
+        "scheduled": "Scheduled",
+        "passes": "Passes"
+    },
     "tautulli": {
         "playing": "Playing",
         "transcoding": "Transcoding",
diff --git a/src/widgets/channelsdvrserver/component.jsx b/src/widgets/channelsdvrserver/component.jsx
new file mode 100644
index 00000000..d989c9a8
--- /dev/null
+++ b/src/widgets/channelsdvrserver/component.jsx
@@ -0,0 +1,36 @@
+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";
+
+export default function Component({ service }) {
+  const { t } = useTranslation();
+  const { widget } = service;
+
+  const { data: channelsData, error: channelsError } = useWidgetAPI(widget, "status");
+
+  if (channelsError) {
+    return <Container error={channelsError} />;
+  }
+
+  if (!channelsData) {
+    return (
+      <Container service={service}>
+        <Block label="channelsdvrserver.shows" />
+        <Block label="channelsdvrserver.recordings" />
+        <Block label="channelsdvrserver.scheduled" />
+        <Block label="channelsdvrserver.passes" />
+      </Container>
+    );
+  }
+
+  return (
+    <Container service={service}>
+      <Block label="channelsdvrserver.shows" value={t("common.number", { value: channelsData.stats.groups })} />
+      <Block label="channelsdvrserver.recordings" value={t("common.number", { value: channelsData.stats.files })} />
+      <Block label="channelsdvrserver.scheduled" value={t("common.number", { value: channelsData.stats.jobs })} />
+      <Block label="channelsdvrserver.passes" value={t("common.number", { value: channelsData.stats.rules })} />
+    </Container>
+  );
+}
diff --git a/src/widgets/channelsdvrserver/widget.js b/src/widgets/channelsdvrserver/widget.js
new file mode 100644
index 00000000..bb945892
--- /dev/null
+++ b/src/widgets/channelsdvrserver/widget.js
@@ -0,0 +1,14 @@
+import genericProxyHandler from "utils/proxy/handlers/generic";
+
+const widget = {
+  api: "{url}/{endpoint}",
+  proxyHandler: genericProxyHandler,
+
+  mappings: {
+    status: {
+      endpoint: "dvr",
+    },
+  },
+};
+
+export default widget;
diff --git a/src/widgets/components.js b/src/widgets/components.js
index 6ca5722e..67338332 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -7,6 +7,7 @@ const components = {
   autobrr: dynamic(() => import("./autobrr/component")),
   bazarr: dynamic(() => import("./bazarr/component")),
   changedetectionio: dynamic(() => import("./changedetectionio/component")),
+  channelsdvrserver: dynamic(() => import("./channelsdvrserver/component")),
   cloudflared: dynamic(() => import("./cloudflared/component")),
   coinmarketcap: dynamic(() => import("./coinmarketcap/component")),
   deluge: dynamic(() => import("./deluge/component")),
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index dca03173..9878d50d 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -4,6 +4,7 @@ import authentik from "./authentik/widget";
 import autobrr from "./autobrr/widget";
 import bazarr from "./bazarr/widget";
 import changedetectionio from "./changedetectionio/widget";
+import channelsdvrserver from "./channelsdvrserver/widget";
 import cloudflared from "./cloudflared/widget";
 import coinmarketcap from "./coinmarketcap/widget";
 import deluge from "./deluge/widget";
@@ -13,7 +14,7 @@ import emby from "./emby/widget";
 import fileflows from "./fileflows/widget";
 import flood from "./flood/widget";
 import freshrss from "./freshrss/widget";
-import ghostfolio from "./ghostfolio/widget"
+import ghostfolio from "./ghostfolio/widget";
 import gluetun from "./gluetun/widget";
 import gotify from "./gotify/widget";
 import grafana from "./grafana/widget";
@@ -83,6 +84,7 @@ const widgets = {
   autobrr,
   bazarr,
   changedetectionio,
+  channelsdvrserver,
   cloudflared,
   coinmarketcap,
   deluge,