@@ -192,18 +173,6 @@ const headerStyles = {
boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1",
};
-function getAllServices(services) {
- function getServices(group) {
- let nestedServices = [...group.services];
- if (group.groups.length > 0) {
- nestedServices = [...nestedServices, ...group.groups.map(getServices).flat()];
- }
- return nestedServices;
- }
-
- return [...services.map(getServices).flat()];
-}
-
function Home({ initialSettings, identityContext }) {
const { i18n } = useTranslation();
const { theme, setTheme } = useContext(ThemeContext);
@@ -220,9 +189,10 @@ function Home({ initialSettings, identityContext }) {
const { data: bookmarks } = useSWR(["/api/bookmarks", identityContext], fetchWithIdentity);
const { data: widgets } = useSWR(["/api/widgets", identityContext], fetchWithIdentity);
- const servicesAndBookmarks = [...bookmarks.map((bg) => bg.bookmarks).flat(), ...getAllServices(services)].filter(
- (i) => i?.href,
- );
+ const servicesAndBookmarks = [
+ ...services.map((sg) => sg.services).flat(),
+ ...bookmarks.map((bg) => bg.bookmarks).flat(),
+ ].filter((i) => i?.href);
useEffect(() => {
if (settings.language) {
@@ -330,7 +300,7 @@ function Home({ initialSettings, identityContext }) {
key={group.name}
group={group}
layout={settings.layout?.[group.name]}
- maxGroupColumns={settings.fiveColumns ? 5 : settings.maxGroupColumns}
+ fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse}
useEqualHeights={settings.useEqualHeights}
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
@@ -341,7 +311,6 @@ function Home({ initialSettings, identityContext }) {
bookmarks={group}
layout={settings.layout?.[group.name]}
disableCollapse={settings.disableCollapse}
- maxGroupColumns={settings.maxBookmarkGroupColumns ?? settings.maxGroupColumns}
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
/>
),
@@ -355,7 +324,7 @@ function Home({ initialSettings, identityContext }) {
key={group.name}
group={group}
layout={settings.layout?.[group.name]}
- maxGroupColumns={settings.fiveColumns ? 5 : settings.maxGroupColumns}
+ fiveColumns={settings.fiveColumns}
disableCollapse={settings.disableCollapse}
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
/>
@@ -370,7 +339,6 @@ function Home({ initialSettings, identityContext }) {
bookmarks={group}
layout={settings.layout?.[group.name]}
disableCollapse={settings.disableCollapse}
- maxGroupColumns={settings.maxBookmarkGroupColumns ?? settings.maxGroupColumns}
groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed}
bookmarksStyle={settings.bookmarksStyle}
/>
@@ -386,8 +354,6 @@ function Home({ initialSettings, identityContext }) {
bookmarks,
settings.layout,
settings.fiveColumns,
- settings.maxGroupColumns,
- settings.maxBookmarkGroupColumns,
settings.disableCollapse,
settings.useEqualHeights,
settings.cardBlur,
@@ -428,12 +394,7 @@ function Home({ initialSettings, identityContext }) {
-
@@ -505,7 +466,7 @@ function Home({ initialSettings, identityContext }) {
}
export default function Wrapper({ initialSettings, fallback, identityContext }) {
- const { themeContext } = useContext(ThemeContext);
+ const { theme } = useContext(ThemeContext);
const wrappedStyle = {};
let backgroundBlur = false;
let backgroundSaturate = false;
@@ -536,9 +497,9 @@ export default function Wrapper({ initialSettings, fallback, identityContext })
id="page_wrapper"
className={classNames(
"relative",
- initialSettings.theme && initialSettings.theme,
+ theme && theme,
initialSettings.color && `theme-${initialSettings.color}`,
- themeContext === "dark" ? "scheme-dark" : "scheme-light",
+ theme === "dark" ? "scheme-dark" : "scheme-light",
)}
>
{
- if (typeof value === "object") {
- group.groups.push(convertLayoutGroupToGroup(key, value));
- }
- });
- }
- return group;
-}
-
function mergeSubgroups(configuredGroups, mergedGroup) {
configuredGroups.forEach((group) => {
if (group.name === mergedGroup.name) {
@@ -113,33 +101,6 @@ function mergeSubgroups(configuredGroups, mergedGroup) {
});
}
-function ensureParentGroupExists(sortedGroups, configuredGroups, group, definedLayouts) {
- // make sure the top level parent group exists in the sortedGroups array
- const parentGroupName = group.parent;
- const parentGroup = findGroupByName(configuredGroups, parentGroupName);
- if (parentGroup && parentGroup.parent) {
- ensureParentGroupExists(sortedGroups, configuredGroups, parentGroup);
- } else {
- const parentGroupIndex = definedLayouts.findIndex((layout) => layout === parentGroupName);
- if (parentGroupIndex > -1) {
- sortedGroups[parentGroupIndex] = parentGroup;
- }
- }
-}
-
-function pruneEmptyGroups(groups) {
- // remove any groups that have no services
- return groups.filter((group) => {
- if (group.services.length === 0 && group.groups.length === 0) {
- return false;
- }
- if (group.groups.length > 0) {
- group.groups = pruneEmptyGroups(group.groups);
- }
- return true;
- });
-}
-
export async function servicesResponse(perms, idGroups) {
let discoveredDockerServices;
let discoveredKubernetesServices;
@@ -198,17 +159,6 @@ export async function servicesResponse(perms, idGroups) {
const sortedGroups = [];
const unsortedGroups = [];
const definedLayouts = initialSettings.layout ? Object.keys(initialSettings.layout) : null;
- if (definedLayouts) {
- // this handles cases where groups are only defined in the settings.yaml layout and not in the services.yaml
- const layoutConfiguredGroups = Object.entries(initialSettings.layout).map(([key, value]) =>
- convertLayoutGroupToGroup(key, value),
- );
- layoutConfiguredGroups.forEach((group) => {
- if (!configuredServices.find((serviceGroup) => serviceGroup.name === group.name)) {
- configuredServices.push(group);
- }
- });
- }
mergedGroupsNames.forEach((groupName) => {
const discoveredDockerGroup = findGroupByName(discoveredDockerServices, groupName) || {
@@ -233,17 +183,11 @@ export async function servicesResponse(perms, idGroups) {
else if (configuredGroup.parent) {
// this is a nested group, so find the parent group and merge the services
mergeSubgroups(configuredServices, mergedGroup);
- // make sure the top level parent group exists in the sortedGroups array
- ensureParentGroupExists(sortedGroups, configuredServices, configuredGroup, definedLayouts);
} else unsortedGroups.push(mergedGroup);
- } else if (configuredGroup.parent) {
- // this is a nested group, so find the parent group and merge the services
- mergeSubgroups(configuredServices, mergedGroup);
} else {
unsortedGroups.push(mergedGroup);
}
});
- const allGroups = [...sortedGroups.filter((g) => g), ...unsortedGroups];
- return pruneEmptyGroups(allGroups);
+ return [...sortedGroups.filter((g) => g), ...unsortedGroups];
}
diff --git a/src/utils/config/config.js b/src/utils/config/config.js
index 3f688842..18dedf62 100644
--- a/src/utils/config/config.js
+++ b/src/utils/config/config.js
@@ -1,9 +1,9 @@
/* eslint-disable no-console */
-import { copyFileSync, existsSync, mkdirSync, readFileSync } from "fs";
import { join } from "path";
+import { copyFileSync, existsSync, mkdirSync, readFileSync } from "fs";
-import yaml from "js-yaml";
import cache from "memory-cache";
+import yaml from "js-yaml";
const cacheKey = "homepageEnvironmentVariables";
const homepageVarPrefix = "HOMEPAGE_VAR_";
diff --git a/src/utils/config/docker.js b/src/utils/config/docker.js
index ed1d3347..6ea728e9 100644
--- a/src/utils/config/docker.js
+++ b/src/utils/config/docker.js
@@ -1,5 +1,5 @@
-import { readFileSync } from "fs";
import path from "path";
+import { readFileSync } from "fs";
import yaml from "js-yaml";
diff --git a/src/utils/config/kubernetes.js b/src/utils/config/kubernetes.js
index 680c408e..6693a98d 100644
--- a/src/utils/config/kubernetes.js
+++ b/src/utils/config/kubernetes.js
@@ -1,22 +1,19 @@
-import { readFileSync } from "fs";
import path from "path";
+import { readFileSync } from "fs";
-import { ApiextensionsV1Api, KubeConfig } from "@kubernetes/client-node";
import yaml from "js-yaml";
+import { KubeConfig } from "@kubernetes/client-node";
import checkAndCopyConfig, { CONF_DIR, substituteEnvironmentVars } from "utils/config/config";
-export function getKubernetes() {
+export default function getKubeConfig() {
checkAndCopyConfig("kubernetes.yaml");
+
const configFile = path.join(CONF_DIR, "kubernetes.yaml");
const rawConfigData = readFileSync(configFile, "utf8");
const configData = substituteEnvironmentVars(rawConfigData);
- return yaml.load(configData);
-}
-
-export const getKubeConfig = () => {
+ const config = yaml.load(configData);
const kc = new KubeConfig();
- const config = getKubernetes();
switch (config?.mode) {
case "cluster":
@@ -31,31 +28,4 @@ export const getKubeConfig = () => {
}
return kc;
-};
-
-export async function checkCRD(name, kc, logger) {
- const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
- const exist = await apiExtensions
- .readCustomResourceDefinitionStatus({
- name,
- })
- .then(() => true)
- .catch(async (error) => {
- if (error.statusCode === 403) {
- logger.error(
- "Error checking if CRD %s exists. Make sure to add the following permission to your RBAC: %d %s %s",
- name,
- error.statusCode,
- error.body.message,
- );
- }
- return false;
- });
-
- return exist;
}
-
-export const ANNOTATION_BASE = "gethomepage.dev";
-export const ANNOTATION_WIDGET_BASE = `${ANNOTATION_BASE}/widget.`;
-export const HTTPROUTE_API_GROUP = "gateway.networking.k8s.io";
-export const HTTPROUTE_API_VERSION = "v1";
diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js
index 297e55a7..a4724eb7 100644
--- a/src/utils/config/service-helpers.js
+++ b/src/utils/config/service-helpers.js
@@ -1,15 +1,15 @@
import { promises as fs } from "fs";
import path from "path";
-import Docker from "dockerode";
import yaml from "js-yaml";
+import Docker from "dockerode";
+import { CustomObjectsApi, NetworkingV1Api, ApiextensionsV1Api } from "@kubernetes/client-node";
+import createLogger from "utils/logger";
import checkAndCopyConfig, { CONF_DIR, getSettings, substituteEnvironmentVars } from "utils/config/config";
import getDockerArguments from "utils/config/docker";
-import { getKubeConfig } from "utils/config/kubernetes";
+import getKubeConfig from "utils/config/kubernetes";
import * as shvl from "utils/config/shvl";
-import kubernetes from "utils/kubernetes/export";
-import createLogger from "utils/logger";
const logger = createLogger("service-helpers");
@@ -167,7 +167,36 @@ export async function servicesFromDocker() {
return mappedServiceGroups;
}
+function getUrlFromIngress(ingress) {
+ const urlHost = ingress.spec.rules[0].host;
+ const urlPath = ingress.spec.rules[0].http.paths[0].path;
+ const urlSchema = ingress.spec.tls ? "https" : "http";
+ return `${urlSchema}://${urlHost}${urlPath}`;
+}
+
+export async function checkCRD(kc, name) {
+ const apiExtensions = kc.makeApiClient(ApiextensionsV1Api);
+ const exist = await apiExtensions
+ .readCustomResourceDefinitionStatus(name)
+ .then(() => true)
+ .catch(async (error) => {
+ if (error.statusCode === 403) {
+ logger.error(
+ "Error checking if CRD %s exists. Make sure to add the following permission to your RBAC: %d %s %s",
+ name,
+ error.statusCode,
+ error.body.message,
+ );
+ }
+ return false;
+ });
+
+ return exist;
+}
+
export async function servicesFromKubernetes() {
+ const ANNOTATION_BASE = "gethomepage.dev";
+ const ANNOTATION_WIDGET_BASE = `${ANNOTATION_BASE}/widget.`;
const { instanceName } = getSettings();
checkAndCopyConfig("kubernetes.yaml");
@@ -177,46 +206,151 @@ export async function servicesFromKubernetes() {
if (!kc) {
return [];
}
+ const networking = kc.makeApiClient(NetworkingV1Api);
+ const crd = kc.makeApiClient(CustomObjectsApi);
- // resource lists
- const [ingressList, traefikIngressList, httpRouteList] = await Promise.all([
- kubernetes.listIngress(),
- kubernetes.listTraefikIngress(),
- kubernetes.listHttpRoute(),
- ]);
-
- const resources = [...ingressList, ...traefikIngressList, ...httpRouteList];
-
- if (!resources) {
- return [];
- }
- const services = await Promise.all(
- resources
- .filter((resource) => kubernetes.isDiscoverable(resource, instanceName))
- .map(async (resource) => kubernetes.constructedServiceFromResource(resource)),
- );
-
- // map service groups
- const mappedServiceGroups = services.reduce((groups, serverService) => {
- let serverGroup = groups.find((group) => group.name === serverService.group);
-
- if (!serverGroup) {
- serverGroup = {
- name: serverService.group,
- services: [],
- };
- groups.push(serverGroup);
- }
-
- const { name: serviceName, group: _, ...pushedService } = serverService;
-
- serverGroup.services.push({
- name: serviceName,
- ...pushedService,
+ const ingressList = await networking
+ .listIngressForAllNamespaces(null, null, null, null)
+ .then((response) => response.body)
+ .catch((error) => {
+ logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response);
+ logger.debug(error);
+ return null;
});
- return groups;
- }, []);
+ const traefikContainoExists = await checkCRD(kc, "ingressroutes.traefik.containo.us");
+ const traefikExists = await checkCRD(kc, "ingressroutes.traefik.io");
+
+ const traefikIngressListContaino = await crd
+ .listClusterCustomObject("traefik.containo.us", "v1alpha1", "ingressroutes")
+ .then((response) => response.body)
+ .catch(async (error) => {
+ if (traefikContainoExists) {
+ logger.error(
+ "Error getting traefik ingresses from traefik.containo.us: %d %s %s",
+ error.statusCode,
+ error.body,
+ error.response,
+ );
+ logger.debug(error);
+ }
+
+ return [];
+ });
+
+ const traefikIngressListIo = await crd
+ .listClusterCustomObject("traefik.io", "v1alpha1", "ingressroutes")
+ .then((response) => response.body)
+ .catch(async (error) => {
+ if (traefikExists) {
+ logger.error(
+ "Error getting traefik ingresses from traefik.io: %d %s %s",
+ error.statusCode,
+ error.body,
+ error.response,
+ );
+ logger.debug(error);
+ }
+
+ return [];
+ });
+
+ const traefikIngressList = [...(traefikIngressListContaino?.items ?? []), ...(traefikIngressListIo?.items ?? [])];
+
+ if (traefikIngressList.length > 0) {
+ const traefikServices = traefikIngressList.filter(
+ (ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${ANNOTATION_BASE}/href`],
+ );
+ ingressList.items.push(...traefikServices);
+ }
+
+ if (!ingressList) {
+ return [];
+ }
+ const services = ingressList.items
+ .filter(
+ (ingress) =>
+ ingress.metadata.annotations &&
+ ingress.metadata.annotations[`${ANNOTATION_BASE}/enabled`] === "true" &&
+ (!ingress.metadata.annotations[`${ANNOTATION_BASE}/instance`] ||
+ ingress.metadata.annotations[`${ANNOTATION_BASE}/instance`] === instanceName ||
+ `${ANNOTATION_BASE}/instance.${instanceName}` in ingress.metadata.annotations),
+ )
+ .map((ingress) => {
+ let constructedService = {
+ app: ingress.metadata.annotations[`${ANNOTATION_BASE}/app`] || ingress.metadata.name,
+ namespace: ingress.metadata.namespace,
+ href: ingress.metadata.annotations[`${ANNOTATION_BASE}/href`] || getUrlFromIngress(ingress),
+ name: ingress.metadata.annotations[`${ANNOTATION_BASE}/name`] || ingress.metadata.name,
+ group: ingress.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
+ weight: ingress.metadata.annotations[`${ANNOTATION_BASE}/weight`] || "0",
+ icon: ingress.metadata.annotations[`${ANNOTATION_BASE}/icon`] || "",
+ description: ingress.metadata.annotations[`${ANNOTATION_BASE}/description`] || "",
+ external: false,
+ type: "service",
+ };
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/external`]) {
+ constructedService.external =
+ String(ingress.metadata.annotations[`${ANNOTATION_BASE}/external`]).toLowerCase() === "true";
+ }
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`] !== undefined) {
+ constructedService.podSelector = ingress.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`];
+ }
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
+ constructedService.ping = ingress.metadata.annotations[`${ANNOTATION_BASE}/ping`];
+ }
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`]) {
+ constructedService.siteMonitor = ingress.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`];
+ }
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`]) {
+ constructedService.statusStyle = ingress.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`];
+ }
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/allowUsers`]) {
+ constructedService.allowUsers = ingress.metadata.annotations[`${ANNOTATION_BASE}/allowUsers`].split(",");
+ }
+ if (ingress.metadata.annotations[`${ANNOTATION_BASE}/allowGroups`]) {
+ constructedService.allowGroups = ingress.metadata.annotations[`${ANNOTATION_BASE}/allowGroups`].split(",");
+ }
+ Object.keys(ingress.metadata.annotations).forEach((annotation) => {
+ if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
+ shvl.set(
+ constructedService,
+ annotation.replace(`${ANNOTATION_BASE}/`, ""),
+ ingress.metadata.annotations[annotation],
+ );
+ }
+ });
+
+ try {
+ constructedService = JSON.parse(substituteEnvironmentVars(JSON.stringify(constructedService)));
+ } catch (e) {
+ logger.error("Error attempting k8s environment variable substitution.");
+ logger.debug(e);
+ }
+
+ return constructedService;
+ });
+
+ const mappedServiceGroups = [];
+
+ services.forEach((serverService) => {
+ let serverGroup = mappedServiceGroups.find((searchedGroup) => searchedGroup.name === serverService.group);
+ if (!serverGroup) {
+ mappedServiceGroups.push({
+ name: serverService.group,
+ services: [],
+ });
+ serverGroup = mappedServiceGroups[mappedServiceGroups.length - 1];
+ }
+
+ const { name: serviceName, group: serverServiceGroup, ...pushedService } = serverService;
+ const result = {
+ name: serviceName,
+ ...pushedService,
+ };
+
+ serverGroup.services.push(result);
+ });
return mappedServiceGroups;
} catch (e) {
@@ -304,7 +438,7 @@ export function cleanServiceGroups(groups) {
// frigate
enableRecentEvents,
- // beszel, glances, immich, komga, mealie, pihole, pfsense, speedtest
+ // beszel, glances, immich, mealie, pihole, pfsense
version,
// glances
@@ -362,9 +496,6 @@ export function cleanServiceGroups(groups) {
// proxmox
node,
- // proxmoxbackupserver
- datastore,
-
// speedtest
bitratePrecision,
@@ -440,9 +571,6 @@ export function cleanServiceGroups(groups) {
if (type === "proxmox") {
if (node) widget.node = node;
}
- if (type === "proxmoxbackupserver") {
- if (datastore) widget.datastore = datastore;
- }
if (type === "kubernetes") {
if (namespace) widget.namespace = namespace;
if (app) widget.app = app;
@@ -488,7 +616,7 @@ export function cleanServiceGroups(groups) {
if (snapshotHost) widget.snapshotHost = snapshotHost;
if (snapshotPath) widget.snapshotPath = snapshotPath;
}
- if (["beszel", "glances", "immich", "komga", "mealie", "pfsense", "pihole", "speedtest"].includes(type)) {
+ if (["beszel", "glances", "immich", "mealie", "pfsense", "pihole"].includes(type)) {
if (version) widget.version = parseInt(version, 10);
}
if (type === "glances") {
@@ -581,7 +709,7 @@ export function findGroupByName(groups, name) {
} else if (group.groups) {
const foundGroup = findGroupByName(group.groups, name);
if (foundGroup) {
- foundGroup.parent = group.name;
+ foundGroup.parent = group;
return foundGroup;
}
}
diff --git a/src/utils/config/widget-helpers.js b/src/utils/config/widget-helpers.js
index 93f71194..7c5c78cd 100644
--- a/src/utils/config/widget-helpers.js
+++ b/src/utils/config/widget-helpers.js
@@ -38,7 +38,7 @@ export async function cleanWidgetGroups(widgets) {
}
});
- // delete url from the sanitized options if the widget is not a search or glances widget
+ // delete url from the sanitized options if the widget is not a search or glances widgeth
if (widget.type !== "search" && widget.type !== "glances" && optionKeys.includes("url")) {
delete sanitizedOptions.url;
}
@@ -56,22 +56,21 @@ export async function cleanWidgetGroups(widgets) {
export async function getPrivateWidgetOptions(type, widgetIndex) {
const widgets = await widgetsFromConfig();
- const privateOptions =
- widgets.map((widget) => {
- const { index, url, username, password, key, apiKey } = widget.options;
+ const privateOptions = widgets.map((widget) => {
+ const { index, url, username, password, key, apiKey } = widget.options;
- return {
- type: widget.type,
- options: {
- index,
- url,
- username,
- password,
- key,
- apiKey,
- },
- };
- }) || {};
+ return {
+ type: widget.type,
+ options: {
+ index,
+ url,
+ username,
+ password,
+ key,
+ apiKey,
+ },
+ };
+ });
return type !== undefined && widgetIndex !== undefined
? privateOptions.find((o) => o.type === type && o.options.index === parseInt(widgetIndex, 10))?.options
diff --git a/src/utils/contexts/color.jsx b/src/utils/contexts/color.jsx
index bc16d605..d7d985f0 100644
--- a/src/utils/contexts/color.jsx
+++ b/src/utils/contexts/color.jsx
@@ -1,4 +1,4 @@
-import { createContext, useEffect, useMemo, useState } from "react";
+import { createContext, useState, useEffect, useMemo } from "react";
let lastColor = false;
diff --git a/src/utils/contexts/settings.jsx b/src/utils/contexts/settings.jsx
index 76451953..d6993b14 100644
--- a/src/utils/contexts/settings.jsx
+++ b/src/utils/contexts/settings.jsx
@@ -1,4 +1,4 @@
-import { createContext, useMemo, useState } from "react";
+import { createContext, useState, useMemo } from "react";
export const SettingsContext = createContext();
diff --git a/src/utils/contexts/tab.jsx b/src/utils/contexts/tab.jsx
index 2a3d3457..8cd5d520 100644
--- a/src/utils/contexts/tab.jsx
+++ b/src/utils/contexts/tab.jsx
@@ -1,4 +1,4 @@
-import { createContext, useMemo, useState } from "react";
+import { createContext, useState, useMemo } from "react";
export const TabContext = createContext();
diff --git a/src/utils/contexts/theme.jsx b/src/utils/contexts/theme.jsx
index 385eeaa2..85d613fc 100644
--- a/src/utils/contexts/theme.jsx
+++ b/src/utils/contexts/theme.jsx
@@ -1,4 +1,4 @@
-import { createContext, useEffect, useMemo, useState } from "react";
+import { createContext, useState, useEffect, useMemo } from "react";
const getInitialTheme = () => {
if (typeof window !== "undefined" && window.localStorage) {
diff --git a/src/utils/hooks/window-focus.js b/src/utils/hooks/window-focus.js
index a221e48e..3ad57ad0 100644
--- a/src/utils/hooks/window-focus.js
+++ b/src/utils/hooks/window-focus.js
@@ -1,4 +1,4 @@
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
const hasFocus = () => typeof document !== "undefined" && document.hasFocus();
diff --git a/src/utils/kubernetes/export.js b/src/utils/kubernetes/export.js
deleted file mode 100644
index ae53aaca..00000000
--- a/src/utils/kubernetes/export.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import listHttpRoute from "utils/kubernetes/httproute-list";
-import listIngress from "utils/kubernetes/ingress-list";
-import { constructedServiceFromResource, isDiscoverable } from "utils/kubernetes/resource-helpers";
-import listTraefikIngress from "utils/kubernetes/traefik-list";
-
-const kubernetes = {
- listIngress,
- listTraefikIngress,
- listHttpRoute,
- isDiscoverable,
- constructedServiceFromResource,
-};
-
-export default kubernetes;
diff --git a/src/utils/kubernetes/httproute-list.js b/src/utils/kubernetes/httproute-list.js
deleted file mode 100644
index df147d16..00000000
--- a/src/utils/kubernetes/httproute-list.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import { CoreV1Api, CustomObjectsApi } from "@kubernetes/client-node";
-
-import { getKubeConfig, getKubernetes, HTTPROUTE_API_GROUP, HTTPROUTE_API_VERSION } from "utils/config/kubernetes";
-import createLogger from "utils/logger";
-
-const logger = createLogger("httproute-list");
-const kc = getKubeConfig();
-
-export default async function listHttpRoute() {
- const crd = kc.makeApiClient(CustomObjectsApi);
- const core = kc.makeApiClient(CoreV1Api);
- const { gateway } = getKubernetes();
- let httpRouteList = [];
-
- if (gateway) {
- // httproutes
- const getHttpRoutes = async (namespace) =>
- crd
- .listNamespacedCustomObject({
- group: HTTPROUTE_API_GROUP,
- version: HTTPROUTE_API_VERSION,
- namespace,
- plural: "httproutes",
- })
- .then((response) => {
- return response.items;
- })
- .catch((error) => {
- logger.error("Error getting httproutes: %d %s %s", error.statusCode, error.body, error.response);
- logger.debug(error);
- return null;
- });
- // namespaces
- const namespaces = await core
- .listNamespace()
- .then((response) => response.items.map((ns) => ns.metadata.name))
- .catch((error) => {
- logger.error("Error getting namespaces: %d %s %s", error.statusCode, error.body, error.response);
- logger.debug(error);
- return null;
- });
-
- if (namespaces) {
- const httpRouteListUnfiltered = await Promise.all(
- namespaces.map(async (namespace) => {
- const httpRoutes = await getHttpRoutes(namespace);
- return httpRoutes;
- }),
- );
-
- httpRouteList = httpRouteListUnfiltered.flat().filter((httpRoute) => httpRoute);
- }
- }
- return httpRouteList;
-}
diff --git a/src/utils/kubernetes/ingress-list.js b/src/utils/kubernetes/ingress-list.js
deleted file mode 100644
index 1cd9ca95..00000000
--- a/src/utils/kubernetes/ingress-list.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { NetworkingV1Api } from "@kubernetes/client-node";
-
-import { getKubeConfig, getKubernetes } from "utils/config/kubernetes";
-import createLogger from "utils/logger";
-
-const logger = createLogger("ingress-list");
-const kc = getKubeConfig();
-
-export default async function listIngress() {
- const networking = kc.makeApiClient(NetworkingV1Api);
- const { ingress = true } = getKubernetes();
- let ingressList = [];
-
- if (ingress) {
- const ingressData = await networking
- .listIngressForAllNamespaces()
- .then((response) => response)
- .catch((error) => {
- logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response);
- logger.debug(error);
- return null;
- });
- ingressList = ingressData.items;
- }
- return ingressList;
-}
diff --git a/src/utils/kubernetes/utils.js b/src/utils/kubernetes/kubernetes-utils.js
similarity index 100%
rename from src/utils/kubernetes/utils.js
rename to src/utils/kubernetes/kubernetes-utils.js
diff --git a/src/utils/kubernetes/resource-helpers.js b/src/utils/kubernetes/resource-helpers.js
deleted file mode 100644
index c7d69751..00000000
--- a/src/utils/kubernetes/resource-helpers.js
+++ /dev/null
@@ -1,143 +0,0 @@
-import { CustomObjectsApi } from "@kubernetes/client-node";
-
-import { substituteEnvironmentVars } from "utils/config/config";
-import {
- ANNOTATION_BASE,
- ANNOTATION_WIDGET_BASE,
- getKubeConfig,
- HTTPROUTE_API_GROUP,
- HTTPROUTE_API_VERSION,
-} from "utils/config/kubernetes";
-import * as shvl from "utils/config/shvl";
-import createLogger from "utils/logger";
-
-const logger = createLogger("resource-helpers");
-const kc = getKubeConfig();
-
-const getSchemaFromGateway = async (parentRef) => {
- const crd = kc.makeApiClient(CustomObjectsApi);
- const schema = await crd
- .getNamespacedCustomObject({
- group: HTTPROUTE_API_GROUP,
- version: HTTPROUTE_API_VERSION,
- namespace: parentRef.namespace,
- plural: "gateways",
- name: parentRef.name,
- })
- .then((response) => {
- const listener =
- response.spec.listeners.find((l) => l.name === parentRef.sectionName) ?? response.spec.listeners[0];
-
- return listener.protocol.toLowerCase();
- })
- .catch((error) => {
- logger.error("Error getting gateways: %d %s %s", error.statusCode, error.body, error.response);
- logger.debug(error);
-
- return "http";
- });
-
- return schema;
-};
-
-async function getUrlFromHttpRoute(resource) {
- let url = null;
- const hasHostName = resource.spec?.hostnames;
-
- if (hasHostName) {
- if (resource.spec.rules[0].matches[0].path.type !== "RegularExpression") {
- const urlHost = resource.spec.hostnames[0];
- const urlPath = resource.spec.rules[0].matches[0].path.value;
- const urlSchema = await getSchemaFromGateway(resource.spec.parentRefs[0]);
- url = `${urlSchema}://${urlHost}${urlPath}`;
- }
- }
-
- return url;
-}
-
-function getUrlFromIngress(resource) {
- const urlHost = resource.spec.rules[0].host;
- const urlPath = resource.spec.rules[0].http.paths[0].path;
- const urlSchema = resource.spec.tls ? "https" : "http";
-
- return `${urlSchema}://${urlHost}${urlPath}`;
-}
-
-async function getUrlSchema(resource) {
- const isHttpRoute = resource.kind === "HTTPRoute";
- let urlSchema;
- if (isHttpRoute) {
- urlSchema = getUrlFromHttpRoute(resource);
- } else {
- urlSchema = getUrlFromIngress(resource);
- }
-
- return urlSchema;
-}
-
-export function isDiscoverable(resource, instanceName) {
- return (
- resource.metadata.annotations &&
- resource.metadata.annotations[`${ANNOTATION_BASE}/enabled`] === "true" &&
- (!resource.metadata.annotations[`${ANNOTATION_BASE}/instance`] ||
- resource.metadata.annotations[`${ANNOTATION_BASE}/instance`] === instanceName ||
- `${ANNOTATION_BASE}/instance.${instanceName}` in resource.metadata.annotations)
- );
-}
-
-export async function constructedServiceFromResource(resource) {
- let constructedService = {
- app: resource.metadata.annotations[`${ANNOTATION_BASE}/app`] || resource.metadata.name,
- namespace: resource.metadata.namespace,
- href: resource.metadata.annotations[`${ANNOTATION_BASE}/href`] || (await getUrlSchema(resource)),
- name: resource.metadata.annotations[`${ANNOTATION_BASE}/name`] || resource.metadata.name,
- group: resource.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
- weight: resource.metadata.annotations[`${ANNOTATION_BASE}/weight`] || "0",
- icon: resource.metadata.annotations[`${ANNOTATION_BASE}/icon`] || "",
- description: resource.metadata.annotations[`${ANNOTATION_BASE}/description`] || "",
- external: false,
- type: "service",
- };
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/external`]) {
- constructedService.external =
- String(resource.metadata.annotations[`${ANNOTATION_BASE}/external`]).toLowerCase() === "true";
- }
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`] !== undefined) {
- constructedService.podSelector = resource.metadata.annotations[`${ANNOTATION_BASE}/pod-selector`];
- }
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/ping`]) {
- constructedService.ping = resource.metadata.annotations[`${ANNOTATION_BASE}/ping`];
- }
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`]) {
- constructedService.siteMonitor = resource.metadata.annotations[`${ANNOTATION_BASE}/siteMonitor`];
- }
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`]) {
- constructedService.statusStyle = resource.metadata.annotations[`${ANNOTATION_BASE}/statusStyle`];
- }
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/allowUsers`]) {
- constructedService.allowUsers = resource.metadata.annotations[`${ANNOTATION_BASE}/allowUsers`].split(",");
- }
- if (resource.metadata.annotations[`${ANNOTATION_BASE}/allowGroups`]) {
- constructedService.allowGroups = resource.metadata.annotations[`${ANNOTATION_BASE}/allowGroups`].split(",");
- }
-
- Object.keys(resource.metadata.annotations).forEach((annotation) => {
- if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
- shvl.set(
- constructedService,
- annotation.replace(`${ANNOTATION_BASE}/`, ""),
- resource.metadata.annotations[annotation],
- );
- }
- });
-
- try {
- constructedService = JSON.parse(substituteEnvironmentVars(JSON.stringify(constructedService)));
- } catch (e) {
- logger.error("Error attempting k8s environment variable substitution.");
- logger.debug(e);
- }
-
- return constructedService;
-}
diff --git a/src/utils/kubernetes/traefik-list.js b/src/utils/kubernetes/traefik-list.js
deleted file mode 100644
index f6e07241..00000000
--- a/src/utils/kubernetes/traefik-list.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import { CustomObjectsApi } from "@kubernetes/client-node";
-
-import { ANNOTATION_BASE, checkCRD, getKubeConfig, getKubernetes } from "utils/config/kubernetes";
-import createLogger from "utils/logger";
-
-const logger = createLogger("traefik-list");
-const kc = getKubeConfig();
-
-export default async function listTraefikIngress() {
- const { traefik } = getKubernetes();
- const traefikList = [];
-
- if (traefik) {
- const crd = kc.makeApiClient(CustomObjectsApi);
- const traefikContainoExists = await checkCRD("ingressroutes.traefik.containo.us", kc, logger);
- const traefikExists = await checkCRD("ingressroutes.traefik.io", kc, logger);
-
- const traefikIngressListContaino = await crd
- .listClusterCustomObject({
- group: "traefik.containo.us",
- version: "v1alpha1",
- plural: "ingressroutes",
- })
- .catch(async (error) => {
- if (traefikContainoExists) {
- logger.error(
- "Error getting traefik ingresses from traefik.containo.us: %d %s %s",
- error.statusCode,
- error.body,
- error.response,
- );
- logger.debug(error);
- }
-
- return [];
- });
-
- const traefikIngressListIo = await crd
- .listClusterCustomObject({
- group: "traefik.io",
- version: "v1alpha1",
- plural: "ingressroutes",
- })
- .catch(async (error) => {
- if (traefikExists) {
- logger.error(
- "Error getting traefik ingresses from traefik.io: %d %s %s",
- error.statusCode,
- error.body,
- error.response,
- );
- logger.debug(error);
- }
-
- return [];
- });
-
- const traefikIngressList = [...(traefikIngressListContaino?.items ?? []), ...(traefikIngressListIo?.items ?? [])];
-
- if (traefikIngressList.length > 0) {
- const traefikServices = traefikIngressList.filter(
- (ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${ANNOTATION_BASE}/href`],
- );
- traefikList.push(...traefikServices);
- }
- }
- return traefikList;
-}
diff --git a/src/utils/proxy/api-helpers.js b/src/utils/proxy/api-helpers.js
index 6ef4d9d0..a02ea623 100644
--- a/src/utils/proxy/api-helpers.js
+++ b/src/utils/proxy/api-helpers.js
@@ -2,14 +2,10 @@ export function formatApiCall(url, args) {
const find = /\{.*?\}/g;
const replace = (match) => {
const key = match.replace(/\{|\}/g, "");
- let value = args[key];
- if (key === "url") {
- value = value.replace(/\/+$/, ""); // remove trailing slashes
- }
- return value || "";
+ return args[key] || "";
};
- return url.replace(find, replace).replace(find, replace);
+ return url.replace(/\/+$/, "").replace(find, replace).replace(find, replace);
}
export function getURLSearchParams(widget, endpoint) {
diff --git a/src/utils/proxy/cached-fetch.js b/src/utils/proxy/cached-fetch.js
new file mode 100644
index 00000000..ae3c4610
--- /dev/null
+++ b/src/utils/proxy/cached-fetch.js
@@ -0,0 +1,25 @@
+import cache from "memory-cache";
+
+const defaultDuration = 5;
+
+export default async function cachedFetch(url, duration, ua) {
+ const cached = cache.get(url);
+
+ // eslint-disable-next-line no-param-reassign
+ duration = duration || defaultDuration;
+
+ if (cached) {
+ return cached;
+ }
+
+ // wrapping text in JSON.parse to handle utf-8 issues
+ const options = {};
+ if (ua) {
+ options.headers = {
+ "User-Agent": ua,
+ };
+ }
+ const data = await fetch(url, options).then((res) => res.json());
+ cache.put(url, data, duration * 1000 * 60);
+ return data;
+}
diff --git a/src/utils/proxy/cookie-jar.js b/src/utils/proxy/cookie-jar.js
index baea21d5..6519231c 100644
--- a/src/utils/proxy/cookie-jar.js
+++ b/src/utils/proxy/cookie-jar.js
@@ -8,7 +8,7 @@ export function setCookieHeader(url, params) {
const existingCookie = cookieJar.getCookieStringSync(url.toString());
if (existingCookie) {
params.headers = params.headers ?? {};
- params.headers[params.cookieHeader ?? "Cookie"] = existingCookie;
+ params.headers.Cookie = existingCookie;
}
}
diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js
index 017d44c9..01fb313b 100644
--- a/src/utils/proxy/handlers/credentialed.js
+++ b/src/utils/proxy/handlers/credentialed.js
@@ -1,9 +1,9 @@
-import { getSettings } from "utils/config/config";
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall, sanitizeErrorURL } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import validateWidgetData from "utils/proxy/validate-widget-data";
+import { httpProxy } from "utils/proxy/http";
+import createLogger from "utils/logger";
+import { getSettings } from "utils/config/config";
import widgets from "widgets/widgets";
const logger = createLogger("credentialedProxyHandler");
@@ -41,8 +41,6 @@ export default async function credentialedProxyHandler(req, res, map) {
"cloudflared",
"ghostfolio",
"headscale",
- "hoarder",
- "karakeep",
"linkwarden",
"mealie",
"netalertx",
@@ -50,7 +48,6 @@ export default async function credentialedProxyHandler(req, res, map) {
"tandoor",
"pterodactyl",
"vikunja",
- "firefly",
].includes(widget.type)
) {
headers.Authorization = `Bearer ${widget.key}`;
@@ -101,11 +98,6 @@ export default async function credentialedProxyHandler(req, res, map) {
headers.Authorization = widget.password;
} else if (widget.type === "gitlab") {
headers["PRIVATE-TOKEN"] = widget.key;
- } else if (widget.type === "speedtest") {
- if (widget.key) {
- // v1 does not require a key
- headers.Authorization = `Bearer ${widget.key}`;
- }
} else {
headers["X-API-Key"] = `${widget.key}`;
}
diff --git a/src/utils/proxy/handlers/generic.js b/src/utils/proxy/handlers/generic.js
index 1914114c..2e788a98 100644
--- a/src/utils/proxy/handlers/generic.js
+++ b/src/utils/proxy/handlers/generic.js
@@ -1,8 +1,8 @@
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall, sanitizeErrorURL } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import validateWidgetData from "utils/proxy/validate-widget-data";
+import { httpProxy } from "utils/proxy/http";
+import createLogger from "utils/logger";
import widgets from "widgets/widgets";
const logger = createLogger("genericProxyHandler");
@@ -79,7 +79,7 @@ export default async function genericProxyHandler(req, res, map) {
error: {
message: "HTTP Error",
url: sanitizeErrorURL(url),
- data: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
+ resultData: Buffer.isBuffer(resultData) ? Buffer.from(resultData).toString() : resultData,
},
});
}
diff --git a/src/utils/proxy/handlers/jsonrpc.js b/src/utils/proxy/handlers/jsonrpc.js
index bdb10e02..f9fb1883 100644
--- a/src/utils/proxy/handlers/jsonrpc.js
+++ b/src/utils/proxy/handlers/jsonrpc.js
@@ -1,9 +1,9 @@
import { JSONRPCClient, JSONRPCErrorException } from "json-rpc-2.0";
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
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";
import widgets from "widgets/widgets";
const logger = createLogger("jsonrpcProxyHandler");
diff --git a/src/utils/proxy/handlers/synology.js b/src/utils/proxy/handlers/synology.js
index 6fe98dce..030e53ba 100644
--- a/src/utils/proxy/handlers/synology.js
+++ b/src/utils/proxy/handlers/synology.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { asJson, formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
+import createLogger from "utils/logger";
import widgets from "widgets/widgets";
const INFO_ENDPOINT = "{url}/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query";
diff --git a/src/utils/proxy/http.js b/src/utils/proxy/http.js
index 1a22a7f7..875bfb4c 100644
--- a/src/utils/proxy/http.js
+++ b/src/utils/proxy/http.js
@@ -3,10 +3,9 @@
import { createUnzip, constants as zlibConstants } from "node:zlib";
import { http, https } from "follow-redirects";
-import cache from "memory-cache";
-import { sanitizeErrorURL } from "./api-helpers";
import { addCookieToJar, setCookieHeader } from "./cookie-jar";
+import { sanitizeErrorURL } from "./api-helpers";
import createLogger from "utils/logger";
@@ -82,46 +81,23 @@ export function httpRequest(url, params) {
return handleRequest(http, url, params);
}
-export async function cachedRequest(url, duration = 5, ua = "homepage") {
- const cached = cache.get(url);
-
- if (cached) {
- return cached;
- }
-
- const options = {
- headers: {
- "User-Agent": ua,
- Accept: "application/json",
- },
- };
- let [, , data] = await httpProxy(url, options);
- if (Buffer.isBuffer(data)) {
- try {
- data = JSON.parse(Buffer.from(data).toString());
- } catch (e) {
- logger.debug("Error parsing cachedRequest data for %s: %s %s", url, Buffer.from(data).toString(), e);
- data = Buffer.from(data).toString();
- }
- }
- cache.put(url, data, duration * 1000 * 60);
- return data;
-}
-
export async function httpProxy(url, params = {}) {
const constructedUrl = new URL(url);
- const disableIpv6 = process.env.HOMEPAGE_PROXY_DISABLE_IPV6 === "true";
- const agentOptions = disableIpv6 ? { family: 4, autoSelectFamily: false } : {};
let request = null;
if (constructedUrl.protocol === "https:") {
request = httpsRequest(constructedUrl, {
- agent: new https.Agent({ ...agentOptions, rejectUnauthorized: false }),
+ agent: new https.Agent({
+ rejectUnauthorized: false,
+ autoSelectFamily: true,
+ }),
...params,
});
} else {
request = httpRequest(constructedUrl, {
- agent: new http.Agent(agentOptions),
+ agent: new http.Agent({
+ autoSelectFamily: true,
+ }),
...params,
});
}
diff --git a/src/utils/proxy/validate-widget-data.js b/src/utils/proxy/validate-widget-data.js
index de2a3c4e..8f865fe2 100644
--- a/src/utils/proxy/validate-widget-data.js
+++ b/src/utils/proxy/validate-widget-data.js
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
-import createLogger from "utils/logger";
import widgets from "widgets/widgets";
+import createLogger from "utils/logger";
const logger = createLogger("validateWidgetData");
diff --git a/src/widgets/adguard/component.jsx b/src/widgets/adguard/component.jsx
index e5a7670a..b2025c4e 100644
--- a/src/widgets/adguard/component.jsx
+++ b/src/widgets/adguard/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/apcups/component.jsx b/src/widgets/apcups/component.jsx
deleted file mode 100644
index 85e621db..00000000
--- a/src/widgets/apcups/component.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-
-import useWidgetAPI from "utils/proxy/use-widget-api";
-
-export default function Component({ service }) {
- const { widget } = service;
- const { data, error } = useWidgetAPI(widget);
-
- if (error) {
- return
;
- }
-
- if (!data) {
- return (
-
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
-
- );
-}
diff --git a/src/widgets/apcups/proxy.js b/src/widgets/apcups/proxy.js
deleted file mode 100644
index bf22730e..00000000
--- a/src/widgets/apcups/proxy.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { Buffer } from "node:buffer";
-import net from "node:net";
-
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
-
-const logger = createLogger("apcupsProxyHandler");
-
-function parseResponse(buffer) {
- let ptr = 0;
- const output = [];
- while (ptr < buffer.length) {
- const lineLen = buffer.readUInt16BE(ptr);
- const asciiData = buffer.toString("ascii", ptr + 2, lineLen + ptr + 2);
- output.push(asciiData);
- ptr += 2 + lineLen;
- }
-
- return output;
-}
-
-function statusAsJSON(statusOutput) {
- return statusOutput?.reduce((output, line) => {
- if (!line || line.startsWith("END APC")) return output;
- const [key, value] = line.trim().split(":");
- const newOutput = { ...output };
- newOutput[key.trim()] = value?.trim();
- return newOutput;
- }, {});
-}
-
-async function getStatus(host = "127.0.0.1", port = 3551) {
- return new Promise((resolve, reject) => {
- const socket = new net.Socket();
- socket.setTimeout(5000);
- socket.connect({ host, port });
-
- const response = [];
-
- socket.on("connect", () => {
- const CMD = "status";
- logger.debug(`Connecting to ${host}:${port}`);
- const buffer = Buffer.alloc(CMD.length + 2);
- buffer.writeUInt16BE(CMD.length, 0);
- buffer.write(CMD, 2);
- socket.write(buffer);
- });
-
- socket.on("data", (data) => {
- response.push(data);
-
- if (data.readUInt16BE(data.length - 2) === 0) {
- try {
- const buffer = Buffer.concat(response);
- const output = parseResponse(buffer);
- resolve(output);
- } catch (e) {
- reject(e);
- }
- socket.end();
- }
- });
-
- socket.on("error", (err) => {
- socket.destroy();
- reject(err);
- });
- socket.on("timeout", () => {
- socket.destroy();
- reject(new Error("socket timeout"));
- });
- socket.on("end", () => {
- logger.debug("socket end");
- });
- socket.on("close", () => {
- logger.debug("socket closed");
- });
- });
-}
-
-export default async function apcupsProxyHandler(req, res) {
- const { group, service, index } = 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, index);
- 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(widget.url);
- const data = {};
-
- try {
- const statusData = await getStatus(url.hostname, url.port);
- const jsonData = statusAsJSON(statusData);
-
- data.status = jsonData.STATUS;
- data.load = jsonData.LOADPCT;
- data.bcharge = jsonData.BCHARGE;
- data.timeleft = jsonData.TIMELEFT;
- } catch (e) {
- logger.error(e);
- return res.status(500).json({ error: e.message });
- }
-
- return res.status(200).send(data);
-}
diff --git a/src/widgets/apcups/widget.js b/src/widgets/apcups/widget.js
deleted file mode 100644
index 68f6371b..00000000
--- a/src/widgets/apcups/widget.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import apcupsProxyHandler from "./proxy";
-
-const widget = {
- proxyHandler: apcupsProxyHandler,
-};
-
-export default widget;
diff --git a/src/widgets/argocd/component.jsx b/src/widgets/argocd/component.jsx
index f61bed43..d3b51936 100644
--- a/src/widgets/argocd/component.jsx
+++ b/src/widgets/argocd/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/atsumeru/component.jsx b/src/widgets/atsumeru/component.jsx
index 01cc8e46..85e78182 100644
--- a/src/widgets/atsumeru/component.jsx
+++ b/src/widgets/atsumeru/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/audiobookshelf/component.jsx b/src/widgets/audiobookshelf/component.jsx
index b410e1a7..06439e8f 100755
--- a/src/widgets/audiobookshelf/component.jsx
+++ b/src/widgets/audiobookshelf/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/audiobookshelf/proxy.js b/src/widgets/audiobookshelf/proxy.js
index afff3ba9..1a89736b 100644
--- a/src/widgets/audiobookshelf/proxy.js
+++ b/src/widgets/audiobookshelf/proxy.js
@@ -1,7 +1,7 @@
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "audiobookshelfProxyHandler";
diff --git a/src/widgets/authentik/component.jsx b/src/widgets/authentik/component.jsx
index edf5ece1..9ca69c30 100644
--- a/src/widgets/authentik/component.jsx
+++ b/src/widgets/authentik/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/autobrr/component.jsx b/src/widgets/autobrr/component.jsx
index 5454cd3c..f983789b 100644
--- a/src/widgets/autobrr/component.jsx
+++ b/src/widgets/autobrr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/azuredevops/component.jsx b/src/widgets/azuredevops/component.jsx
index 7a36aab2..fc388595 100644
--- a/src/widgets/azuredevops/component.jsx
+++ b/src/widgets/azuredevops/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/bazarr/component.jsx b/src/widgets/bazarr/component.jsx
index f79ec206..082e368a 100644
--- a/src/widgets/bazarr/component.jsx
+++ b/src/widgets/bazarr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/bazarr/widget.js b/src/widgets/bazarr/widget.js
index c54e38ad..5b89b2b4 100644
--- a/src/widgets/bazarr/widget.js
+++ b/src/widgets/bazarr/widget.js
@@ -1,5 +1,5 @@
-import { asJson } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+import { asJson } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/{endpoint}/wanted?apikey={key}",
diff --git a/src/widgets/beszel/component.jsx b/src/widgets/beszel/component.jsx
index e80a9fab..da1b7a48 100644
--- a/src/widgets/beszel/component.jsx
+++ b/src/widgets/beszel/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/beszel/proxy.js b/src/widgets/beszel/proxy.js
index 96dfc913..078e22c3 100644
--- a/src/widgets/beszel/proxy.js
+++ b/src/widgets/beszel/proxy.js
@@ -1,10 +1,10 @@
import cache from "memory-cache";
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
+import createLogger from "utils/logger";
const proxyName = "beszelProxyHandler";
const tokenCacheKey = `${proxyName}__token`;
diff --git a/src/widgets/caddy/component.jsx b/src/widgets/caddy/component.jsx
index 1613760d..36e5f959 100644
--- a/src/widgets/caddy/component.jsx
+++ b/src/widgets/caddy/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/calendar/agenda.jsx b/src/widgets/calendar/agenda.jsx
index cb00c1d2..6a3be031 100644
--- a/src/widgets/calendar/agenda.jsx
+++ b/src/widgets/calendar/agenda.jsx
@@ -1,5 +1,5 @@
-import classNames from "classnames";
import { DateTime } from "luxon";
+import classNames from "classnames";
import { useTranslation } from "next-i18next";
import Event, { compareDateTimezone } from "./event";
diff --git a/src/widgets/calendar/component.jsx b/src/widgets/calendar/component.jsx
index 0647d4ad..ff93c41b 100644
--- a/src/widgets/calendar/component.jsx
+++ b/src/widgets/calendar/component.jsx
@@ -1,12 +1,13 @@
-import Container from "components/services/widget/container";
+import { useEffect, useMemo, useState, useContext } from "react";
+import dynamic from "next/dynamic";
import { DateTime } from "luxon";
import { useTranslation } from "next-i18next";
-import dynamic from "next/dynamic";
-import { useContext, useEffect, useMemo, useState } from "react";
-import { SettingsContext } from "utils/contexts/settings";
-import Agenda from "./agenda";
import Monthly from "./monthly";
+import Agenda from "./agenda";
+
+import Container from "components/services/widget/container";
+import { SettingsContext } from "utils/contexts/settings";
const colorVariants = {
// https://tailwindcss.com/docs/content-configuration#dynamic-class-names
diff --git a/src/widgets/calendar/event.jsx b/src/widgets/calendar/event.jsx
index 6ea2e1ae..91b40e82 100644
--- a/src/widgets/calendar/event.jsx
+++ b/src/widgets/calendar/event.jsx
@@ -1,7 +1,7 @@
-import classNames from "classnames";
-import { DateTime } from "luxon";
-import { useTranslation } from "next-i18next";
import { useState } from "react";
+import { useTranslation } from "next-i18next";
+import { DateTime } from "luxon";
+import classNames from "classnames";
import { IoMdCheckmarkCircleOutline } from "react-icons/io";
export default function Event({ event, colorVariants, showDate = false, showTime = false, showDateColumn = true }) {
@@ -26,7 +26,7 @@ export default function Event({ event, colorVariants, showDate = false, showTime
)}
-
+
{hover && event.additional ? event.additional : event.title}
@@ -39,5 +39,4 @@ export default function Event({ event, colorVariants, showDate = false, showTime
);
}
-export const compareDateTimezone = (date, event) =>
- date.startOf("day").toISODate() === event.date.startOf("day").toISODate();
+export const compareDateTimezone = (date, event) => date.startOf("day").ts === event.date.startOf("day").ts;
diff --git a/src/widgets/calendar/integrations/ical.jsx b/src/widgets/calendar/integrations/ical.jsx
index 46217977..059adfa2 100644
--- a/src/widgets/calendar/integrations/ical.jsx
+++ b/src/widgets/calendar/integrations/ical.jsx
@@ -1,11 +1,11 @@
-import { parseString } from "cal-parser";
import { DateTime } from "luxon";
-import { useTranslation } from "next-i18next";
+import { parseString } from "cal-parser";
import { useEffect } from "react";
+import { useTranslation } from "next-i18next";
import { RRule } from "rrule";
-import Error from "../../../components/services/widget/error";
import useWidgetAPI from "../../../utils/proxy/use-widget-api";
+import Error from "../../../components/services/widget/error";
// https://gist.github.com/jlevy/c246006675becc446360a798e2b2d781
function simpleHash(str) {
@@ -51,10 +51,9 @@ export default function Integration({ config, params, setEvents, hideErrors, tim
title = `${config.name}: ${title}`;
}
- // 'dtend' is null for all-day events
- const { dtstart, dtend = { value: 0 } } = event;
-
const eventToAdd = (date, i, type) => {
+ // 'dtend' is null for all-day events
+ const { dtstart, dtend = { value: 0 } } = event;
const days = dtend.value === 0 ? 1 : (dtend.value - dtstart.value) / (1000 * 60 * 60 * 24);
const eventDate = timezone ? DateTime.fromJSDate(date, { zone: timezone }) : DateTime.fromJSDate(date);
@@ -73,28 +72,13 @@ export default function Integration({ config, params, setEvents, hideErrors, tim
}
};
- let recurrenceOptions = event?.recurrenceRule?.origOptions;
- // RRuleSet does not have dtstart, add it manually
- if (event?.recurrenceRule && event.recurrenceRule.rrules && event.recurrenceRule.rrules()?.[0]?.origOptions) {
- recurrenceOptions = event.recurrenceRule.rrules()[0].origOptions;
- recurrenceOptions.dtstart = dtstart.value;
- }
-
+ const recurrenceOptions = event?.recurrenceRule?.origOptions;
if (recurrenceOptions && Object.keys(recurrenceOptions).length !== 0) {
try {
const rule = new RRule(recurrenceOptions);
const recurringEvents = rule.between(startDate.toJSDate(), endDate.toJSDate());
- recurringEvents.forEach((date, i) => {
- let eventDate = date;
- if (event.dtstart?.params?.tzid) {
- // date is in UTC but parsed as if it is in current timezone, so we need to adjust it
- const dateInUTC = DateTime.fromJSDate(date).setZone("UTC");
- const offset = dateInUTC.offset - DateTime.fromJSDate(date, { zone: event.dtstart.params.tzid }).offset;
- eventDate = dateInUTC.plus({ minutes: offset }).toJSDate();
- }
- eventToAdd(eventDate, i, "recurring");
- });
+ recurringEvents.forEach((date, i) => eventToAdd(date, i, "recurring"));
return;
} catch (e) {
// eslint-disable-next-line no-console
diff --git a/src/widgets/calendar/integrations/lidarr.jsx b/src/widgets/calendar/integrations/lidarr.jsx
index 65ad1da2..d4a6edbe 100644
--- a/src/widgets/calendar/integrations/lidarr.jsx
+++ b/src/widgets/calendar/integrations/lidarr.jsx
@@ -1,8 +1,8 @@
import { DateTime } from "luxon";
import { useEffect } from "react";
-import Error from "../../../components/services/widget/error";
import useWidgetAPI from "../../../utils/proxy/use-widget-api";
+import Error from "../../../components/services/widget/error";
export default function Integration({ config, params, setEvents, hideErrors = false }) {
const { data: lidarrData, error: lidarrError } = useWidgetAPI(config, "calendar", {
diff --git a/src/widgets/calendar/integrations/radarr.jsx b/src/widgets/calendar/integrations/radarr.jsx
index 9c8880a9..945eadd9 100644
--- a/src/widgets/calendar/integrations/radarr.jsx
+++ b/src/widgets/calendar/integrations/radarr.jsx
@@ -1,9 +1,9 @@
import { DateTime } from "luxon";
-import { useTranslation } from "next-i18next";
import { useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Error from "../../../components/services/widget/error";
import useWidgetAPI from "../../../utils/proxy/use-widget-api";
+import Error from "../../../components/services/widget/error";
export default function Integration({ config, params, setEvents, hideErrors = false }) {
const { t } = useTranslation();
diff --git a/src/widgets/calendar/integrations/readarr.jsx b/src/widgets/calendar/integrations/readarr.jsx
index 4fe3872e..6ae919ef 100644
--- a/src/widgets/calendar/integrations/readarr.jsx
+++ b/src/widgets/calendar/integrations/readarr.jsx
@@ -1,8 +1,8 @@
import { DateTime } from "luxon";
import { useEffect } from "react";
-import Error from "../../../components/services/widget/error";
import useWidgetAPI from "../../../utils/proxy/use-widget-api";
+import Error from "../../../components/services/widget/error";
export default function Integration({ config, params, setEvents, hideErrors = false }) {
const { data: readarrData, error: readarrError } = useWidgetAPI(config, "calendar", {
diff --git a/src/widgets/calendar/integrations/sonarr.jsx b/src/widgets/calendar/integrations/sonarr.jsx
index abdec328..34cc679d 100644
--- a/src/widgets/calendar/integrations/sonarr.jsx
+++ b/src/widgets/calendar/integrations/sonarr.jsx
@@ -1,8 +1,8 @@
import { DateTime } from "luxon";
import { useEffect } from "react";
-import Error from "../../../components/services/widget/error";
import useWidgetAPI from "../../../utils/proxy/use-widget-api";
+import Error from "../../../components/services/widget/error";
export default function Integration({ config, params, setEvents, hideErrors = false }) {
const { data: sonarrData, error: sonarrError } = useWidgetAPI(config, "calendar", {
diff --git a/src/widgets/calendar/monthly.jsx b/src/widgets/calendar/monthly.jsx
index 4e870261..a102e8da 100644
--- a/src/widgets/calendar/monthly.jsx
+++ b/src/widgets/calendar/monthly.jsx
@@ -1,7 +1,7 @@
-import classNames from "classnames";
-import { DateTime, Info } from "luxon";
-import { useTranslation } from "next-i18next";
import { useMemo } from "react";
+import { DateTime, Info } from "luxon";
+import classNames from "classnames";
+import { useTranslation } from "next-i18next";
import Event, { compareDateTimezone } from "./event";
@@ -57,7 +57,7 @@ export function Day({ weekNumber, weekday, events, colorVariants, showDate, setS
.map((event) => (
))}
diff --git a/src/widgets/calendar/proxy.js b/src/widgets/calendar/proxy.js
index c98441ee..d36f30c9 100644
--- a/src/widgets/calendar/proxy.js
+++ b/src/widgets/calendar/proxy.js
@@ -1,6 +1,6 @@
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { httpProxy } from "utils/proxy/http";
+import createLogger from "utils/logger";
const logger = createLogger("calendarProxyHandler");
diff --git a/src/widgets/calibreweb/component.jsx b/src/widgets/calibreweb/component.jsx
index be8424e5..acb9e029 100644
--- a/src/widgets/calibreweb/component.jsx
+++ b/src/widgets/calibreweb/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/changedetectionio/component.jsx b/src/widgets/changedetectionio/component.jsx
index d7d7272b..caef8655 100644
--- a/src/widgets/changedetectionio/component.jsx
+++ b/src/widgets/changedetectionio/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/channelsdvrserver/component.jsx b/src/widgets/channelsdvrserver/component.jsx
index 79ca3f14..52e94c29 100644
--- a/src/widgets/channelsdvrserver/component.jsx
+++ b/src/widgets/channelsdvrserver/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/cloudflared/component.jsx b/src/widgets/cloudflared/component.jsx
index 790a5f34..e9200171 100644
--- a/src/widgets/cloudflared/component.jsx
+++ b/src/widgets/cloudflared/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/coinmarketcap/component.jsx b/src/widgets/coinmarketcap/component.jsx
index fd9c030f..7e717bef 100644
--- a/src/widgets/coinmarketcap/component.jsx
+++ b/src/widgets/coinmarketcap/component.jsx
@@ -1,10 +1,10 @@
-import classNames from "classnames";
-import Dropdown from "components/services/dropdown";
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
import { useState } from "react";
+import { useTranslation } from "next-i18next";
+import classNames from "classnames";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
+import Dropdown from "components/services/dropdown";
import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
@@ -73,7 +73,7 @@ export default function Component({ service }) {
{validCryptos.map((crypto) => (
{crypto.name}
diff --git a/src/widgets/components.js b/src/widgets/components.js
index 880c8222..19f41d4a 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -2,7 +2,6 @@ import dynamic from "next/dynamic";
const components = {
adguard: dynamic(() => import("./adguard/component")),
- apcups: dynamic(() => import("./apcups/component")),
argocd: dynamic(() => import("./argocd/component")),
atsumeru: dynamic(() => import("./atsumeru/component")),
audiobookshelf: dynamic(() => import("./audiobookshelf/component")),
@@ -31,7 +30,6 @@ const components = {
esphome: dynamic(() => import("./esphome/component")),
evcc: dynamic(() => import("./evcc/component")),
fileflows: dynamic(() => import("./fileflows/component")),
- firefly: dynamic(() => import("./firefly/component")),
flood: dynamic(() => import("./flood/component")),
freshrss: dynamic(() => import("./freshrss/component")),
frigate: dynamic(() => import("./frigate/component")),
@@ -47,8 +45,6 @@ const components = {
grafana: dynamic(() => import("./grafana/component")),
hdhomerun: dynamic(() => import("./hdhomerun/component")),
headscale: dynamic(() => import("./headscale/component")),
- hoarder: dynamic(() => import("./karakeep/component")),
- karakeep: dynamic(() => import("./karakeep/component")),
peanut: dynamic(() => import("./peanut/component")),
homeassistant: dynamic(() => import("./homeassistant/component")),
homebox: dynamic(() => import("./homebox/component")),
@@ -114,7 +110,6 @@ const components = {
rutorrent: dynamic(() => import("./rutorrent/component")),
sabnzbd: dynamic(() => import("./sabnzbd/component")),
scrutiny: dynamic(() => import("./scrutiny/component")),
- slskd: dynamic(() => import("./slskd/component")),
sonarr: dynamic(() => import("./sonarr/component")),
speedtest: dynamic(() => import("./speedtest/component")),
spoolman: dynamic(() => import("./spoolman/component")),
diff --git a/src/widgets/crowdsec/component.jsx b/src/widgets/crowdsec/component.jsx
index f567ad70..2e98cee9 100644
--- a/src/widgets/crowdsec/component.jsx
+++ b/src/widgets/crowdsec/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/crowdsec/proxy.js b/src/widgets/crowdsec/proxy.js
index d3257fa6..85803845 100644
--- a/src/widgets/crowdsec/proxy.js
+++ b/src/widgets/crowdsec/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "crowdsecProxyHandler";
diff --git a/src/widgets/customapi/component.jsx b/src/widgets/customapi/component.jsx
index f537e8da..3f1825b2 100644
--- a/src/widgets/customapi/component.jsx
+++ b/src/widgets/customapi/component.jsx
@@ -1,9 +1,7 @@
-import classNames from "classnames";
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
-import * as shvl from "utils/config/shvl";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
function getValue(field, data) {
@@ -16,11 +14,6 @@ function getValue(field, data) {
return value;
}
- // shvl is easier, everything else is kept for backwards compatibility.
- if (typeof field === "string") {
- return shvl.get(data, field, null) ?? data[field] ?? null;
- }
-
while (typeof lastField === "object") {
key = Object.keys(lastField)[0] ?? null;
@@ -85,9 +78,6 @@ function formatValue(t, mapping, rawValue) {
case "percent":
value = t("common.percent", { value });
break;
- case "duration":
- value = t("common.duration", { value });
- break;
case "bytes":
value = t("common.bytes", { value });
break;
@@ -172,16 +162,6 @@ export default function Component({ service }) {
if (!customData) {
switch (display) {
- case "dynamic-list":
- return (
-
-
-
- );
case "list":
return (
@@ -189,7 +169,7 @@ export default function Component({ service }) {
{mappings.map((mapping) => (
{mapping.label}
@@ -213,76 +193,6 @@ export default function Component({ service }) {
}
switch (display) {
- case "dynamic-list":
- let listItems = customData;
- if (mappings.items) listItems = shvl.get(customData, mappings.items, null);
- let error;
- if (!listItems || !Array.isArray(listItems)) {
- error = { message: "Unable to find items" };
- }
- const name = mappings.name;
- const label = mappings.label;
- if (!name || !label) {
- error = { message: "Name and label properties are required" };
- }
- if (error) {
- return
;
- }
-
- const target = mappings.target;
- if (mappings.limit && parseInt(mappings.limit, 10) > 0) {
- listItems.splice(mappings.limit);
- }
-
- return (
-
-
- {listItems.length === 0 ? (
-
- ) : (
- listItems.map((item, index) => {
- const itemName = shvl.get(item, name, item[name]) ?? "";
- const itemLabel = shvl.get(item, label, item[label]) ?? "";
-
- const itemUrl = target
- ? [...target.matchAll(/\{(.*?)\}/g)]
- .map((match) => match[1])
- .reduce((url, targetTemplate) => {
- const value = shvl.get(item, targetTemplate, item[targetTemplate]) ?? "";
- return url.replaceAll(`{${targetTemplate}}`, value);
- }, target)
- : null;
- const className =
- "bg-theme-200/50 dark:bg-theme-900/20 rounded-sm m-1 flex-1 flex flex-row items-center justify-between p-1 text-xs";
-
- return itemUrl ? (
-
- {itemName}
-
-
{formatValue(t, mappings, itemLabel)}
-
-
- ) : (
-
-
{itemName}
-
-
{formatValue(t, mappings, itemLabel)}
-
-
- );
- })
- )}
-
-
- );
case "list":
return (
@@ -290,7 +200,7 @@ export default function Component({ service }) {
{mappings.map((mapping) => (
{mapping.label}
diff --git a/src/widgets/deluge/component.jsx b/src/widgets/deluge/component.jsx
index eb6ddfaa..231f69ab 100644
--- a/src/widgets/deluge/component.jsx
+++ b/src/widgets/deluge/component.jsx
@@ -1,9 +1,9 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import QueueEntry from "../../components/widgets/queue/queueEntry";
+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 }) {
diff --git a/src/widgets/deluge/proxy.js b/src/widgets/deluge/proxy.js
index ef255160..0430a6ac 100644
--- a/src/widgets/deluge/proxy.js
+++ b/src/widgets/deluge/proxy.js
@@ -1,7 +1,7 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
import { sendJsonRpcRequest } from "utils/proxy/handlers/jsonrpc";
+import getServiceWidget from "utils/config/service-helpers";
+import createLogger from "utils/logger";
import widgets from "widgets/widgets";
const logger = createLogger("delugeProxyHandler");
diff --git a/src/widgets/develancacheui/component.jsx b/src/widgets/develancacheui/component.jsx
index 61f608e1..b13852c6 100644
--- a/src/widgets/develancacheui/component.jsx
+++ b/src/widgets/develancacheui/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/diskstation/component.jsx b/src/widgets/diskstation/component.jsx
index 0ca0b8ae..26550466 100644
--- a/src/widgets/diskstation/component.jsx
+++ b/src/widgets/diskstation/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
@@ -43,9 +43,8 @@ export default function Component({ service }) {
// utilization info
const { cpu, memory } = utilizationData.data;
const cpuLoad = parseFloat(cpu.user_load) + parseFloat(cpu.system_load);
- const memoryUsage = memory.real_usage
- ? parseFloat(memory.real_usage)
- : 100 - (100 * (parseFloat(memory.avail_real) + parseFloat(memory.cached))) / parseFloat(memory.total_real);
+ const memoryUsage =
+ 100 - (100 * (parseFloat(memory.avail_real) + parseFloat(memory.cached))) / parseFloat(memory.total_real);
return (
diff --git a/src/widgets/docker/component.jsx b/src/widgets/docker/component.jsx
index 6e05454f..9535d3bd 100644
--- a/src/widgets/docker/component.jsx
+++ b/src/widgets/docker/component.jsx
@@ -1,9 +1,10 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
import useSWR from "swr";
+import { useTranslation } from "next-i18next";
-import { calculateCPUPercent, calculateThroughput, calculateUsedMemory } from "./stats-helpers";
+import { calculateCPUPercent, calculateUsedMemory, calculateThroughput } from "./stats-helpers";
+
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
export default function Component({ service }) {
const { t } = useTranslation();
diff --git a/src/widgets/downloadstation/component.jsx b/src/widgets/downloadstation/component.jsx
index 016f4953..aae4713d 100644
--- a/src/widgets/downloadstation/component.jsx
+++ b/src/widgets/downloadstation/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/emby/component.jsx b/src/widgets/emby/component.jsx
index 88858da2..6f66d1dc 100644
--- a/src/widgets/emby/component.jsx
+++ b/src/widgets/emby/component.jsx
@@ -1,9 +1,9 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
-import { BsCpu, BsFillCpuFill, BsFillPlayFill, BsPauseFill, BsVolumeMuteFill } from "react-icons/bs";
+import { BsVolumeMuteFill, BsFillPlayFill, BsPauseFill, BsCpu, BsFillCpuFill } from "react-icons/bs";
import { MdOutlineSmartDisplay } from "react-icons/md";
+import Block from "components/services/widget/block";
+import Container from "components/services/widget/container";
import { getURLSearchParams } from "utils/proxy/api-helpers";
import useWidgetAPI from "utils/proxy/use-widget-api";
@@ -35,8 +35,8 @@ function generateStreamTitle(session, enableUser, showEpisodeNumber) {
let streamTitle = "";
if (Type === "Episode" && showEpisodeNumber) {
- const seasonStr = ParentIndexNumber ? `S${ParentIndexNumber.toString().padStart(2, "0")}` : "";
- const episodeStr = IndexNumber ? `E${IndexNumber.toString().padStart(2, "0")}` : "";
+ const seasonStr = `S${ParentIndexNumber.toString().padStart(2, "0")}`;
+ const episodeStr = `E${IndexNumber.toString().padStart(2, "0")}`;
streamTitle = `${SeriesName}: ${seasonStr} · ${episodeStr} - ${Name}`;
} else {
streamTitle = `${Name}${SeriesName ? ` - ${SeriesName}` : ""}`;
diff --git a/src/widgets/esphome/component.jsx b/src/widgets/esphome/component.jsx
index e0f02089..ea2e5db3 100644
--- a/src/widgets/esphome/component.jsx
+++ b/src/widgets/esphome/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
+import Block from "components/services/widget/block";
+import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
diff --git a/src/widgets/evcc/component.jsx b/src/widgets/evcc/component.jsx
index d0debdc3..09a8ffe4 100644
--- a/src/widgets/evcc/component.jsx
+++ b/src/widgets/evcc/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
function toKilowatts(t, value) {
@@ -29,13 +29,10 @@ export default function Component({ service }) {
);
}
- // broken by evcc v0.133.0 https://github.com/evcc-io/evcc/commit/9dcb1fa0a7c08dd926b79309aa1f676a5fc6c8aa
- const gridPower = stateData.result.gridPower ?? stateData.result.grid?.power ?? 0;
-
return (
-
+
;
- }
-
- if (!summaryData || !budgetData) {
- return (
-
-
-
-
- );
- }
-
- const netWorth = Object.keys(summaryData)
- .filter((key) => key.includes("net-worth-in"))
- .map((key) => summaryData[key]);
-
- let budgetValue = null;
-
- if (budgetData.data?.length && budgetData.data[0].type === "available_budgets") {
- const budgetAmount = parseFloat(budgetData.data[0].attributes.amount);
- const budgetSpent = -parseFloat(budgetData.data[0].attributes.spent_in_budgets[0]?.sum ?? "0");
- const budgetCurrency = budgetData.data[0].attributes.currency_symbol;
-
- budgetValue = `${budgetCurrency} ${t("common.number", {
- value: budgetSpent,
- minimumFractionDigits: 2,
- })} / ${budgetCurrency} ${t("common.number", {
- value: budgetAmount,
- minimumFractionDigits: 2,
- })}`;
- }
-
- return (
-
-
-
-
- );
-}
diff --git a/src/widgets/firefly/widget.js b/src/widgets/firefly/widget.js
deleted file mode 100644
index cd23504d..00000000
--- a/src/widgets/firefly/widget.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
-
-const widget = {
- api: "{url}/api/{endpoint}",
- proxyHandler: credentialedProxyHandler,
-
- mappings: {
- summary: {
- endpoint: "v1/summary/basic",
- params: ["start", "end"],
- },
- budgets: {
- endpoint: "v1/available-budgets",
- params: ["start", "end"],
- },
- },
-};
-
-export default widget;
diff --git a/src/widgets/flood/component.jsx b/src/widgets/flood/component.jsx
index 92a2b61a..4ecdcbcd 100644
--- a/src/widgets/flood/component.jsx
+++ b/src/widgets/flood/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/flood/proxy.js b/src/widgets/flood/proxy.js
index 5e5335ae..e0c10173 100644
--- a/src/widgets/flood/proxy.js
+++ b/src/widgets/flood/proxy.js
@@ -1,7 +1,7 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
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("floodProxyHandler");
diff --git a/src/widgets/freshrss/component.jsx b/src/widgets/freshrss/component.jsx
index 70833e1d..788f1f6f 100644
--- a/src/widgets/freshrss/component.jsx
+++ b/src/widgets/freshrss/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/freshrss/proxy.js b/src/widgets/freshrss/proxy.js
index 6168db86..881094bd 100644
--- a/src/widgets/freshrss/proxy.js
+++ b/src/widgets/freshrss/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "freshrssProxyHandler";
diff --git a/src/widgets/frigate/component.jsx b/src/widgets/frigate/component.jsx
index ab67c461..ac77be51 100644
--- a/src/widgets/frigate/component.jsx
+++ b/src/widgets/frigate/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/fritzbox/component.jsx b/src/widgets/fritzbox/component.jsx
index d7928c20..c3ea1bf6 100644
--- a/src/widgets/fritzbox/component.jsx
+++ b/src/widgets/fritzbox/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 const fritzboxDefaultFields = ["connectionStatus", "uptime", "maxDown", "maxUp"];
@@ -37,8 +37,6 @@ export default function Component({ service }) {
-
-
);
}
@@ -54,8 +52,6 @@ export default function Component({ service }) {
-
-
);
}
diff --git a/src/widgets/fritzbox/proxy.js b/src/widgets/fritzbox/proxy.js
index c8c57fbc..d1a66d97 100644
--- a/src/widgets/fritzbox/proxy.js
+++ b/src/widgets/fritzbox/proxy.js
@@ -2,9 +2,9 @@ import { xml2json } from "xml-js";
import { fritzboxDefaultFields } from "./component";
+import { httpProxy } from "utils/proxy/http";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { httpProxy } from "utils/proxy/http";
const logger = createLogger("fritzboxProxyHandler");
@@ -70,21 +70,14 @@ export default async function fritzboxProxyHandler(req, res) {
const requestLinkProperties = ["maxDown", "maxUp"].some((field) => serviceWidget.fields.includes(field));
const requestAddonInfos = ["down", "up", "received", "sent"].some((field) => serviceWidget.fields.includes(field));
const requestExternalIPAddress = ["externalIPAddress"].some((field) => serviceWidget.fields.includes(field));
- const requestExternalIPv6Address = ["externalIPv6Address"].some((field) => serviceWidget.fields.includes(field));
- const requestExternalIPv6Prefix = ["externalIPv6Prefix"].some((field) => serviceWidget.fields.includes(field));
await Promise.all([
- // as per http://fritz.box:49000/igddesc.xml specifications (fritz.box is a hostname of your router)
requestStatusInfo ? requestEndpoint(apiBaseUrl, "WANIPConnection", "GetStatusInfo") : null,
requestLinkProperties ? requestEndpoint(apiBaseUrl, "WANCommonInterfaceConfig", "GetCommonLinkProperties") : null,
requestAddonInfos ? requestEndpoint(apiBaseUrl, "WANCommonInterfaceConfig", "GetAddonInfos") : null,
requestExternalIPAddress ? requestEndpoint(apiBaseUrl, "WANIPConnection", "GetExternalIPAddress") : null,
- requestExternalIPv6Address
- ? requestEndpoint(apiBaseUrl, "WANIPConnection", "X_AVM_DE_GetExternalIPv6Address")
- : null,
- requestExternalIPv6Prefix ? requestEndpoint(apiBaseUrl, "WANIPConnection", "X_AVM_DE_GetIPv6Prefix") : null,
])
- .then(([statusInfo, linkProperties, addonInfos, externalIPAddress, externalIPv6Address, externalIPv6Prefix]) => {
+ .then(([statusInfo, linkProperties, addonInfos, externalIPAddress]) => {
res.status(200).json({
connectionStatus: statusInfo?.NewConnectionStatus || "Unconfigured",
uptime: statusInfo?.NewUptime || 0,
@@ -95,8 +88,6 @@ export default async function fritzboxProxyHandler(req, res) {
received: addonInfos?.NewX_AVM_DE_TotalBytesReceived64 || 0,
sent: addonInfos?.NewX_AVM_DE_TotalBytesSent64 || 0,
externalIPAddress: externalIPAddress?.NewExternalIPAddress || null,
- externalIPv6Address: externalIPv6Address?.NewExternalIPv6Address || null,
- externalIPv6Prefix: externalIPv6Prefix?.NewIPv6Prefix || null,
});
})
.catch((error) => {
diff --git a/src/widgets/gamedig/component.jsx b/src/widgets/gamedig/component.jsx
index 5acd1b9c..69b78d9a 100644
--- a/src/widgets/gamedig/component.jsx
+++ b/src/widgets/gamedig/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/gamedig/proxy.js b/src/widgets/gamedig/proxy.js
index 79d7fa02..ecf6e4c6 100644
--- a/src/widgets/gamedig/proxy.js
+++ b/src/widgets/gamedig/proxy.js
@@ -1,7 +1,7 @@
import { GameDig } from "gamedig";
-import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
+import getServiceWidget from "utils/config/service-helpers";
const proxyName = "gamedigProxyHandler";
const logger = createLogger(proxyName);
@@ -24,7 +24,7 @@ export default async function gamedigProxyHandler(req, res) {
online: true,
name: serverData.name,
map: serverData.map,
- players: serverData.numplayers ?? serverData.players?.length,
+ players: serverData.players.length,
maxplayers: serverData.maxplayers,
bots: serverData.bots.length,
ping: serverData.ping,
diff --git a/src/widgets/gatus/component.jsx b/src/widgets/gatus/component.jsx
index 25aae239..86b85ff3 100644
--- a/src/widgets/gatus/component.jsx
+++ b/src/widgets/gatus/component.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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();
diff --git a/src/widgets/ghostfolio/component.jsx b/src/widgets/ghostfolio/component.jsx
index f2587586..183b05ca 100644
--- a/src/widgets/ghostfolio/component.jsx
+++ b/src/widgets/ghostfolio/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
function getPerformancePercent(t, performanceRange) {
diff --git a/src/widgets/gitea/component.jsx b/src/widgets/gitea/component.jsx
index 81b69d67..b193efd2 100644
--- a/src/widgets/gitea/component.jsx
+++ b/src/widgets/gitea/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
@@ -8,21 +7,17 @@ export default function Component({ service }) {
const { data: giteaNotifications, error: giteaNotificationsError } = useWidgetAPI(widget, "notifications");
const { data: giteaIssues, error: giteaIssuesError } = useWidgetAPI(widget, "issues");
- const { data: giteaRepositories, error: giteaRepositoriesError } = useWidgetAPI(widget, "repositories");
- if (giteaNotificationsError || giteaIssuesError || giteaRepositoriesError) {
- return (
-
- );
+ if (giteaNotificationsError || giteaIssuesError) {
+ return
;
}
- if (!giteaNotifications || !giteaIssues || !giteaRepositories) {
+ if (!giteaNotifications || !giteaIssues) {
return (
-
);
}
@@ -32,7 +27,6 @@ export default function Component({ service }) {
-
);
}
diff --git a/src/widgets/gitea/widget.js b/src/widgets/gitea/widget.js
index b0420ccc..32871b00 100644
--- a/src/widgets/gitea/widget.js
+++ b/src/widgets/gitea/widget.js
@@ -16,9 +16,6 @@ const widget = {
issues: asJson(data).filter((issue) => !issue.pull_request),
}),
},
- repositories: {
- endpoint: "repos/search",
- },
},
};
diff --git a/src/widgets/gitlab/component.jsx b/src/widgets/gitlab/component.jsx
index 4d2805ba..fb6f898f 100644
--- a/src/widgets/gitlab/component.jsx
+++ b/src/widgets/gitlab/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/glances/component.jsx b/src/widgets/glances/component.jsx
index 4ca0cc72..bff31ac1 100644
--- a/src/widgets/glances/component.jsx
+++ b/src/widgets/glances/component.jsx
@@ -1,13 +1,13 @@
-import Containers from "./metrics/containers";
-import Cpu from "./metrics/cpu";
-import Disk from "./metrics/disk";
-import Fs from "./metrics/fs";
-import GPU from "./metrics/gpu";
-import Info from "./metrics/info";
import Memory from "./metrics/memory";
+import Cpu from "./metrics/cpu";
+import Sensor from "./metrics/sensor";
import Net from "./metrics/net";
import Process from "./metrics/process";
-import Sensor from "./metrics/sensor";
+import Disk from "./metrics/disk";
+import GPU from "./metrics/gpu";
+import Info from "./metrics/info";
+import Fs from "./metrics/fs";
+import Containers from "./metrics/containers";
export default function Component({ service }) {
const { widget } = service;
diff --git a/src/widgets/glances/components/chart.jsx b/src/widgets/glances/components/chart.jsx
index b919a92d..132fcc8e 100644
--- a/src/widgets/glances/components/chart.jsx
+++ b/src/widgets/glances/components/chart.jsx
@@ -1,5 +1,5 @@
import { PureComponent } from "react";
-import { Area, AreaChart, ResponsiveContainer, Tooltip } from "recharts";
+import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
import CustomTooltip from "./custom_tooltip";
diff --git a/src/widgets/glances/components/chart_dual.jsx b/src/widgets/glances/components/chart_dual.jsx
index d6ec2076..5fabe755 100644
--- a/src/widgets/glances/components/chart_dual.jsx
+++ b/src/widgets/glances/components/chart_dual.jsx
@@ -1,5 +1,5 @@
import { PureComponent } from "react";
-import { Area, AreaChart, ResponsiveContainer, Tooltip } from "recharts";
+import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts";
import CustomTooltip from "./custom_tooltip";
diff --git a/src/widgets/glances/components/container.jsx b/src/widgets/glances/components/container.jsx
index 7bcd5c46..01a7e05d 100644
--- a/src/widgets/glances/components/container.jsx
+++ b/src/widgets/glances/components/container.jsx
@@ -1,9 +1,10 @@
-import classNames from "classnames";
import { useContext } from "react";
-import { SettingsContext } from "utils/contexts/settings";
+import classNames from "classnames";
import Error from "./error";
+import { SettingsContext } from "utils/contexts/settings";
+
export default function Container({ children, widget, error = null, chart = true, className = "" }) {
const { settings } = useContext(SettingsContext);
const hideErrors = settings.hideErrors || widget?.hideErrors;
diff --git a/src/widgets/glances/metrics/containers.jsx b/src/widgets/glances/metrics/containers.jsx
index 93ecbc28..1f408d3e 100644
--- a/src/widgets/glances/metrics/containers.jsx
+++ b/src/widgets/glances/metrics/containers.jsx
@@ -1,10 +1,10 @@
-import ResolvedIcon from "components/resolvedicon";
import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
+import ResolvedIcon from "components/resolvedicon";
const statusMap = {
running:
,
@@ -65,7 +65,7 @@ export default function Component({ service }) {
{item.cpu_percent.toFixed(1)}%
{t("common.bytes", {
- value: item.memory.usage - item.memory.inactive_file,
+ value: item.memory.usage,
maximumFractionDigits: 0,
})}
diff --git a/src/widgets/glances/metrics/cpu.jsx b/src/widgets/glances/metrics/cpu.jsx
index 3debf11a..e993fca9 100644
--- a/src/widgets/glances/metrics/cpu.jsx
+++ b/src/widgets/glances/metrics/cpu.jsx
@@ -1,9 +1,9 @@
-import { useTranslation } from "next-i18next";
import dynamic from "next/dynamic";
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
diff --git a/src/widgets/glances/metrics/disk.jsx b/src/widgets/glances/metrics/disk.jsx
index 69dd2d99..0a459e07 100644
--- a/src/widgets/glances/metrics/disk.jsx
+++ b/src/widgets/glances/metrics/disk.jsx
@@ -1,9 +1,9 @@
-import { useTranslation } from "next-i18next";
import dynamic from "next/dynamic";
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
diff --git a/src/widgets/glances/metrics/fs.jsx b/src/widgets/glances/metrics/fs.jsx
index 317a781f..3285bd0e 100644
--- a/src/widgets/glances/metrics/fs.jsx
+++ b/src/widgets/glances/metrics/fs.jsx
@@ -1,7 +1,7 @@
import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
@@ -46,9 +46,9 @@ export default function Component({ service }) {
)}
diff --git a/src/widgets/glances/metrics/gpu.jsx b/src/widgets/glances/metrics/gpu.jsx
index 7eab536c..37b06ce3 100644
--- a/src/widgets/glances/metrics/gpu.jsx
+++ b/src/widgets/glances/metrics/gpu.jsx
@@ -1,9 +1,9 @@
-import { useTranslation } from "next-i18next";
import dynamic from "next/dynamic";
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
diff --git a/src/widgets/glances/metrics/info.jsx b/src/widgets/glances/metrics/info.jsx
index 3c0ef429..3fc7ab23 100644
--- a/src/widgets/glances/metrics/info.jsx
+++ b/src/widgets/glances/metrics/info.jsx
@@ -1,7 +1,7 @@
import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
@@ -109,7 +109,7 @@ export default function Component({ service }) {
return (
{chart && (
-
+
)}
diff --git a/src/widgets/glances/metrics/memory.jsx b/src/widgets/glances/metrics/memory.jsx
index e5fbc350..8cfddb66 100644
--- a/src/widgets/glances/metrics/memory.jsx
+++ b/src/widgets/glances/metrics/memory.jsx
@@ -1,9 +1,9 @@
-import { useTranslation } from "next-i18next";
import dynamic from "next/dynamic";
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
diff --git a/src/widgets/glances/metrics/net.jsx b/src/widgets/glances/metrics/net.jsx
index 2bdd491c..372c4ec6 100644
--- a/src/widgets/glances/metrics/net.jsx
+++ b/src/widgets/glances/metrics/net.jsx
@@ -1,9 +1,9 @@
-import { useTranslation } from "next-i18next";
import dynamic from "next/dynamic";
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
diff --git a/src/widgets/glances/metrics/process.jsx b/src/widgets/glances/metrics/process.jsx
index ad3fee54..997948f4 100644
--- a/src/widgets/glances/metrics/process.jsx
+++ b/src/widgets/glances/metrics/process.jsx
@@ -1,10 +1,10 @@
-import ResolvedIcon from "components/resolvedicon";
import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
+import ResolvedIcon from "components/resolvedicon";
const statusMap = {
R: , // running
diff --git a/src/widgets/glances/metrics/sensor.jsx b/src/widgets/glances/metrics/sensor.jsx
index b5a16d10..3cb38c1c 100644
--- a/src/widgets/glances/metrics/sensor.jsx
+++ b/src/widgets/glances/metrics/sensor.jsx
@@ -1,9 +1,9 @@
-import { useTranslation } from "next-i18next";
import dynamic from "next/dynamic";
-import { useEffect, useState } from "react";
+import { useState, useEffect } from "react";
+import { useTranslation } from "next-i18next";
-import Block from "../components/block";
import Container from "../components/container";
+import Block from "../components/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
diff --git a/src/widgets/gluetun/component.jsx b/src/widgets/gluetun/component.jsx
index f7128237..c4ec14fb 100644
--- a/src/widgets/gluetun/component.jsx
+++ b/src/widgets/gluetun/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/gotify/component.jsx b/src/widgets/gotify/component.jsx
index 6cf9cea9..39664a31 100644
--- a/src/widgets/gotify/component.jsx
+++ b/src/widgets/gotify/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/grafana/component.jsx b/src/widgets/grafana/component.jsx
index 82d6e5c9..ecedac8e 100755
--- a/src/widgets/grafana/component.jsx
+++ b/src/widgets/grafana/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/hdhomerun/component.jsx b/src/widgets/hdhomerun/component.jsx
index 2532f92b..a118eafe 100644
--- a/src/widgets/hdhomerun/component.jsx
+++ b/src/widgets/hdhomerun/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/headscale/component.jsx b/src/widgets/headscale/component.jsx
index acee3a82..361aa756 100644
--- a/src/widgets/headscale/component.jsx
+++ b/src/widgets/headscale/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/healthchecks/component.jsx b/src/widgets/healthchecks/component.jsx
index b65f91c5..21fb7cb6 100644
--- a/src/widgets/healthchecks/component.jsx
+++ b/src/widgets/healthchecks/component.jsx
@@ -1,9 +1,9 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import { i18n } from "../../../next-i18next.config";
+import Block from "components/services/widget/block";
+import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";
function formatDate(dateString) {
diff --git a/src/widgets/homeassistant/component.jsx b/src/widgets/homeassistant/component.jsx
index 1df415ae..af75a664 100644
--- a/src/widgets/homeassistant/component.jsx
+++ b/src/widgets/homeassistant/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/homeassistant/proxy.js b/src/widgets/homeassistant/proxy.js
index 7702eb5d..e1f02ddb 100644
--- a/src/widgets/homeassistant/proxy.js
+++ b/src/widgets/homeassistant/proxy.js
@@ -1,6 +1,6 @@
+import { httpProxy } from "utils/proxy/http";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { httpProxy } from "utils/proxy/http";
const logger = createLogger("homeassistantProxyHandler");
diff --git a/src/widgets/homebox/component.jsx b/src/widgets/homebox/component.jsx
index 4c550748..18ea520e 100644
--- a/src/widgets/homebox/component.jsx
+++ b/src/widgets/homebox/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 const homeboxDefaultFields = ["items", "locations", "totalValue"];
diff --git a/src/widgets/homebox/proxy.js b/src/widgets/homebox/proxy.js
index 8a4550fc..c91ce552 100644
--- a/src/widgets/homebox/proxy.js
+++ b/src/widgets/homebox/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
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 proxyName = "homeboxProxyHandler";
const sessionTokenCacheKey = `${proxyName}__sessionToken`;
diff --git a/src/widgets/homebridge/component.jsx b/src/widgets/homebridge/component.jsx
index 6201b70b..3237423e 100644
--- a/src/widgets/homebridge/component.jsx
+++ b/src/widgets/homebridge/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/homebridge/proxy.js b/src/widgets/homebridge/proxy.js
index 675e2976..4da9197b 100644
--- a/src/widgets/homebridge/proxy.js
+++ b/src/widgets/homebridge/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "homebridgeProxyHandler";
diff --git a/src/widgets/iframe/component.jsx b/src/widgets/iframe/component.jsx
index 9d2d60ca..21075dbe 100644
--- a/src/widgets/iframe/component.jsx
+++ b/src/widgets/iframe/component.jsx
@@ -1,6 +1,7 @@
+import { useState, useEffect } from "react";
import classNames from "classnames";
+
import Container from "components/services/widget/container";
-import { useEffect, useState } from "react";
export default function Component({ service }) {
const [refreshTimer, setRefreshTimer] = useState(0);
@@ -24,7 +25,7 @@ export default function Component({ service }) {
@@ -41,7 +42,7 @@ export default function Component({ service }) {
style={{
scrollingDisableStyle,
}}
- className={`rounded-sm w-full ${classes}`}
+ className={`rounded w-full ${classes}`}
/>
diff --git a/src/widgets/immich/component.jsx b/src/widgets/immich/component.jsx
index a38cac1e..ed27d4d8 100644
--- a/src/widgets/immich/component.jsx
+++ b/src/widgets/immich/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/jackett/component.jsx b/src/widgets/jackett/component.jsx
index 63e3e1c3..122e5012 100644
--- a/src/widgets/jackett/component.jsx
+++ b/src/widgets/jackett/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/jackett/proxy.js b/src/widgets/jackett/proxy.js
index 10e85175..035309b3 100644
--- a/src/widgets/jackett/proxy.js
+++ b/src/widgets/jackett/proxy.js
@@ -1,7 +1,7 @@
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const logger = createLogger("jackettProxyHandler");
diff --git a/src/widgets/jdownloader/component.jsx b/src/widgets/jdownloader/component.jsx
index a7722c7c..0e7ef72e 100644
--- a/src/widgets/jdownloader/component.jsx
+++ b/src/widgets/jdownloader/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
+import Block from "components/services/widget/block";
+import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
diff --git a/src/widgets/jdownloader/proxy.js b/src/widgets/jdownloader/proxy.js
index d5d5ac3d..ae8c845c 100644
--- a/src/widgets/jdownloader/proxy.js
+++ b/src/widgets/jdownloader/proxy.js
@@ -2,11 +2,11 @@
import crypto from "crypto";
import querystring from "querystring";
-import { createEncryptionToken, decrypt, encrypt, sha256, uniqueRid, validateRid } from "./tools";
+import { sha256, uniqueRid, validateRid, createEncryptionToken, decrypt, encrypt } from "./tools";
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { httpProxy } from "utils/proxy/http";
+import createLogger from "utils/logger";
const proxyName = "jdownloaderProxyHandler";
const logger = createLogger(proxyName);
diff --git a/src/widgets/jellyseerr/component.jsx b/src/widgets/jellyseerr/component.jsx
index d99fffdb..7fb3971e 100644
--- a/src/widgets/jellyseerr/component.jsx
+++ b/src/widgets/jellyseerr/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/karakeep/component.jsx b/src/widgets/karakeep/component.jsx
deleted file mode 100644
index 8a74662d..00000000
--- a/src/widgets/karakeep/component.jsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
-
-import useWidgetAPI from "utils/proxy/use-widget-api";
-
-export const karakeepDefaultFields = ["bookmarks", "favorites", "archived", "highlights"];
-const MAX_ALLOWED_FIELDS = 4;
-
-export default function Component({ service }) {
- const { t } = useTranslation();
- const { widget } = service;
-
- const { data: statsData, error: statsError } = useWidgetAPI(widget, "stats");
-
- if (statsError) {
- return ;
- }
-
- if (!widget.fields || widget.fields.length === 0) {
- widget.fields = karakeepDefaultFields;
- } else if (widget.fields?.length > MAX_ALLOWED_FIELDS) {
- widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
- }
-
- if (!statsData) {
- return (
-
-
-
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/widgets/karakeep/widget.js b/src/widgets/karakeep/widget.js
deleted file mode 100644
index b005b04f..00000000
--- a/src/widgets/karakeep/widget.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
-
-const widget = {
- api: `{url}/api/v1/{endpoint}`,
- proxyHandler: credentialedProxyHandler,
-
- mappings: {
- stats: {
- endpoint: "users/me/stats",
- },
- },
-};
-
-export default widget;
diff --git a/src/widgets/kavita/component.jsx b/src/widgets/kavita/component.jsx
index 887b3bbe..d2d8f442 100644
--- a/src/widgets/kavita/component.jsx
+++ b/src/widgets/kavita/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/kavita/proxy.js b/src/widgets/kavita/proxy.js
index cb3b3569..1c41c45f 100644
--- a/src/widgets/kavita/proxy.js
+++ b/src/widgets/kavita/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "kavitaProxyHandler";
@@ -14,17 +14,7 @@ async function login(widget, service) {
const endpoint = "Account/login";
const api = widgets?.[widget.type]?.api;
const loginUrl = new URL(formatApiCall(api, { endpoint, ...widget }));
- const loginBody = {
- username: "",
- password: "",
- apiKey: "",
- };
- if (widget.username && widget.password) {
- loginBody.username = widget.username;
- loginBody.password = widget.password;
- } else if (widget.key) {
- loginBody.apiKey = widget.key;
- }
+ const loginBody = { username: widget.username, password: widget.password };
const headers = { "Content-Type": "application/json", accept: "text/plain" };
const [, , data] = await httpProxy(loginUrl, {
diff --git a/src/widgets/komga/component.jsx b/src/widgets/komga/component.jsx
index 1e31b726..3cf51bd8 100644
--- a/src/widgets/komga/component.jsx
+++ b/src/widgets/komga/component.jsx
@@ -1,20 +1,23 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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: komgaData, error: komgaError } = useWidgetAPI(widget);
+ const { data: libraryData, error: libraryError } = useWidgetAPI(widget, "libraries");
+ const { data: seriesData, error: seriesError } = useWidgetAPI(widget, "series");
+ const { data: bookData, error: bookError } = useWidgetAPI(widget, "books");
- if (komgaError) {
- return ;
+ if (libraryError || seriesError || bookError) {
+ const finalError = libraryError ?? seriesError ?? bookError;
+ return ;
}
- if (!komgaData) {
+ if (!libraryData || !seriesData || !bookData) {
return (
@@ -24,11 +27,9 @@ export default function Component({ service }) {
);
}
- const { libraries: libraryData, series: seriesData, books: bookData } = komgaData;
-
return (
-
+
diff --git a/src/widgets/komga/proxy.js b/src/widgets/komga/proxy.js
deleted file mode 100644
index b3d72690..00000000
--- a/src/widgets/komga/proxy.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
-import widgets from "widgets/widgets";
-
-const proxyName = "komgaProxyHandler";
-const logger = createLogger(proxyName);
-
-export default async function komgaProxyHandler(req, res) {
- const { group, service, index } = req.query;
-
- if (group && service) {
- const widget = await getServiceWidget(group, service, index);
-
- if (!widgets?.[widget.type]?.api) {
- return res.status(403).json({ error: "Service does not support API calls" });
- }
-
- if (widget) {
- try {
- const data = {};
- const headers = {
- accept: "application/json",
- "Content-Type": "application/json",
- };
- if (widget.username && widget.password) {
- headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
- } else if (widget.key) {
- headers["X-API-Key"] = widget.key;
- }
- const librariesURL = formatApiCall(widgets?.[widget.type].api, { ...widget, endpoint: "libraries" });
- const [librariesStatus, , librariesData] = await httpProxy(librariesURL, {
- method: "GET",
- headers,
- cookieHeader: "X-Auth-Token",
- });
-
- if (librariesStatus !== 200) {
- return res.status(librariesStatus).send(data);
- }
-
- data.libraries = JSON.parse(Buffer.from(librariesData).toString()).filter((library) => !library.unavailable);
-
- const seriesEndpointName = widget.version === 2 ? "seriesv2" : "series";
- const seriesEndpoint = widgets[widget.type].mappings[seriesEndpointName].endpoint;
- const seriesURL = formatApiCall(widgets?.[widget.type].api, { ...widget, endpoint: seriesEndpoint });
- const [seriesStatus, , seriesData] = await httpProxy(seriesURL, {
- method: widgets[widget.type].mappings[seriesEndpointName].method || "GET",
- headers,
- body: "{}",
- cookieHeader: "X-Auth-Token",
- });
-
- if (seriesStatus !== 200) {
- return res.status(seriesStatus).send(data);
- }
-
- data.series = JSON.parse(Buffer.from(seriesData).toString());
-
- const booksEndpointName = widget.version === 2 ? "booksv2" : "books";
- const booksEndpoint = widgets[widget.type].mappings[booksEndpointName].endpoint;
- const booksURL = formatApiCall(widgets?.[widget.type].api, { ...widget, endpoint: booksEndpoint });
- const [booksStatus, , booksData] = await httpProxy(booksURL, {
- method: widgets[widget.type].mappings[booksEndpointName].method || "GET",
- headers,
- body: "{}",
- cookieHeader: "X-Auth-Token",
- });
-
- if (booksStatus !== 200) {
- return res.status(booksStatus).send(data);
- }
-
- data.books = JSON.parse(Buffer.from(booksData).toString());
-
- return res.send(data);
- } catch (e) {
- logger.error("Error communicating with Komga API: %s", e);
- return res.status(500).json({ error: "Error communicating with Komga API" });
- }
- }
- }
-
- return res.status(400).json({ error: "Invalid proxy service type" });
-}
diff --git a/src/widgets/komga/widget.js b/src/widgets/komga/widget.js
index e89bd746..ee01e391 100644
--- a/src/widgets/komga/widget.js
+++ b/src/widgets/komga/widget.js
@@ -1,31 +1,25 @@
-import komgaProxyHandler from "./proxy";
+import genericProxyHandler from "utils/proxy/handlers/generic";
+import { jsonArrayFilter } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/v1/{endpoint}",
- proxyHandler: komgaProxyHandler,
+ proxyHandler: genericProxyHandler,
mappings: {
libraries: {
endpoint: "libraries",
+ map: (data) => ({
+ total: jsonArrayFilter(data, (item) => !item.unavailable).length,
+ }),
},
series: {
endpoint: "series",
validate: ["totalElements"],
},
- seriesv2: {
- endpoint: "series/list",
- method: "POST",
- validate: ["totalElements"],
- },
books: {
endpoint: "books",
validate: ["totalElements"],
},
- booksv2: {
- endpoint: "books/list",
- method: "POST",
- validate: ["totalElements"],
- },
},
};
diff --git a/src/widgets/kopia/component.jsx b/src/widgets/kopia/component.jsx
index d022a545..2e361960 100755
--- a/src/widgets/kopia/component.jsx
+++ b/src/widgets/kopia/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
function relativeDate(date) {
diff --git a/src/widgets/kubernetes/component.jsx b/src/widgets/kubernetes/component.jsx
index d3587a59..68d0da29 100644
--- a/src/widgets/kubernetes/component.jsx
+++ b/src/widgets/kubernetes/component.jsx
@@ -1,7 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
import useSWR from "swr";
+import { useTranslation } from "next-i18next";
+
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
export default function Component({ service }) {
const { t } = useTranslation();
diff --git a/src/widgets/lidarr/component.jsx b/src/widgets/lidarr/component.jsx
index 92f5b893..68360d82 100644
--- a/src/widgets/lidarr/component.jsx
+++ b/src/widgets/lidarr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/linkwarden/component.jsx b/src/widgets/linkwarden/component.jsx
index b2b0d91a..e74a90a8 100644
--- a/src/widgets/linkwarden/component.jsx
+++ b/src/widgets/linkwarden/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useEffect, useState } from "react";
+import React, { useState, useEffect } from "react";
+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 }) {
diff --git a/src/widgets/lubelogger/component.jsx b/src/widgets/lubelogger/component.jsx
index 5ec88983..48995073 100644
--- a/src/widgets/lubelogger/component.jsx
+++ b/src/widgets/lubelogger/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
+import { useTranslation } from "react-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 }) {
diff --git a/src/widgets/mailcow/component.jsx b/src/widgets/mailcow/component.jsx
index e5d9db65..5d5fee9d 100644
--- a/src/widgets/mailcow/component.jsx
+++ b/src/widgets/mailcow/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/mastodon/component.jsx b/src/widgets/mastodon/component.jsx
index 3a5d9ab6..154c9d17 100644
--- a/src/widgets/mastodon/component.jsx
+++ b/src/widgets/mastodon/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/mealie/component.jsx b/src/widgets/mealie/component.jsx
index 4a558157..a4dd1bf1 100644
--- a/src/widgets/mealie/component.jsx
+++ b/src/widgets/mealie/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/medusa/component.jsx b/src/widgets/medusa/component.jsx
index 88f55bcb..d7cc3f39 100644
--- a/src/widgets/medusa/component.jsx
+++ b/src/widgets/medusa/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/medusa/widget.js b/src/widgets/medusa/widget.js
index fbfd8af2..3619d16b 100644
--- a/src/widgets/medusa/widget.js
+++ b/src/widgets/medusa/widget.js
@@ -1,7 +1,7 @@
import genericProxyHandler from "utils/proxy/handlers/generic";
const widget = {
- api: "{url}/api/v1/{key}/{endpoint}",
+ api: "{url}/api/v1/{key}/{endpoint}/",
proxyHandler: genericProxyHandler,
mappings: {
diff --git a/src/widgets/mikrotik/component.jsx b/src/widgets/mikrotik/component.jsx
index 4bab6792..74a9c9ed 100644
--- a/src/widgets/mikrotik/component.jsx
+++ b/src/widgets/mikrotik/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/minecraft/component.jsx b/src/widgets/minecraft/component.jsx
index 00c5f6f8..671e21ab 100644
--- a/src/widgets/minecraft/component.jsx
+++ b/src/widgets/minecraft/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/minecraft/proxy.js b/src/widgets/minecraft/proxy.js
index d1fe1463..98d1be88 100644
--- a/src/widgets/minecraft/proxy.js
+++ b/src/widgets/minecraft/proxy.js
@@ -1,7 +1,7 @@
-import mc from "minecraftstatuspinger";
+import { pingWithPromise } from "minecraft-ping-js";
-import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
+import getServiceWidget from "utils/config/service-helpers";
const proxyName = "minecraftProxyHandler";
const logger = createLogger(proxyName);
@@ -11,14 +11,11 @@ export default async function minecraftProxyHandler(req, res) {
const serviceWidget = await getServiceWidget(group, service, index);
const url = new URL(serviceWidget.url);
try {
- const pingResponse = await mc.lookup({
- host: url.hostname,
- port: url.port || 25565,
- });
+ const pingResponse = await pingWithPromise(url.hostname, url.port || 25565);
res.status(200).send({
- version: pingResponse.status.version.name,
+ version: pingResponse.version.name,
online: true,
- players: pingResponse.status.players,
+ players: pingResponse.players,
});
} catch (e) {
if (e) logger.error(e);
diff --git a/src/widgets/miniflux/component.jsx b/src/widgets/miniflux/component.jsx
index 2cbbb254..aa4699ad 100644
--- a/src/widgets/miniflux/component.jsx
+++ b/src/widgets/miniflux/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/moonraker/component.jsx b/src/widgets/moonraker/component.jsx
index 238c8327..78332135 100644
--- a/src/widgets/moonraker/component.jsx
+++ b/src/widgets/moonraker/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
@@ -36,16 +36,14 @@ export default function Component({ service }) {
const printStatsInfo = printStats.result.status.print_stats.info ?? {};
const { current_layer: currentLayer = "-", total_layer: totalLayer = "-" } = printStatsInfo;
- const layers = printStats.result.status.print_stats.state === "standby" ? "- / -" : `${currentLayer} / ${totalLayer}`;
- const progress =
- printStats.result.status.print_stats.state === "standby"
- ? "-"
- : t("common.percent", { value: displayStatus.result.status.display_status.progress * 100 });
return (
-
-
+
+
);
diff --git a/src/widgets/mylar/component.jsx b/src/widgets/mylar/component.jsx
index 95ec1aca..2d080ac0 100644
--- a/src/widgets/mylar/component.jsx
+++ b/src/widgets/mylar/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/myspeed/component.jsx b/src/widgets/myspeed/component.jsx
index dacd2b59..e4c481c7 100644
--- a/src/widgets/myspeed/component.jsx
+++ b/src/widgets/myspeed/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/navidrome/component.jsx b/src/widgets/navidrome/component.jsx
index 6218e6d9..367ca985 100644
--- a/src/widgets/navidrome/component.jsx
+++ b/src/widgets/navidrome/component.jsx
@@ -1,6 +1,6 @@
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
+import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";
function SinglePlayingEntry({ entry }) {
diff --git a/src/widgets/netalertx/component.jsx b/src/widgets/netalertx/component.jsx
index 786db9a5..5172121e 100644
--- a/src/widgets/netalertx/component.jsx
+++ b/src/widgets/netalertx/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/netdata/component.jsx b/src/widgets/netdata/component.jsx
index 2d04aa23..9d7f2469 100644
--- a/src/widgets/netdata/component.jsx
+++ b/src/widgets/netdata/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/nextcloud/component.jsx b/src/widgets/nextcloud/component.jsx
index d1f1cac9..4e673e4a 100755
--- a/src/widgets/nextcloud/component.jsx
+++ b/src/widgets/nextcloud/component.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import { useMemo } from "react";
+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 }) {
diff --git a/src/widgets/nextdns/component.jsx b/src/widgets/nextdns/component.jsx
index 45e01281..79afc5cd 100644
--- a/src/widgets/nextdns/component.jsx
+++ b/src/widgets/nextdns/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/npm/component.jsx b/src/widgets/npm/component.jsx
index 54e123a8..e9f7e871 100644
--- a/src/widgets/npm/component.jsx
+++ b/src/widgets/npm/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/npm/proxy.js b/src/widgets/npm/proxy.js
index 79307782..6c7ba09e 100644
--- a/src/widgets/npm/proxy.js
+++ b/src/widgets/npm/proxy.js
@@ -1,10 +1,10 @@
import cache from "memory-cache";
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
+import createLogger from "utils/logger";
const proxyName = "npmProxyHandler";
const tokenCacheKey = `${proxyName}__token`;
diff --git a/src/widgets/nzbget/component.jsx b/src/widgets/nzbget/component.jsx
index a11ac9da..1c38abf7 100644
--- a/src/widgets/nzbget/component.jsx
+++ b/src/widgets/nzbget/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/octoprint/component.jsx b/src/widgets/octoprint/component.jsx
index e6b13809..a42475bd 100644
--- a/src/widgets/octoprint/component.jsx
+++ b/src/widgets/octoprint/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/omada/component.jsx b/src/widgets/omada/component.jsx
index bf301d81..e63f93d3 100644
--- a/src/widgets/omada/component.jsx
+++ b/src/widgets/omada/component.jsx
@@ -1,8 +1,8 @@
import { useTranslation } from "next-i18next";
-import Block from "../../components/services/widget/block";
-import Container from "../../components/services/widget/container";
import useWidgetAPI from "../../utils/proxy/use-widget-api";
+import Container from "../../components/services/widget/container";
+import Block from "../../components/services/widget/block";
export default function Component({ service }) {
const { t } = useTranslation();
@@ -18,7 +18,7 @@ export default function Component({ service }) {
}
if (!widget.fields) {
- widget.fields = ["connectedAp", "activeUser", "alerts", "connectedGateways"];
+ widget.fields = ["connectedAp", "activeUser", "alerts", "connectedGateway"];
} else if (widget.fields?.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
@@ -29,7 +29,7 @@ export default function Component({ service }) {
-
+
);
@@ -40,7 +40,7 @@ export default function Component({ service }) {
-
+
);
diff --git a/src/widgets/omada/proxy.js b/src/widgets/omada/proxy.js
index a5af47b2..f4da1293 100644
--- a/src/widgets/omada/proxy.js
+++ b/src/widgets/omada/proxy.js
@@ -1,6 +1,6 @@
+import { httpProxy } from "utils/proxy/http";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { httpProxy } from "utils/proxy/http";
const proxyName = "omadaProxyHandler";
diff --git a/src/widgets/ombi/component.jsx b/src/widgets/ombi/component.jsx
index 859c01aa..0d31081a 100644
--- a/src/widgets/ombi/component.jsx
+++ b/src/widgets/ombi/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/opendtu/component.jsx b/src/widgets/opendtu/component.jsx
index c1b924b9..e91495c5 100644
--- a/src/widgets/opendtu/component.jsx
+++ b/src/widgets/opendtu/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/openmediavault/component.jsx b/src/widgets/openmediavault/component.jsx
index c14581f9..bd34a750 100644
--- a/src/widgets/openmediavault/component.jsx
+++ b/src/widgets/openmediavault/component.jsx
@@ -1,6 +1,6 @@
-import DownloaderGetDownloadList from "./methods/downloader_get_downloadlist";
import ServicesGetStatus from "./methods/services_get_status";
import SmartGetList from "./methods/smart_get_list";
+import DownloaderGetDownloadList from "./methods/downloader_get_downloadlist";
export default function Component({ service }) {
switch (service.widget.method) {
diff --git a/src/widgets/openmediavault/methods/downloader_get_downloadlist.jsx b/src/widgets/openmediavault/methods/downloader_get_downloadlist.jsx
index 7caf3426..ed776db0 100644
--- a/src/widgets/openmediavault/methods/downloader_get_downloadlist.jsx
+++ b/src/widgets/openmediavault/methods/downloader_get_downloadlist.jsx
@@ -1,7 +1,6 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-
import useWidgetAPI from "utils/proxy/use-widget-api";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
const downloadReduce = (acc, e) => {
if (e.downloading) {
diff --git a/src/widgets/openmediavault/methods/services_get_status.jsx b/src/widgets/openmediavault/methods/services_get_status.jsx
index 7ab0f8c1..3ec66a45 100644
--- a/src/widgets/openmediavault/methods/services_get_status.jsx
+++ b/src/widgets/openmediavault/methods/services_get_status.jsx
@@ -1,7 +1,6 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-
import useWidgetAPI from "utils/proxy/use-widget-api";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
const isRunningReduce = (acc, e) => {
if (e.running) {
diff --git a/src/widgets/openmediavault/methods/smart_get_list.jsx b/src/widgets/openmediavault/methods/smart_get_list.jsx
index 4998c02f..b8ca33ee 100644
--- a/src/widgets/openmediavault/methods/smart_get_list.jsx
+++ b/src/widgets/openmediavault/methods/smart_get_list.jsx
@@ -1,7 +1,6 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-
import useWidgetAPI from "utils/proxy/use-widget-api";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
const passedReduce = (acc, e) => {
if (e.monitor && e.overallstatus === "GOOD") {
diff --git a/src/widgets/openmediavault/proxy.js b/src/widgets/openmediavault/proxy.js
index d2365f2b..9cda42e8 100644
--- a/src/widgets/openmediavault/proxy.js
+++ b/src/widgets/openmediavault/proxy.js
@@ -1,8 +1,8 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
-import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar";
import { httpProxy } from "utils/proxy/http";
+import getServiceWidget from "utils/config/service-helpers";
+import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar";
+import createLogger from "utils/logger";
import widgets from "widgets/widgets";
const PROXY_NAME = "OMVProxyHandler";
diff --git a/src/widgets/openwrt/methods/interface.jsx b/src/widgets/openwrt/methods/interface.jsx
index 4f77036f..91366ec9 100644
--- a/src/widgets/openwrt/methods/interface.jsx
+++ b/src/widgets/openwrt/methods/interface.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import useWidgetAPI from "utils/proxy/use-widget-api";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
export default function Component({ service }) {
const { t } = useTranslation();
diff --git a/src/widgets/openwrt/methods/system.jsx b/src/widgets/openwrt/methods/system.jsx
index 55c0b005..0a8146cc 100644
--- a/src/widgets/openwrt/methods/system.jsx
+++ b/src/widgets/openwrt/methods/system.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import useWidgetAPI from "utils/proxy/use-widget-api";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
export default function Component({ service }) {
const { t } = useTranslation();
diff --git a/src/widgets/openwrt/proxy.js b/src/widgets/openwrt/proxy.js
index 5db90790..0a0da3ff 100644
--- a/src/widgets/openwrt/proxy.js
+++ b/src/widgets/openwrt/proxy.js
@@ -1,7 +1,7 @@
+import { sendJsonRpcRequest } from "utils/proxy/handlers/jsonrpc";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { sendJsonRpcRequest } from "utils/proxy/handlers/jsonrpc";
import widgets from "widgets/widgets";
const PROXY_NAME = "OpenWRTProxyHandler";
diff --git a/src/widgets/opnsense/component.jsx b/src/widgets/opnsense/component.jsx
index 1caaab47..1b2171a8 100644
--- a/src/widgets/opnsense/component.jsx
+++ b/src/widgets/opnsense/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/overseerr/component.jsx b/src/widgets/overseerr/component.jsx
index d5c64392..336bc6fc 100644
--- a/src/widgets/overseerr/component.jsx
+++ b/src/widgets/overseerr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/paperlessngx/component.jsx b/src/widgets/paperlessngx/component.jsx
index bafc2e99..cd9cc559 100644
--- a/src/widgets/paperlessngx/component.jsx
+++ b/src/widgets/paperlessngx/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/peanut/component.jsx b/src/widgets/peanut/component.jsx
index 54a293ad..aa6f31b3 100644
--- a/src/widgets/peanut/component.jsx
+++ b/src/widgets/peanut/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/pfsense/component.jsx b/src/widgets/pfsense/component.jsx
index 9f43488b..8e02c590 100644
--- a/src/widgets/pfsense/component.jsx
+++ b/src/widgets/pfsense/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/photoprism/component.jsx b/src/widgets/photoprism/component.jsx
index 21817a10..e5033eda 100644
--- a/src/widgets/photoprism/component.jsx
+++ b/src/widgets/photoprism/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/photoprism/proxy.js b/src/widgets/photoprism/proxy.js
index 1959817a..fe5096b3 100644
--- a/src/widgets/photoprism/proxy.js
+++ b/src/widgets/photoprism/proxy.js
@@ -1,7 +1,7 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
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");
diff --git a/src/widgets/pihole/component.jsx b/src/widgets/pihole/component.jsx
index 6895ab28..7aa706e4 100644
--- a/src/widgets/pihole/component.jsx
+++ b/src/widgets/pihole/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/pihole/proxy.js b/src/widgets/pihole/proxy.js
index 75cd0fb5..bf24624d 100644
--- a/src/widgets/pihole/proxy.js
+++ b/src/widgets/pihole/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "piholeProxyHandler";
@@ -28,11 +28,7 @@ async function login(widget, service) {
logger.error("Failed to login to Pi-Hole API, status: %d", status);
cache.del(`${sessionSIDCacheKey}.${service}`);
} else {
- cache.put(
- `${sessionSIDCacheKey}.${service}`,
- dataParsed.session.sid,
- Math.min(2147483647, dataParsed.session.validity * 1000), // https://github.com/ptarjan/node-cache/issues/84
- );
+ cache.put(`${sessionSIDCacheKey}.${service}`, dataParsed.session.sid, dataParsed.session.validity);
}
}
diff --git a/src/widgets/plantit/component.jsx b/src/widgets/plantit/component.jsx
index d93304e7..ea203b87 100644
--- a/src/widgets/plantit/component.jsx
+++ b/src/widgets/plantit/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/plex/component.jsx b/src/widgets/plex/component.jsx
index 153d57b5..86ba5503 100644
--- a/src/widgets/plex/component.jsx
+++ b/src/widgets/plex/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
+import Block from "components/services/widget/block";
+import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
diff --git a/src/widgets/plex/proxy.js b/src/widgets/plex/proxy.js
index 18ffc49b..2956f280 100644
--- a/src/widgets/plex/proxy.js
+++ b/src/widgets/plex/proxy.js
@@ -2,10 +2,10 @@
import cache from "memory-cache";
import { xml2json } from "xml-js";
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
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";
import widgets from "widgets/widgets";
const proxyName = "plexProxyHandler";
@@ -41,12 +41,7 @@ async function fetchFromPlexAPI(endpoint, widget) {
const url = new URL(formatApiCall(api, { endpoint, ...widget }));
- const [status, contentType, data] = await httpProxy(url, {
- headers: {
- "X-Plex-Container-Start": `0`,
- "X-Plex-Container-Size": `500`,
- },
- });
+ const [status, contentType, data] = await httpProxy(url);
if (status !== 200) {
logger.error("HTTP %d communicating with Plex. Data: %s", status, data.toString());
@@ -111,8 +106,7 @@ export default async function plexProxyHandler(req, res) {
: `/library/sections/${library._attributes.key}/albums`; // music
[status, apiData] = await fetchFromPlexAPI(libraryURL, widget);
if (apiData && apiData.MediaContainer) {
- const sizeProp = apiData.MediaContainer._attributes["totalSize"] ? "totalSize" : "size";
- const size = parseInt(apiData.MediaContainer._attributes[sizeProp], 10);
+ const size = parseInt(apiData.MediaContainer._attributes.size, 10);
if (library._attributes.type === "movie") {
movies += size;
} else if (library._attributes.type === "show") {
diff --git a/src/widgets/portainer/component.jsx b/src/widgets/portainer/component.jsx
index f8a89507..41d541dc 100644
--- a/src/widgets/portainer/component.jsx
+++ b/src/widgets/portainer/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/prometheus/component.jsx b/src/widgets/prometheus/component.jsx
index 7b3722d0..da93d490 100644
--- a/src/widgets/prometheus/component.jsx
+++ b/src/widgets/prometheus/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/prometheus/widget.js b/src/widgets/prometheus/widget.js
index 817dc029..1ecf7b7c 100644
--- a/src/widgets/prometheus/widget.js
+++ b/src/widgets/prometheus/widget.js
@@ -6,7 +6,7 @@ const widget = {
mappings: {
targets: {
- endpoint: "targets?state=active",
+ endpoint: "targets",
validate: ["data"],
},
},
diff --git a/src/widgets/prometheusmetric/component.jsx b/src/widgets/prometheusmetric/component.jsx
index d58efde9..350a6b7d 100644
--- a/src/widgets/prometheusmetric/component.jsx
+++ b/src/widgets/prometheusmetric/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
function formatValue(t, metric, rawValue) {
diff --git a/src/widgets/prowlarr/component.jsx b/src/widgets/prowlarr/component.jsx
index e454c1a7..6f7211f0 100644
--- a/src/widgets/prowlarr/component.jsx
+++ b/src/widgets/prowlarr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
+import { useTranslation } from "react-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 }) {
diff --git a/src/widgets/proxmox/component.jsx b/src/widgets/proxmox/component.jsx
index 51762a73..f7493e7a 100644
--- a/src/widgets/proxmox/component.jsx
+++ b/src/widgets/proxmox/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
function calcRunning(total, current) {
diff --git a/src/widgets/proxmoxbackupserver/component.jsx b/src/widgets/proxmoxbackupserver/component.jsx
index b13f8756..d6320d61 100644
--- a/src/widgets/proxmoxbackupserver/component.jsx
+++ b/src/widgets/proxmoxbackupserver/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
@@ -29,18 +29,7 @@ export default function Component({ service }) {
);
}
- const datastoreIndex = !!widget.datastore
- ? datastoreData.data.findIndex(function (ds) {
- return ds.store == widget.datastore;
- })
- : -1;
- const datastoreUsage =
- datastoreIndex > -1
- ? (datastoreData.data[datastoreIndex].used / datastoreData.data[datastoreIndex].total) * 100
- : (datastoreData.data.reduce((sum, datastore) => sum + datastore.used, 0) /
- datastoreData.data.reduce((sum, datastore) => sum + datastore.total, 0)) *
- 100;
-
+ const datastoreUsage = datastoreData.data ? (datastoreData.data[0].used / datastoreData.data[0].total) * 100 : 0;
const cpuUsage = hostData.data.cpu * 100;
const memoryUsage = (hostData.data.memory.used / hostData.data.memory.total) * 100;
const failedTasks = tasksData.total >= 100 ? "99+" : tasksData.total;
diff --git a/src/widgets/pterodactyl/component.jsx b/src/widgets/pterodactyl/component.jsx
index 9a702eef..bd3242cc 100644
--- a/src/widgets/pterodactyl/component.jsx
+++ b/src/widgets/pterodactyl/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/pyload/component.jsx b/src/widgets/pyload/component.jsx
index f618f75e..3df11c8e 100644
--- a/src/widgets/pyload/component.jsx
+++ b/src/widgets/pyload/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/pyload/proxy.js b/src/widgets/pyload/proxy.js
index 2a1949c1..a380c865 100644
--- a/src/widgets/pyload/proxy.js
+++ b/src/widgets/pyload/proxy.js
@@ -1,10 +1,10 @@
import cache from "memory-cache";
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
+import createLogger from "utils/logger";
+import { httpProxy } from "utils/proxy/http";
const proxyName = "pyloadProxyHandler";
const logger = createLogger(proxyName);
diff --git a/src/widgets/qbittorrent/component.jsx b/src/widgets/qbittorrent/component.jsx
index c9f64816..d7fb8bf7 100644
--- a/src/widgets/qbittorrent/component.jsx
+++ b/src/widgets/qbittorrent/component.jsx
@@ -1,9 +1,9 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import QueueEntry from "../../components/widgets/queue/queueEntry";
+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 }) {
diff --git a/src/widgets/qbittorrent/proxy.js b/src/widgets/qbittorrent/proxy.js
index 8f1874bf..aead7582 100644
--- a/src/widgets/qbittorrent/proxy.js
+++ b/src/widgets/qbittorrent/proxy.js
@@ -1,7 +1,7 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
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("qbittorrentProxyHandler");
diff --git a/src/widgets/qnap/component.jsx b/src/widgets/qnap/component.jsx
index d7fdf8bc..1bfa1f9a 100644
--- a/src/widgets/qnap/component.jsx
+++ b/src/widgets/qnap/component.jsx
@@ -1,9 +1,9 @@
/* eslint no-underscore-dangle: ["error", { "allow": ["_text", "_cdata"] }] */
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/qnap/proxy.js b/src/widgets/qnap/proxy.js
index 1c5356ae..07917d28 100644
--- a/src/widgets/qnap/proxy.js
+++ b/src/widgets/qnap/proxy.js
@@ -3,10 +3,10 @@
import cache from "memory-cache";
import { xml2json } from "xml-js";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
const proxyName = "qnapProxyHandler";
const sessionTokenCacheKey = `${proxyName}__sessionToken`;
diff --git a/src/widgets/radarr/component.jsx b/src/widgets/radarr/component.jsx
index bcf9301b..ebb00fee 100644
--- a/src/widgets/radarr/component.jsx
+++ b/src/widgets/radarr/component.jsx
@@ -1,10 +1,10 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import { useCallback } from "react";
import QueueEntry from "../../components/widgets/queue/queueEntry";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
function getProgress(sizeLeft, size) {
diff --git a/src/widgets/radarr/widget.js b/src/widgets/radarr/widget.js
index 4f71b8d9..7d370378 100644
--- a/src/widgets/radarr/widget.js
+++ b/src/widgets/radarr/widget.js
@@ -1,5 +1,5 @@
-import { asJson, jsonArrayFilter } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+import { asJson, jsonArrayFilter } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/v3/{endpoint}?apikey={key}",
diff --git a/src/widgets/readarr/component.jsx b/src/widgets/readarr/component.jsx
index 845b7820..bde9715a 100644
--- a/src/widgets/readarr/component.jsx
+++ b/src/widgets/readarr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/readarr/widget.js b/src/widgets/readarr/widget.js
index f786f0bc..58cc09c4 100644
--- a/src/widgets/readarr/widget.js
+++ b/src/widgets/readarr/widget.js
@@ -1,5 +1,5 @@
-import { jsonArrayFilter } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+import { jsonArrayFilter } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/v1/{endpoint}?apikey={key}",
diff --git a/src/widgets/romm/component.jsx b/src/widgets/romm/component.jsx
index b0787fb3..ea9549f7 100644
--- a/src/widgets/romm/component.jsx
+++ b/src/widgets/romm/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
const ROMM_DEFAULT_FIELDS = ["platforms", "totalRoms", "saves", "states"];
diff --git a/src/widgets/rutorrent/component.jsx b/src/widgets/rutorrent/component.jsx
index 245a786c..e7dc26e7 100644
--- a/src/widgets/rutorrent/component.jsx
+++ b/src/widgets/rutorrent/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/rutorrent/proxy.js b/src/widgets/rutorrent/proxy.js
index 910f2311..e0ae44fe 100644
--- a/src/widgets/rutorrent/proxy.js
+++ b/src/widgets/rutorrent/proxy.js
@@ -1,8 +1,8 @@
import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
+import { formatApiCall } from "utils/proxy/api-helpers";
+import createLogger from "utils/logger";
const logger = createLogger("rutorrentProxyHandler");
diff --git a/src/widgets/sabnzbd/component.jsx b/src/widgets/sabnzbd/component.jsx
index 9807dd93..260375a4 100644
--- a/src/widgets/sabnzbd/component.jsx
+++ b/src/widgets/sabnzbd/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
function fromUnits(value) {
diff --git a/src/widgets/scrutiny/component.jsx b/src/widgets/scrutiny/component.jsx
index 2450a95e..b0ebc767 100644
--- a/src/widgets/scrutiny/component.jsx
+++ b/src/widgets/scrutiny/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
import Container from "components/services/widget/container";
-
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
// @see https://github.com/AnalogJ/scrutiny/blob/d8d56f77f9e868127c4849dac74d65512db658e8/webapp/frontend/src/app/shared/device-status.pipe.ts
diff --git a/src/widgets/slskd/component.jsx b/src/widgets/slskd/component.jsx
deleted file mode 100644
index 40a206b6..00000000
--- a/src/widgets/slskd/component.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
-import { useTranslation } from "next-i18next";
-
-import useWidgetAPI from "utils/proxy/use-widget-api";
-
-const slskdDefaultFields = ["slskStatus", "downloads", "uploads", "sharedFiles"];
-const MAX_ALLOWED_FIELDS = 4;
-
-export default function Component({ service }) {
- const { t } = useTranslation();
- const { widget } = service;
-
- const { data: appData, error: appError } = useWidgetAPI(widget, "application");
- const { data: downData, error: downError } = useWidgetAPI(widget, "downloads");
- const { data: upData, error: upError } = useWidgetAPI(widget, "uploads");
-
- if (appError || downError || upError) {
- return
;
- }
-
- if (!widget.fields || widget.fields.length === 0) {
- widget.fields = slskdDefaultFields;
- } else if (widget.fields?.length > MAX_ALLOWED_FIELDS) {
- widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
- }
-
- if (!appData || !downData || !upData) {
- return (
-
-
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
-
-
- );
-}
diff --git a/src/widgets/slskd/widget.js b/src/widgets/slskd/widget.js
deleted file mode 100644
index 3eedd356..00000000
--- a/src/widgets/slskd/widget.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
-
-const widget = {
- api: `{url}/api/v0/{endpoint}`,
- proxyHandler: credentialedProxyHandler,
-
- mappings: {
- application: {
- endpoint: "application",
- },
- downloads: {
- endpoint: "transfers/downloads",
- },
- uploads: {
- endpoint: "transfers/uploads",
- },
- },
-};
-
-export default widget;
diff --git a/src/widgets/sonarr/component.jsx b/src/widgets/sonarr/component.jsx
index 19cc2c12..e4b63bad 100644
--- a/src/widgets/sonarr/component.jsx
+++ b/src/widgets/sonarr/component.jsx
@@ -1,10 +1,10 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import { useCallback } from "react";
import QueueEntry from "../../components/widgets/queue/queueEntry";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
function getProgress(sizeLeft, size) {
diff --git a/src/widgets/sonarr/widget.js b/src/widgets/sonarr/widget.js
index 1fcef8eb..acb4a551 100644
--- a/src/widgets/sonarr/widget.js
+++ b/src/widgets/sonarr/widget.js
@@ -1,5 +1,5 @@
-import { asJson } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+import { asJson } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/v3/{endpoint}?apikey={key}",
diff --git a/src/widgets/speedtest/component.jsx b/src/widgets/speedtest/component.jsx
index 7be00aa2..9826f776 100644
--- a/src/widgets/speedtest/component.jsx
+++ b/src/widgets/speedtest/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
@@ -9,19 +9,18 @@ export default function Component({ service }) {
const { widget } = service;
- const endpoint = widget.version === 2 ? "latestv2" : "latestv1";
- const { data: speedtestData, error: speedtestError } = useWidgetAPI(widget, endpoint);
+ const { data: speedtestData, error: speedtestError } = useWidgetAPI(widget, "speedtest/latest");
const bitratePrecision =
!widget?.bitratePrecision || Number.isNaN(widget?.bitratePrecision) || widget?.bitratePrecision < 0
? 0
: widget.bitratePrecision;
- if (speedtestError || speedtestData?.error) {
- return
;
+ if (speedtestError) {
+ return
;
}
- if (!speedtestData?.data) {
+ if (!speedtestData) {
return (
@@ -36,14 +35,14 @@ export default function Component({ service }) {
diff --git a/src/widgets/speedtest/widget.js b/src/widgets/speedtest/widget.js
index 3517de3c..09e0da7c 100644
--- a/src/widgets/speedtest/widget.js
+++ b/src/widgets/speedtest/widget.js
@@ -1,18 +1,14 @@
-import genericProxyHandler from "utils/proxy/handlers/credentialed";
+import genericProxyHandler from "utils/proxy/handlers/generic";
const widget = {
api: "{url}/api/{endpoint}",
proxyHandler: genericProxyHandler,
mappings: {
- latestv1: {
+ "speedtest/latest": {
endpoint: "speedtest/latest",
validate: ["data"],
},
- latestv2: {
- endpoint: "v1/results/latest",
- validate: ["data"],
- },
},
};
diff --git a/src/widgets/spoolman/component.jsx b/src/widgets/spoolman/component.jsx
index 62eb3a1d..523ecea7 100644
--- a/src/widgets/spoolman/component.jsx
+++ b/src/widgets/spoolman/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/stash/component.jsx b/src/widgets/stash/component.jsx
index 965c6b59..b7c259a8 100644
--- a/src/widgets/stash/component.jsx
+++ b/src/widgets/stash/component.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import { useEffect, useState } from "react";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import { formatProxyUrl } from "utils/proxy/api-helpers";
export default function Component({ service }) {
diff --git a/src/widgets/stocks/component.jsx b/src/widgets/stocks/component.jsx
index be471ddf..844365cb 100644
--- a/src/widgets/stocks/component.jsx
+++ b/src/widgets/stocks/component.jsx
@@ -1,8 +1,8 @@
-import classNames from "classnames";
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
+import classNames from "classnames";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
function MarketStatus({ service }) {
@@ -61,7 +61,7 @@ function StockItem({ service, ticker }) {
}
return (
-
+
{ticker}
0 ? "text-emerald-300" : "text-rose-300"}`}>
diff --git a/src/widgets/strelaysrv/component.jsx b/src/widgets/strelaysrv/component.jsx
index 026e19b7..a14678d2 100644
--- a/src/widgets/strelaysrv/component.jsx
+++ b/src/widgets/strelaysrv/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/suwayomi/component.jsx b/src/widgets/suwayomi/component.jsx
index 1cbd8c53..b7c34820 100644
--- a/src/widgets/suwayomi/component.jsx
+++ b/src/widgets/suwayomi/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/suwayomi/proxy.js b/src/widgets/suwayomi/proxy.js
index 4df55b95..def811cc 100644
--- a/src/widgets/suwayomi/proxy.js
+++ b/src/widgets/suwayomi/proxy.js
@@ -1,7 +1,7 @@
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "suwayomiProxyHandler";
diff --git a/src/widgets/swagdashboard/component.jsx b/src/widgets/swagdashboard/component.jsx
index 4220e3c8..d4dbd494 100644
--- a/src/widgets/swagdashboard/component.jsx
+++ b/src/widgets/swagdashboard/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/tailscale/component.jsx b/src/widgets/tailscale/component.jsx
index b95cb016..d3c937d5 100644
--- a/src/widgets/tailscale/component.jsx
+++ b/src/widgets/tailscale/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/tandoor/component.jsx b/src/widgets/tandoor/component.jsx
index 4a02d539..40d2b88e 100644
--- a/src/widgets/tandoor/component.jsx
+++ b/src/widgets/tandoor/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/tautulli/component.jsx b/src/widgets/tautulli/component.jsx
index 3f6443dd..ba94f143 100644
--- a/src/widgets/tautulli/component.jsx
+++ b/src/widgets/tautulli/component.jsx
@@ -1,9 +1,9 @@
/* eslint-disable camelcase */
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
-import { BsCpu, BsFillCpuFill, BsFillPlayFill, BsPauseFill } from "react-icons/bs";
+import { BsFillPlayFill, BsPauseFill, BsCpu, BsFillCpuFill } from "react-icons/bs";
import { MdOutlineSmartDisplay, MdSmartDisplay } from "react-icons/md";
+import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";
function millisecondsToTime(milliseconds) {
diff --git a/src/widgets/tdarr/component.jsx b/src/widgets/tdarr/component.jsx
index 824a56b3..f885830f 100644
--- a/src/widgets/tdarr/component.jsx
+++ b/src/widgets/tdarr/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/tdarr/proxy.js b/src/widgets/tdarr/proxy.js
index d6897dfc..88da30fd 100644
--- a/src/widgets/tdarr/proxy.js
+++ b/src/widgets/tdarr/proxy.js
@@ -1,7 +1,7 @@
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "tdarrProxyHandler";
diff --git a/src/widgets/technitium/component.jsx b/src/widgets/technitium/component.jsx
index fa221025..d510a59d 100644
--- a/src/widgets/technitium/component.jsx
+++ b/src/widgets/technitium/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
const MAX_ALLOWED_FIELDS = 4;
diff --git a/src/widgets/technitium/widget.js b/src/widgets/technitium/widget.js
index fc4577be..c3432a67 100644
--- a/src/widgets/technitium/widget.js
+++ b/src/widgets/technitium/widget.js
@@ -1,5 +1,5 @@
-import { asJson } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+import { asJson } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/{endpoint}?token={key}&utc=true",
diff --git a/src/widgets/traefik/component.jsx b/src/widgets/traefik/component.jsx
index e4b3b46b..42d261e3 100644
--- a/src/widgets/traefik/component.jsx
+++ b/src/widgets/traefik/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/transmission/component.jsx b/src/widgets/transmission/component.jsx
index 474fe69f..98b269a5 100644
--- a/src/widgets/transmission/component.jsx
+++ b/src/widgets/transmission/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/transmission/proxy.js b/src/widgets/transmission/proxy.js
index b0be7bac..8b8049bc 100644
--- a/src/widgets/transmission/proxy.js
+++ b/src/widgets/transmission/proxy.js
@@ -1,9 +1,9 @@
import cache from "memory-cache";
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "transmissionProxyHandler";
diff --git a/src/widgets/truenas/component.jsx b/src/widgets/truenas/component.jsx
index 12ceef56..ccdab297 100644
--- a/src/widgets/truenas/component.jsx
+++ b/src/widgets/truenas/component.jsx
@@ -1,9 +1,9 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
-import Pool from "widgets/truenas/pool";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
+import Pool from "widgets/truenas/pool";
export default function Component({ service }) {
const { t } = useTranslation();
@@ -12,15 +12,14 @@ export default function Component({ service }) {
const { data: alertData, error: alertError } = useWidgetAPI(widget, "alerts");
const { data: statusData, error: statusError } = useWidgetAPI(widget, "status");
- const { data: poolsData, error: poolsError } = useWidgetAPI(widget, widget?.enablePools ? "pools" : null);
- const { data: datasetData, error: datasetError } = useWidgetAPI(widget, widget?.enablePools ? "dataset" : null);
+ const { data: poolsData, error: poolsError } = useWidgetAPI(widget, "pools");
if (alertError || statusError || poolsError) {
- const finalError = alertError ?? statusError ?? poolsError ?? datasetError;
+ const finalError = alertError ?? statusError ?? poolsError;
return ;
}
- if (!alertData || !statusData || (widget?.enablePools && (!poolsData || !datasetData))) {
+ if (!alertData || !statusData) {
return (
@@ -30,22 +29,7 @@ export default function Component({ service }) {
);
}
- let pools = [];
- const showPools =
- Array.isArray(poolsData) && poolsData.length > 0 && Array.isArray(datasetData) && datasetData.length > 0;
-
- if (showPools) {
- pools = poolsData.map((pool) => {
- const dataset = datasetData.find((d) => d.pool === pool.name && d.name === pool.name);
- return {
- id: pool.id,
- name: pool.name,
- healthy: pool.healthy,
- allocated: dataset?.used.parsed ?? 0,
- free: dataset?.available.parsed ?? 0,
- };
- });
- }
+ const enablePools = widget?.enablePools && Array.isArray(poolsData) && poolsData.length > 0;
return (
<>
@@ -54,11 +38,19 @@ export default function Component({ service }) {
- {showPools &&
- pools
+ {enablePools &&
+ poolsData
.sort((a, b) => a.name.localeCompare(b.name))
.map((pool) => (
-
+
))}
>
);
diff --git a/src/widgets/truenas/pool.jsx b/src/widgets/truenas/pool.jsx
index 7b2052ea..b92ecb68 100644
--- a/src/widgets/truenas/pool.jsx
+++ b/src/widgets/truenas/pool.jsx
@@ -1,9 +1,19 @@
import classNames from "classnames";
-import { useTranslation } from "next-i18next";
+import prettyBytes from "pretty-bytes";
-export default function Pool({ name, free, allocated, healthy }) {
- const { t } = useTranslation();
- const usedPercent = Math.round((allocated / (free + allocated)) * 100);
+export default function Pool({ name, free, allocated, healthy, data, nasType }) {
+ let total = 0;
+ if (nasType === "scale") {
+ total = free + allocated;
+ } else {
+ allocated = 0; // eslint-disable-line no-param-reassign
+ for (let i = 0; i < data.length; i += 1) {
+ total += data[i].stats.size;
+ allocated += data[i].stats.allocated; // eslint-disable-line no-param-reassign
+ }
+ }
+
+ const usedPercent = Math.round((allocated / total) * 100);
const statusColor = healthy ? "bg-green-500" : "bg-yellow-500";
return (
@@ -15,22 +25,14 @@ export default function Pool({ name, free, allocated, healthy }) {
}}
/>
-
+
- {`${t("common.bytes", {
- value: allocated,
- maximumFractionDigits: 1,
- binary: true,
- })} / ${t("common.bytes", {
- value: free + allocated,
- maximumFractionDigits: 1,
- binary: true,
- })}`}
+ {prettyBytes(allocated)} / {prettyBytes(total)}
({usedPercent}%)
diff --git a/src/widgets/truenas/widget.js b/src/widgets/truenas/widget.js
index 528114ed..8e50956b 100644
--- a/src/widgets/truenas/widget.js
+++ b/src/widgets/truenas/widget.js
@@ -1,5 +1,5 @@
-import { asJson, jsonArrayFilter } from "utils/proxy/api-helpers";
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
+import { asJson, jsonArrayFilter } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/api/v2.0/{endpoint}",
@@ -23,11 +23,11 @@ const widget = {
id: entry.name,
name: entry.name,
healthy: entry.healthy,
+ allocated: entry.allocated,
+ free: entry.free,
+ data: entry.topology?.data ?? [],
})),
},
- dataset: {
- endpoint: "pool/dataset",
- },
},
};
diff --git a/src/widgets/tubearchivist/component.jsx b/src/widgets/tubearchivist/component.jsx
index 427298e4..c95db074 100644
--- a/src/widgets/tubearchivist/component.jsx
+++ b/src/widgets/tubearchivist/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
@@ -14,8 +14,8 @@ export default function Component({ service }) {
const { data: channelsData, error: channelsError } = useWidgetAPI(widget, "channels");
const { data: playlistsData, error: playlistsError } = useWidgetAPI(widget, "playlists");
- if (downloadsError || videosError || channelsError || playlistsError || (downloadsData && downloadsData.detail)) {
- const finalError = downloadsError ?? videosError ?? channelsError ?? playlistsError ?? downloadsData.detail;
+ if (downloadsError || videosError || channelsError || playlistsError) {
+ const finalError = downloadsError ?? videosError ?? channelsError ?? playlistsError;
return ;
}
diff --git a/src/widgets/unifi/component.jsx b/src/widgets/unifi/component.jsx
index ad58d1d9..2d5784b7 100644
--- a/src/widgets/unifi/component.jsx
+++ b/src/widgets/unifi/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/unifi/proxy.js b/src/widgets/unifi/proxy.js
index c932fc41..559065e3 100644
--- a/src/widgets/unifi/proxy.js
+++ b/src/widgets/unifi/proxy.js
@@ -1,11 +1,11 @@
import cache from "memory-cache";
+import { formatApiCall } from "utils/proxy/api-helpers";
+import { httpProxy } from "utils/proxy/http";
+import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar";
import getServiceWidget from "utils/config/service-helpers";
import { getPrivateWidgetOptions } from "utils/config/widget-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const udmpPrefix = "/proxy/network";
@@ -47,7 +47,7 @@ async function login(widget, csrfToken) {
const endpoint = widget.prefix === udmpPrefix ? "auth/login" : "login";
const api = widgets?.[widget.type]?.api?.replace("{prefix}", ""); // no prefix for login url
const loginUrl = new URL(formatApiCall(api, { endpoint, ...widget }));
- const loginBody = { username: widget.username, password: widget.password, remember: true, rememberMe: true };
+ const loginBody = { username: widget.username, password: widget.password, remember: true };
const headers = { "Content-Type": "application/json" };
if (csrfToken) {
headers["X-CSRF-TOKEN"] = csrfToken;
@@ -75,39 +75,31 @@ export default async function unifiProxyHandler(req, res) {
let [status, contentType, data, responseHeaders] = [];
let prefix = cache.get(`${prefixCacheKey}.${service}`);
let csrfToken;
- const headers = {};
- if (widget.key) {
- prefix = udmpPrefix;
- headers["X-API-KEY"] = widget.key;
- headers["Accept"] = "application/json";
- } else if (prefix === null) {
- // auto detect if we're talking to a UDM Pro or Network API device, and cache the result
- // so that we don't make two requests each time data from Unifi is required
+ if (prefix === null) {
+ // auto detect if we're talking to a UDM Pro, and cache the result so that we
+ // don't make two requests each time data from Unifi is required
[status, contentType, data, responseHeaders] = await httpProxy(widget.url);
prefix = "";
if (responseHeaders?.["x-csrf-token"]) {
// Unifi OS < 3.2.5 passes & requires csrf-token
prefix = udmpPrefix;
csrfToken = responseHeaders["x-csrf-token"];
- } else if (
- responseHeaders?.["access-control-expose-headers"] ||
- responseHeaders?.["Access-Control-Expose-Headers"]
- ) {
- // Unifi OS ≥ 3.2.5 doesnt pass csrf token but still uses different endpoint, same with Network API
+ } else if (responseHeaders?.["access-control-expose-headers"]) {
+ // Unifi OS ≥ 3.2.5 doesnt pass csrf token but still uses different endpoint
prefix = udmpPrefix;
}
+ cache.put(`${prefixCacheKey}.${service}`, prefix);
}
- cache.put(`${prefixCacheKey}.${service}`, prefix);
widget.prefix = prefix;
const { endpoint } = req.query;
const url = new URL(formatApiCall(api, { endpoint, ...widget }));
- const params = { method: "GET", headers };
+ const params = { method: "GET", headers: {} };
setCookieHeader(url, params);
[status, contentType, data, responseHeaders] = await httpProxy(url, params);
- if (status === 401 && !widget.key) {
+ if (status === 401) {
logger.debug("Unifi isn't logged in or rejected the reqeust, attempting login.");
if (responseHeaders?.["x-csrf-token"]) {
csrfToken = responseHeaders["x-csrf-token"];
diff --git a/src/widgets/unmanic/component.jsx b/src/widgets/unmanic/component.jsx
index 12069e52..98688463 100644
--- a/src/widgets/unmanic/component.jsx
+++ b/src/widgets/unmanic/component.jsx
@@ -1,9 +1,9 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useEffect, useState } from "react";
-import { formatProxyUrl } from "utils/proxy/api-helpers";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
+import { formatProxyUrl } from "utils/proxy/api-helpers";
export default function Component({ service }) {
const { widget } = service;
diff --git a/src/widgets/unmanic/widget.js b/src/widgets/unmanic/widget.js
index ef4493e9..4c9713e4 100644
--- a/src/widgets/unmanic/widget.js
+++ b/src/widgets/unmanic/widget.js
@@ -1,5 +1,5 @@
-import { asJson } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+import { asJson } from "utils/proxy/api-helpers";
const widget = {
api: "{url}/unmanic/api/v2/{endpoint}",
diff --git a/src/widgets/uptimekuma/component.jsx b/src/widgets/uptimekuma/component.jsx
index e8a42e48..01693db3 100644
--- a/src/widgets/uptimekuma/component.jsx
+++ b/src/widgets/uptimekuma/component.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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();
diff --git a/src/widgets/uptimerobot/component.jsx b/src/widgets/uptimerobot/component.jsx
index a1f234c2..b2027a6f 100644
--- a/src/widgets/uptimerobot/component.jsx
+++ b/src/widgets/uptimerobot/component.jsx
@@ -1,8 +1,8 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next";
import { useEffect, useState } from "react";
+import Container from "components/services/widget/container";
+import Block from "components/services/widget/block";
import { formatProxyUrl } from "utils/proxy/api-helpers";
export default function Component({ service }) {
diff --git a/src/widgets/urbackup/component.jsx b/src/widgets/urbackup/component.jsx
index 9d8f92ba..c76cdf48 100644
--- a/src/widgets/urbackup/component.jsx
+++ b/src/widgets/urbackup/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
const Status = Object.freeze({
diff --git a/src/widgets/vikunja/component.jsx b/src/widgets/vikunja/component.jsx
index 1afccd38..09704338 100644
--- a/src/widgets/vikunja/component.jsx
+++ b/src/widgets/vikunja/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/vikunja/widget.js b/src/widgets/vikunja/widget.js
index 8e5e680a..9a192026 100644
--- a/src/widgets/vikunja/widget.js
+++ b/src/widgets/vikunja/widget.js
@@ -1,5 +1,5 @@
-import { asJson } from "utils/proxy/api-helpers";
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
+import { asJson } from "utils/proxy/api-helpers";
const widget = {
api: `{url}/api/v1/{endpoint}`,
diff --git a/src/widgets/watchtower/component.jsx b/src/widgets/watchtower/component.jsx
index 58b2a3f5..4bca538f 100644
--- a/src/widgets/watchtower/component.jsx
+++ b/src/widgets/watchtower/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/watchtower/proxy.js b/src/widgets/watchtower/proxy.js
index 484c3c7d..588d08ee 100644
--- a/src/widgets/watchtower/proxy.js
+++ b/src/widgets/watchtower/proxy.js
@@ -1,7 +1,7 @@
+import { httpProxy } from "utils/proxy/http";
+import { formatApiCall } from "utils/proxy/api-helpers";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
-import { formatApiCall } from "utils/proxy/api-helpers";
-import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "watchtowerProxyHandler";
diff --git a/src/widgets/wgeasy/component.jsx b/src/widgets/wgeasy/component.jsx
index 829b120d..db39c81a 100644
--- a/src/widgets/wgeasy/component.jsx
+++ b/src/widgets/wgeasy/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/whatsupdocker/component.jsx b/src/widgets/whatsupdocker/component.jsx
index cc3b5174..2719fa8f 100644
--- a/src/widgets/whatsupdocker/component.jsx
+++ b/src/widgets/whatsupdocker/component.jsx
@@ -1,6 +1,5 @@
-import Block from "components/services/widget/block";
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 }) {
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index e183a9c6..9d4bb935 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -1,5 +1,4 @@
import adguard from "./adguard/widget";
-import apcups from "./apcups/widget";
import argocd from "./argocd/widget";
import atsumeru from "./atsumeru/widget";
import audiobookshelf from "./audiobookshelf/widget";
@@ -25,7 +24,6 @@ import emby from "./emby/widget";
import esphome from "./esphome/widget";
import evcc from "./evcc/widget";
import fileflows from "./fileflows/widget";
-import firefly from "./firefly/widget";
import flood from "./flood/widget";
import freshrss from "./freshrss/widget";
import frigate from "./frigate/widget";
@@ -41,15 +39,14 @@ import gotify from "./gotify/widget";
import grafana from "./grafana/widget";
import hdhomerun from "./hdhomerun/widget";
import headscale from "./headscale/widget";
-import healthchecks from "./healthchecks/widget";
import homeassistant from "./homeassistant/widget";
import homebox from "./homebox/widget";
import homebridge from "./homebridge/widget";
+import healthchecks from "./healthchecks/widget";
import immich from "./immich/widget";
import jackett from "./jackett/widget";
-import jdownloader from "./jdownloader/widget";
import jellyseerr from "./jellyseerr/widget";
-import karakeep from "./karakeep/widget";
+import jdownloader from "./jdownloader/widget";
import kavita from "./kavita/widget";
import komga from "./komga/widget";
import kopia from "./kopia/widget";
@@ -60,9 +57,9 @@ import mailcow from "./mailcow/widget";
import mastodon from "./mastodon/widget";
import mealie from "./mealie/widget";
import medusa from "./medusa/widget";
-import mikrotik from "./mikrotik/widget";
import minecraft from "./minecraft/widget";
import miniflux from "./miniflux/widget";
+import mikrotik from "./mikrotik/widget";
import mjpeg from "./mjpeg/widget";
import moonraker from "./moonraker/widget";
import mylar from "./mylar/widget";
@@ -78,14 +75,15 @@ import octoprint from "./octoprint/widget";
import omada from "./omada/widget";
import ombi from "./ombi/widget";
import opendtu from "./opendtu/widget";
-import openmediavault from "./openmediavault/widget";
-import openwrt from "./openwrt/widget";
import opnsense from "./opnsense/widget";
import overseerr from "./overseerr/widget";
+import openmediavault from "./openmediavault/widget";
+import openwrt from "./openwrt/widget";
import paperlessngx from "./paperlessngx/widget";
import peanut from "./peanut/widget";
import pfsense from "./pfsense/widget";
import photoprism from "./photoprism/widget";
+import proxmoxbackupserver from "./proxmoxbackupserver/widget";
import pihole from "./pihole/widget";
import plantit from "./plantit/widget";
import plex from "./plex/widget";
@@ -94,50 +92,47 @@ import prometheus from "./prometheus/widget";
import prometheusmetric from "./prometheusmetric/widget";
import prowlarr from "./prowlarr/widget";
import proxmox from "./proxmox/widget";
-import proxmoxbackupserver from "./proxmoxbackupserver/widget";
import pterodactyl from "./pterodactyl/widget";
import pyload from "./pyload/widget";
import qbittorrent from "./qbittorrent/widget";
import qnap from "./qnap/widget";
import radarr from "./radarr/widget";
import readarr from "./readarr/widget";
-import romm from "./romm/widget";
import rutorrent from "./rutorrent/widget";
import sabnzbd from "./sabnzbd/widget";
import scrutiny from "./scrutiny/widget";
-import slskd from "./slskd/widget";
import sonarr from "./sonarr/widget";
import speedtest from "./speedtest/widget";
import spoolman from "./spoolman/widget";
import stash from "./stash/widget";
import stocks from "./stocks/widget";
import strelaysrv from "./strelaysrv/widget";
-import suwayomi from "./suwayomi/widget";
import swagdashboard from "./swagdashboard/widget";
+import suwayomi from "./suwayomi/widget";
import tailscale from "./tailscale/widget";
import tandoor from "./tandoor/widget";
import tautulli from "./tautulli/widget";
-import tdarr from "./tdarr/widget";
import technitium from "./technitium/widget";
+import tdarr from "./tdarr/widget";
import traefik from "./traefik/widget";
import transmission from "./transmission/widget";
-import truenas from "./truenas/widget";
import tubearchivist from "./tubearchivist/widget";
+import truenas from "./truenas/widget";
import unifi from "./unifi/widget";
import unmanic from "./unmanic/widget";
import uptimekuma from "./uptimekuma/widget";
import uptimerobot from "./uptimerobot/widget";
-import urbackup from "./urbackup/widget";
import vikunja from "./vikunja/widget";
import watchtower from "./watchtower/widget";
import wgeasy from "./wgeasy/widget";
import whatsupdocker from "./whatsupdocker/widget";
import xteve from "./xteve/widget";
+import urbackup from "./urbackup/widget";
+import romm from "./romm/widget";
import zabbix from "./zabbix/widget";
const widgets = {
adguard,
- apcups,
argocd,
atsumeru,
audiobookshelf,
@@ -162,7 +157,6 @@ const widgets = {
esphome,
evcc,
fileflows,
- firefly,
flood,
freshrss,
frigate,
@@ -178,8 +172,6 @@ const widgets = {
grafana,
hdhomerun,
headscale,
- hoarder: karakeep,
- karakeep,
homeassistant,
homebox,
homebridge,
@@ -246,7 +238,6 @@ const widgets = {
rutorrent,
sabnzbd,
scrutiny,
- slskd,
sonarr,
speedtest,
spoolman,
diff --git a/src/widgets/xteve/component.jsx b/src/widgets/xteve/component.jsx
index 41f2beb0..84a617c2 100644
--- a/src/widgets/xteve/component.jsx
+++ b/src/widgets/xteve/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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 }) {
diff --git a/src/widgets/xteve/proxy.js b/src/widgets/xteve/proxy.js
index 53d82bc4..453e3645 100644
--- a/src/widgets/xteve/proxy.js
+++ b/src/widgets/xteve/proxy.js
@@ -1,8 +1,8 @@
-import getServiceWidget from "utils/config/service-helpers";
-import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
+import createLogger from "utils/logger";
import widgets from "widgets/widgets";
+import getServiceWidget from "utils/config/service-helpers";
const logger = createLogger("xteveProxyHandler");
diff --git a/src/widgets/zabbix/component.jsx b/src/widgets/zabbix/component.jsx
index b6a5b20b..ffad9f7f 100644
--- a/src/widgets/zabbix/component.jsx
+++ b/src/widgets/zabbix/component.jsx
@@ -1,7 +1,7 @@
-import Block from "components/services/widget/block";
-import Container from "components/services/widget/container";
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";
const PriorityUnclassified = "0";
diff --git a/tailwind.config.js b/tailwind.config.js
index 4cc6f130..5d425938 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -30,7 +30,55 @@ module.exports = {
900: "rgb(var(--color-900) / )",
},
},
+ screens: {
+ "3xl": "1800px",
+ // => @media (min-width: 1800px) { ... }
+ },
},
},
plugins: [tailwindForms, tailwindScrollbars],
+ // always include these in build as classes are dynamically constructed
+ safelist: [
+ "backdrop-blur",
+ "backdrop-blur-sm",
+ "backdrop-blur-md",
+ "backdrop-blur-xl",
+ "backdrop-saturate-0",
+ "backdrop-saturate-50",
+ "backdrop-saturate-100",
+ "backdrop-saturate-150",
+ "backdrop-saturate-200",
+ "backdrop-brightness-0",
+ "backdrop-brightness-50",
+ "backdrop-brightness-75",
+ "backdrop-brightness-90",
+ "backdrop-brightness-95",
+ "backdrop-brightness-100",
+ "backdrop-brightness-105",
+ "backdrop-brightness-110",
+ "backdrop-brightness-125",
+ "backdrop-brightness-150",
+ "backdrop-brightness-200",
+ "grid-cols-1",
+ "md:grid-cols-1",
+ "md:grid-cols-2",
+ "lg:grid-cols-1",
+ "lg:grid-cols-2",
+ "lg:grid-cols-3",
+ "lg:grid-cols-4",
+ "lg:grid-cols-5",
+ "lg:grid-cols-6",
+ "lg:grid-cols-7",
+ "lg:grid-cols-8",
+ // for status
+ "bg-white",
+ "bg-black",
+ "dark:bg-white",
+ "bg-orange-400",
+ "dark:bg-orange-400",
+ {
+ pattern: /h-([0-96])/,
+ variants: ["sm", "md", "lg", "xl", "2xl"],
+ },
+ ],
};