diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index c8cb23f5..812f497c 100755
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -535,5 +535,11 @@
"targets_up": "Targets Up",
"targets_down": "Targets Down",
"targets_total": "Total Targets"
+ },
+ "ghostfolio": {
+ "gross_percent_today": "Today",
+ "gross_percent_ytd": "This year",
+ "gross_percent_1y": "One year",
+ "gross_percent_max": "All time"
}
}
diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js
index b29443c2..75b9d8f3 100644
--- a/src/utils/proxy/handlers/credentialed.js
+++ b/src/utils/proxy/handlers/credentialed.js
@@ -47,6 +47,8 @@ export default async function credentialedProxyHandler(req, res, map) {
headers.Authorization = `Bearer ${widget.key}`;
} else if (widget.type === "pterodactyl") {
headers.Authorization = `Bearer ${widget.key}`;
+ } else if (widget.type === "ghostfolio") {
+ headers.Authorization = `Bearer ${widget.key}`;
} else {
headers["X-API-Key"] = `${widget.key}`;
}
diff --git a/src/widgets/components.js b/src/widgets/components.js
index bb96b901..cfd3d665 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -16,6 +16,7 @@ const components = {
emby: dynamic(() => import("./emby/component")),
fileflows: dynamic(() => import("./fileflows/component")),
flood: dynamic(() => import("./flood/component")),
+ ghostfolio: dynamic(() => import("./ghostfolio/component")),
gluetun: dynamic(() => import("./gluetun/component")),
gotify: dynamic(() => import("./gotify/component")),
grafana: dynamic(() => import("./grafana/component")),
diff --git a/src/widgets/ghostfolio/component.jsx b/src/widgets/ghostfolio/component.jsx
new file mode 100644
index 00000000..d6314991
--- /dev/null
+++ b/src/widgets/ghostfolio/component.jsx
@@ -0,0 +1,45 @@
+
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
+import useWidgetAPI from "utils/proxy/use-widget-api";
+// import { useTranslation } from "next-i18next";
+
+export default function Component({ service }) {
+ // const { t } = useTranslation();
+
+ const { widget } = service;
+
+ const { data: performanceToday, error: ghostfolioErrorToday } = useWidgetAPI(widget, "today");
+ const { data: performanceYtd, error: ghostfolioErrorYtd } = useWidgetAPI(widget, "ytd", { refreshInterval: 36000 });
+ const { data: performanceYear, error: ghostfolioErrorYear } = useWidgetAPI(widget, "year", { refreshInterval: 36000 });
+ const { data: performanceMax, error: ghostfolioErrorMax } = useWidgetAPI(widget, "max", { refreshInterval: 36000 });
+
+ if (ghostfolioErrorToday) {
+ return ;
+ }
+
+ if (ghostfolioErrorYtd) {
+ return ;
+ }
+
+ if (ghostfolioErrorYear) {
+ return ;
+ }
+
+ if (ghostfolioErrorMax) {
+ return ;
+ }
+
+ return (
+
+ {/*
+
+
+ */}
+ 0 ? "+" : "")}${(Math.round(performanceToday.performance.currentGrossPerformancePercent * 10000) / 100)}%` || false} />
+ 0 ? "+" : "")}${(Math.round(performanceYtd.performance.currentGrossPerformancePercent * 10000) / 100)}%` || false} />
+ 0 ? "+" : "")}${(Math.round(performanceYear.performance.currentGrossPerformancePercent * 10000) / 100)}%` || false} />
+ 0 ? "+" : "")}${(Math.round(performanceMax.performance.currentGrossPerformancePercent * 10000) / 100)}%` || false} />
+
+ );
+}
diff --git a/src/widgets/ghostfolio/widget.js b/src/widgets/ghostfolio/widget.js
new file mode 100644
index 00000000..1c790474
--- /dev/null
+++ b/src/widgets/ghostfolio/widget.js
@@ -0,0 +1,23 @@
+import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
+
+const widget = {
+ api: "{url}/api/v2/portfolio/performance?range={endpoint}",
+ proxyHandler: credentialedProxyHandler,
+
+ mappings: {
+ today: {
+ endpoint: "1d"
+ },
+ ytd: {
+ endpoint: "ytd"
+ },
+ year: {
+ endpoint: "1y"
+ },
+ max: {
+ endpoint: "max"
+ },
+ },
+};
+
+export default widget;
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index 4e537cd6..0716c1d6 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -11,6 +11,7 @@ import downloadstation from "./downloadstation/widget";
import emby from "./emby/widget";
import fileflows from "./fileflows/widget";
import flood from "./flood/widget";
+import ghostfolio from "./ghostfolio/widget"
import gluetun from "./gluetun/widget";
import gotify from "./gotify/widget";
import grafana from "./grafana/widget";
@@ -86,6 +87,7 @@ const widgets = {
emby,
fileflows,
flood,
+ ghostfolio,
gluetun,
gotify,
grafana,