From 551f521edd361e25b68831be20d80c2e54935e22 Mon Sep 17 00:00:00 2001
From: geckoflume <6378002+geckoflume@users.noreply.github.com>
Date: Sat, 4 Feb 2023 18:58:26 +0100
Subject: [PATCH 1/2] Add PhotoPrism widget
---
public/locales/en/common.json | 6 ++++
src/widgets/components.js | 1 +
src/widgets/photoprism/component.jsx | 37 +++++++++++++++++++++
src/widgets/photoprism/proxy.js | 48 ++++++++++++++++++++++++++++
src/widgets/photoprism/widget.js | 7 ++++
src/widgets/widgets.js | 2 ++
6 files changed, 101 insertions(+)
create mode 100644 src/widgets/photoprism/component.jsx
create mode 100644 src/widgets/photoprism/proxy.js
create mode 100644 src/widgets/photoprism/widget.js
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index a653b41f..2c0e1dfc 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -465,5 +465,11 @@
"series": "Series",
"issues": "Issues",
"wanted": "Wanted"
+ },
+ "photoprism": {
+ "albums": "Albums",
+ "photos": "Photos",
+ "videos": "Videos",
+ "people": "People"
}
}
\ No newline at end of file
diff --git a/src/widgets/components.js b/src/widgets/components.js
index d28a28c0..4948d002 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -39,6 +39,7 @@ const components = {
opnsense: dynamic(() => import("./opnsense/component")),
overseerr: dynamic(() => import("./overseerr/component")),
paperlessngx: dynamic(() => import("./paperlessngx/component")),
+ photoprism: dynamic(() => import("./photoprism/component")),
proxmoxbackupserver: dynamic(() => import("./proxmoxbackupserver/component")),
pihole: dynamic(() => import("./pihole/component")),
plex: dynamic(() => import("./plex/component")),
diff --git a/src/widgets/photoprism/component.jsx b/src/widgets/photoprism/component.jsx
new file mode 100644
index 00000000..1a679cd9
--- /dev/null
+++ b/src/widgets/photoprism/component.jsx
@@ -0,0 +1,37 @@
+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: photoprismData, error: photoprismError } = useWidgetAPI(widget);
+
+ if (photoprismError) {
+ return ;
+ }
+
+ if (!photoprismData) {
+ return (
+
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/src/widgets/photoprism/proxy.js b/src/widgets/photoprism/proxy.js
new file mode 100644
index 00000000..af133044
--- /dev/null
+++ b/src/widgets/photoprism/proxy.js
@@ -0,0 +1,48 @@
+import { formatApiCall } from "utils/proxy/api-helpers";
+import { httpProxy } from "utils/proxy/http";
+import getServiceWidget from "utils/config/service-helpers";
+import createLogger from "utils/logger";
+
+const logger = createLogger("photoprismProxyHandler");
+
+export default async function photoprismProxyHandler(req, res) {
+ const { group, service, endpoint } = req.query;
+
+ if (!group || !service) {
+ logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
+ return res.status(400).json({ error: "Invalid proxy service type" });
+ }
+
+ const widget = await getServiceWidget(group, service);
+
+ if (!widget) {
+ logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
+ return res.status(400).json({ error: "Invalid proxy service type" });
+ }
+
+ const url = new URL(formatApiCall("{url}/api/v1/session", { endpoint, ...widget }));
+ const params = {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: null
+ };
+
+ if (widget.username && widget.password) {
+ params.body = JSON.stringify({
+ "username": widget.username,
+ "password": widget.password
+ });
+ }
+
+ let [status, contentType, data] = await httpProxy(url, params);
+
+ if (status !== 200) {
+ logger.error("HTTP %d getting data from PhotoPrism. Data: %s", status, data);
+ return res.status(status).json({error: {message: `HTTP Error ${status}`, url, data}});
+ }
+
+ const json = JSON.parse(data.toString())
+
+ if (contentType) res.setHeader("Content-Type", contentType);
+ return res.status(200).send(json?.config?.count);
+}
diff --git a/src/widgets/photoprism/widget.js b/src/widgets/photoprism/widget.js
new file mode 100644
index 00000000..eaddbcc9
--- /dev/null
+++ b/src/widgets/photoprism/widget.js
@@ -0,0 +1,7 @@
+import photoprismProxyHandler from "./proxy";
+
+const widget = {
+ proxyHandler: photoprismProxyHandler,
+};
+
+export default widget;
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index 47b5e988..2e244331 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -33,6 +33,7 @@ import ombi from "./ombi/widget";
import opnsense from "./opnsense/widget";
import overseerr from "./overseerr/widget";
import paperlessngx from "./paperlessngx/widget";
+import photoprism from "./photoprism/widget";
import proxmoxbackupserver from "./proxmoxbackupserver/widget";
import pihole from "./pihole/widget";
import plex from "./plex/widget";
@@ -99,6 +100,7 @@ const widgets = {
opnsense,
overseerr,
paperlessngx,
+ photoprism,
proxmoxbackupserver,
pihole,
plex,
From a226f9de1217ee94bfabad30c16609c7784ca5a8 Mon Sep 17 00:00:00 2001
From: shamoon <4887959+shamoon@users.noreply.github.com>
Date: Sun, 5 Feb 2023 22:01:12 -0800
Subject: [PATCH 2/2] remove folders, unused vars
---
src/widgets/photoprism/component.jsx | 2 +-
src/widgets/photoprism/proxy.js | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/widgets/photoprism/component.jsx b/src/widgets/photoprism/component.jsx
index 1a679cd9..ee489d35 100644
--- a/src/widgets/photoprism/component.jsx
+++ b/src/widgets/photoprism/component.jsx
@@ -28,7 +28,7 @@ export default function Component({ service }) {
return (
-
+
diff --git a/src/widgets/photoprism/proxy.js b/src/widgets/photoprism/proxy.js
index af133044..eba398dc 100644
--- a/src/widgets/photoprism/proxy.js
+++ b/src/widgets/photoprism/proxy.js
@@ -6,7 +6,7 @@ import createLogger from "utils/logger";
const logger = createLogger("photoprismProxyHandler");
export default async function photoprismProxyHandler(req, res) {
- const { group, service, endpoint } = req.query;
+ const { group, service } = req.query;
if (!group || !service) {
logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
@@ -20,7 +20,7 @@ export default async function photoprismProxyHandler(req, res) {
return res.status(400).json({ error: "Invalid proxy service type" });
}
- const url = new URL(formatApiCall("{url}/api/v1/session", { endpoint, ...widget }));
+ const url = new URL(formatApiCall("{url}/api/v1/session", { ...widget }));
const params = {
method: "POST",
headers: { "Content-Type": "application/json" },
@@ -37,7 +37,7 @@ export default async function photoprismProxyHandler(req, res) {
let [status, contentType, data] = await httpProxy(url, params);
if (status !== 200) {
- logger.error("HTTP %d getting data from PhotoPrism. Data: %s", status, data);
+ logger.error("HTTP %d getting data from PhotoPrism. Data: %s", status, data);
return res.status(status).json({error: {message: `HTTP Error ${status}`, url, data}});
}