Another batch

This commit is contained in:
shamoon
2026-08-21 12:33:35 -07:00
parent 08bddc288e
commit 69f20bf38a
24 changed files with 85 additions and 124 deletions
+5 -10
View File
@@ -2,19 +2,14 @@ import Block from "components/services/widget/block";
import Container from "components/services/widget/container"; import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["apps", "synced", "outOfSync", "healthy"];
export default function Component({ service: configuredService }) {
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
if (!widget.fields) {
widget.fields = ["apps", "synced", "outOfSync", "healthy"];
}
const MAX_ALLOWED_FIELDS = 4;
if (widget.fields.length > MAX_ALLOWED_FIELDS) {
widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
}
const { data: appsData, error: appsError } = useWidgetAPI(widget, "applications"); const { data: appsData, error: appsError } = useWidgetAPI(widget, "applications");
const appCounts = widget.fields.map((status) => { const appCounts = widget.fields.map((status) => {
+1 -1
View File
@@ -25,7 +25,7 @@ describe("widgets/argocd/component", () => {
const service = { widget: { type: "argocd", fields: ["apps", "synced", "outOfSync", "healthy", "extra"] } }; const service = { widget: { type: "argocd", fields: ["apps", "synced", "outOfSync", "healthy", "extra"] } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["apps", "synced", "outOfSync", "healthy"]); expect(service.widget.fields).toEqual(["apps", "synced", "outOfSync", "healthy", "extra"]);
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("argocd.apps")).toBeInTheDocument(); expect(screen.getByText("argocd.apps")).toBeInTheDocument();
expect(screen.getByText("argocd.synced")).toBeInTheDocument(); expect(screen.getByText("argocd.synced")).toBeInTheDocument();
+5 -7
View File
@@ -3,10 +3,14 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["online", "offline", "offline_alt", "total"];
export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { data: resultData, error: resultError } = useWidgetAPI(widget); const { data: resultData, error: resultError } = useWidgetAPI(widget);
@@ -14,12 +18,6 @@ export default function Component({ service }) {
return <Container service={service} error={resultError} />; return <Container service={service} error={resultError} />;
} }
if (!widget.fields || widget.fields.length === 0) {
widget.fields = ["online", "offline", "offline_alt", "total"];
} else if (widget.fields.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
if (!resultData) { if (!resultData) {
return ( return (
<Container service={service}> <Container service={service}>
+1 -1
View File
@@ -22,7 +22,7 @@ describe("widgets/esphome/component", () => {
const service = { widget: { type: "esphome" } }; const service = { widget: { type: "esphome" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["online", "offline", "offline_alt", "total"]); expect(service.widget.fields).toBeUndefined();
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("esphome.online")).toBeInTheDocument(); expect(screen.getByText("esphome.online")).toBeInTheDocument();
expect(screen.getByText("esphome.offline")).toBeInTheDocument(); expect(screen.getByText("esphome.offline")).toBeInTheDocument();
+5 -11
View File
@@ -3,8 +3,12 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["map", "currentPlayers", "ping"];
export default function Component({ service: configuredService }) {
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { data: serverData, error: serverError } = useWidgetAPI(widget, "status"); const { data: serverData, error: serverError } = useWidgetAPI(widget, "status");
const { t } = useTranslation(); const { t } = useTranslation();
@@ -13,16 +17,6 @@ export default function Component({ service }) {
return <Container service={service} error={serverError} />; return <Container service={service} error={serverError} />;
} }
// Default fields
if (widget.fields == null || widget.fields.length === 0) {
widget.fields = ["map", "currentPlayers", "ping"];
}
const MAX_ALLOWED_FIELDS = 4;
// Limits max number of displayed fields
if (widget.fields != null && widget.fields.length > MAX_ALLOWED_FIELDS) {
widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
}
if (!serverData) { if (!serverData) {
return ( return (
<Container service={service}> <Container service={service}>
+2 -2
View File
@@ -22,7 +22,7 @@ describe("widgets/gamedig/component", () => {
const service = { widget: { type: "gamedig", url: "http://x" } }; const service = { widget: { type: "gamedig", url: "http://x" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["map", "currentPlayers", "ping"]); expect(service.widget.fields).toBeUndefined();
expect(container.querySelectorAll(".service-block")).toHaveLength(3); expect(container.querySelectorAll(".service-block")).toHaveLength(3);
expect(screen.getByText("gamedig.map")).toBeInTheDocument(); expect(screen.getByText("gamedig.map")).toBeInTheDocument();
expect(screen.getByText("gamedig.currentPlayers")).toBeInTheDocument(); expect(screen.getByText("gamedig.currentPlayers")).toBeInTheDocument();
@@ -54,7 +54,7 @@ describe("widgets/gamedig/component", () => {
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["status", "name", "map", "currentPlayers"]); expect(service.widget.fields).toEqual(["status", "name", "map", "currentPlayers", "ping"]);
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expectBlockValue(container, "gamedig.status", "gamedig.online"); expectBlockValue(container, "gamedig.status", "gamedig.online");
+5 -5
View File
@@ -2,14 +2,14 @@ import Block from "components/services/widget/block";
import Container from "components/services/widget/container"; import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["public_ip", "region", "country"];
export default function Component({ service: configuredService }) {
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
if (!widget.fields) {
widget.fields = ["public_ip", "region", "country"];
}
const { data: gluetunData, error: gluetunError } = useWidgetAPI(widget, "ip"); const { data: gluetunData, error: gluetunError } = useWidgetAPI(widget, "ip");
const includePF = widget.fields.includes("port_forwarded"); const includePF = widget.fields.includes("port_forwarded");
const pfEndpoint = widget.version > 1 ? "port_forwarded_v2" : "port_forwarded"; const pfEndpoint = widget.version > 1 ? "port_forwarded_v2" : "port_forwarded";
+1 -1
View File
@@ -22,7 +22,7 @@ describe("widgets/gluetun/component", () => {
const service = { widget: { type: "gluetun", url: "http://x" } }; const service = { widget: { type: "gluetun", url: "http://x" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["public_ip", "region", "country"]); expect(service.widget.fields).toBeUndefined();
expect(container.querySelectorAll(".service-block")).toHaveLength(3); expect(container.querySelectorAll(".service-block")).toHaveLength(3);
expect(screen.getByText("gluetun.public_ip")).toBeInTheDocument(); expect(screen.getByText("gluetun.public_ip")).toBeInTheDocument();
expect(screen.getByText("gluetun.region")).toBeInTheDocument(); expect(screen.getByText("gluetun.region")).toBeInTheDocument();
+5 -10
View File
@@ -2,8 +2,12 @@ import Block from "components/services/widget/block";
import Container from "components/services/widget/container"; import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["channels", "hd"];
export default function Component({ service: configuredService }) {
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { tuner = 0 } = widget; const { tuner = 0 } = widget;
@@ -24,15 +28,6 @@ export default function Component({ service }) {
); );
} }
// Provide a default if not set in the config
if (!widget.fields) {
widget.fields = ["channels", "hd"];
}
// Limit to a maximum of 4 at a time
if (widget.fields.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
return ( return (
<Container service={service}> <Container service={service}>
<Block label="hdhomerun.channels" value={channelsData?.length} /> <Block label="hdhomerun.channels" value={channelsData?.length} />
+1 -1
View File
@@ -58,7 +58,7 @@ describe("widgets/hdhomerun/component", () => {
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["channels", "hd", "tunerCount", "channelNumber"]); expect(service.widget.fields).toEqual(["channels", "hd", "tunerCount", "channelNumber", "signalStrength"]);
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("hdhomerun.channels")).toBeInTheDocument(); expect(screen.getByText("hdhomerun.channels")).toBeInTheDocument();
expect(screen.getByText("hdhomerun.hd")).toBeInTheDocument(); expect(screen.getByText("hdhomerun.hd")).toBeInTheDocument();
+3 -11
View File
@@ -3,11 +3,13 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export const homeboxDefaultFields = ["items", "locations", "totalValue"]; export const homeboxDefaultFields = ["items", "locations", "totalValue"];
export default function Component({ service }) { export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, homeboxDefaultFields);
const { widget } = service; const { widget } = service;
const { data: homeboxData, error: homeboxError } = useWidgetAPI(widget); const { data: homeboxData, error: homeboxError } = useWidgetAPI(widget);
@@ -15,16 +17,6 @@ export default function Component({ service }) {
return <Container service={service} error={homeboxError} />; return <Container service={service} error={homeboxError} />;
} }
// Default fields
if (!widget.fields?.length > 0) {
widget.fields = homeboxDefaultFields;
}
const MAX_ALLOWED_FIELDS = 4;
// Limits max number of displayed fields
if (widget.fields?.length > MAX_ALLOWED_FIELDS) {
widget.fields = widget.fields.slice(0, MAX_ALLOWED_FIELDS);
}
if (!homeboxData) { if (!homeboxData) {
return ( return (
<Container service={service}> <Container service={service}>
+2 -2
View File
@@ -9,7 +9,7 @@ import { expectBlockValue } from "test-utils/widget-assertions";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() })); const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI })); vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
import Component, { homeboxDefaultFields } from "./component"; import Component from "./component";
describe("widgets/homebox/component", () => { describe("widgets/homebox/component", () => {
beforeEach(() => { beforeEach(() => {
@@ -22,7 +22,7 @@ describe("widgets/homebox/component", () => {
const service = { widget: { type: "homebox", url: "http://x" } }; const service = { widget: { type: "homebox", url: "http://x" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(homeboxDefaultFields); expect(service.widget.fields).toBeUndefined();
expect(container.querySelectorAll(".service-block")).toHaveLength(3); expect(container.querySelectorAll(".service-block")).toHaveLength(3);
expect(screen.getByText("homebox.items")).toBeInTheDocument(); expect(screen.getByText("homebox.items")).toBeInTheDocument();
expect(screen.getByText("homebox.locations")).toBeInTheDocument(); expect(screen.getByText("homebox.locations")).toBeInTheDocument();
+5 -7
View File
@@ -6,6 +6,9 @@ import { MdOutlineSmartDisplay } from "react-icons/md";
import { getURLSearchParams } from "utils/proxy/api-helpers"; import { getURLSearchParams } from "utils/proxy/api-helpers";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
const DEFAULT_FIELDS = ["movies", "series", "episodes", "songs"];
function ticksToTime(ticks) { function ticksToTime(ticks) {
const milliseconds = ticks / 10000; const milliseconds = ticks / 10000;
@@ -178,12 +181,6 @@ function CountBlocks({ service, countData }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { widget } = service; const { widget } = service;
if (!widget.fields || widget.fields.length === 0) {
widget.fields = ["movies", "series", "episodes", "songs"];
} else if (widget.fields?.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
if (!countData) { if (!countData) {
return ( return (
<Container service={service}> <Container service={service}>
@@ -207,9 +204,10 @@ function CountBlocks({ service, countData }) {
); );
} }
export default function Component({ service }) { export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const version = widget?.version ?? 1; const version = widget?.version ?? 1;
const useJellyfinV2 = version === 2; const useJellyfinV2 = version === 2;
+1 -1
View File
@@ -109,7 +109,7 @@ describe("widgets/jellyfin/component", () => {
renderWithProviders(<Component service={service} />); renderWithProviders(<Component service={service} />);
expect(service.widget.fields).toEqual(["movies", "series", "episodes", "albums"]); expect(service.widget.fields).toEqual(["movies", "series", "episodes", "albums", "songs"]);
expect(screen.getByText("jellyfin.albums")).toBeInTheDocument(); expect(screen.getByText("jellyfin.albums")).toBeInTheDocument();
expect(screen.getByText("5")).toBeInTheDocument(); expect(screen.getByText("5")).toBeInTheDocument();
expect(screen.queryByText("jellyfin.songs")).not.toBeInTheDocument(); expect(screen.queryByText("jellyfin.songs")).not.toBeInTheDocument();
+6 -6
View File
@@ -3,13 +3,13 @@ import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) { export default function Component({ service: configuredService }) {
const { widget } = service; const configuredDays = configuredService.widget.days;
const days = Number.isInteger(configuredDays) && configuredDays > 0 ? configuredDays : 30;
const widget = { ...configuredService.widget, days };
const service = { ...configuredService, widget };
// Days validation const { data: viewsData, error: viewsError } = useWidgetAPI(widget, "getViewsByLibraryType", { days });
if (!(Number.isInteger(widget.days) && 0 < widget.days)) widget.days = 30;
const { data: viewsData, error: viewsError } = useWidgetAPI(widget, "getViewsByLibraryType", { days: widget.days });
const error = viewsError || viewsData?.message; const error = viewsError || viewsData?.message;
if (error) { if (error) {
+2 -2
View File
@@ -26,8 +26,8 @@ describe("widgets/jellystat/component", () => {
const service = { widget: { type: "jellystat", days: -1 } }; const service = { widget: { type: "jellystat", days: -1 } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.days).toBe(30); expect(service.widget.days).toBe(-1);
expect(useWidgetAPI).toHaveBeenCalledWith(service.widget, "getViewsByLibraryType", { days: 30 }); expect(useWidgetAPI).toHaveBeenCalledWith({ type: "jellystat", days: 30 }, "getViewsByLibraryType", { days: 30 });
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("jellystat.songs")).toBeInTheDocument(); expect(screen.getByText("jellystat.songs")).toBeInTheDocument();
+5 -7
View File
@@ -3,6 +3,9 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
const DEFAULT_FIELDS = ["title", "message", "priority", "lastReceived"];
const priorityLabels = { const priorityLabels = {
1: "min", 1: "min",
@@ -20,8 +23,9 @@ function Truncated({ text }) {
); );
} }
export default function Component({ service }) { export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { data: messagesData, error: messagesError } = useWidgetAPI(widget, "messages"); const { data: messagesData, error: messagesError } = useWidgetAPI(widget, "messages");
@@ -30,12 +34,6 @@ export default function Component({ service }) {
return <Container service={service} error={messagesError} />; return <Container service={service} error={messagesError} />;
} }
if (!widget.fields || widget.fields.length === 0) {
widget.fields = ["title", "message", "priority", "lastReceived"];
} else if (widget.fields?.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
if (!messagesData) { if (!messagesData) {
return ( return (
<Container service={service}> <Container service={service}>
+5 -7
View File
@@ -3,10 +3,14 @@ import { useTranslation } from "next-i18next/pages";
import Block from "../../components/services/widget/block"; import Block from "../../components/services/widget/block";
import Container from "../../components/services/widget/container"; import Container from "../../components/services/widget/container";
import useWidgetAPI from "../../utils/proxy/use-widget-api"; import useWidgetAPI from "../../utils/proxy/use-widget-api";
import withWidgetFields from "../../utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["connectedAp", "activeUser", "alerts", "connectedGateways"];
export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { data: omadaData, error: omadaAPIError } = useWidgetAPI(widget, "info", { const { data: omadaData, error: omadaAPIError } = useWidgetAPI(widget, "info", {
@@ -17,12 +21,6 @@ export default function Component({ service }) {
return <Container service={service} error={omadaAPIError} />; return <Container service={service} error={omadaAPIError} />;
} }
if (!widget.fields) {
widget.fields = ["connectedAp", "activeUser", "alerts", "connectedGateways"];
} else if (widget.fields?.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
if (!omadaData) { if (!omadaData) {
return ( return (
<Container service={service}> <Container service={service}>
+5 -5
View File
@@ -3,10 +3,14 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["queries", "blocked", "gravity"];
export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { data: piholeData, error: piholeError } = useWidgetAPI(widget); const { data: piholeData, error: piholeError } = useWidgetAPI(widget);
@@ -15,10 +19,6 @@ export default function Component({ service }) {
return <Container service={service} error={piholeError} />; return <Container service={service} error={piholeError} />;
} }
if (!widget.fields) {
widget.fields = ["queries", "blocked", "gravity"];
}
if (!piholeData) { if (!piholeData) {
return ( return (
<Container service={service}> <Container service={service}>
+8 -14
View File
@@ -4,23 +4,27 @@ import { useTranslation } from "next-i18next/pages";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { formatProxyUrl } from "utils/proxy/api-helpers"; import { formatProxyUrl } from "utils/proxy/api-helpers";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["scenes", "images"];
export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { widget } = service; const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const requestWidget = configuredService.widget;
const [stats, setStats] = useState(null); const [stats, setStats] = useState(null);
useEffect(() => { useEffect(() => {
async function fetchStats() { async function fetchStats() {
const url = formatProxyUrl(widget, "stats"); const url = formatProxyUrl(requestWidget, "stats");
const res = await fetch(url, { method: "POST" }); const res = await fetch(url, { method: "POST" });
setStats(await res.json()); setStats(await res.json());
} }
if (!stats) { if (!stats) {
fetchStats(); fetchStats();
} }
}, [widget, stats]); }, [requestWidget, stats]);
if (!stats) { if (!stats) {
return ( return (
@@ -31,16 +35,6 @@ export default function Component({ service }) {
); );
} }
// Provide a default if not set in the config
if (!widget.fields) {
widget.fields = ["scenes", "images"];
}
// Limit to a maximum of 4 at a time
if (widget.fields.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
return ( return (
<Container service={service}> <Container service={service}>
<Block label="stash.scenes" value={t("common.number", { value: stats.scene_count })} /> <Block label="stash.scenes" value={t("common.number", { value: stats.scene_count })} />
+5 -6
View File
@@ -3,10 +3,14 @@ import Container from "components/services/widget/container";
import { useTranslation } from "next-i18next/pages"; import { useTranslation } from "next-i18next/pages";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["download", "nondownload", "read", "unread"];
export default function Component({ service: configuredService }) {
const { t } = useTranslation(); const { t } = useTranslation();
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const { data: suwayomiData, error: suwayomiError } = useWidgetAPI(widget); const { data: suwayomiData, error: suwayomiError } = useWidgetAPI(widget);
@@ -16,11 +20,6 @@ export default function Component({ service }) {
} }
if (!suwayomiData) { if (!suwayomiData) {
if (!widget.fields || widget.fields.length === 0) {
widget.fields = ["download", "nondownload", "read", "unread"];
} else if (widget.fields.length > 4) {
widget.fields = widget.fields.slice(0, 4);
}
return ( return (
<Container service={service}> <Container service={service}>
{widget.fields.map((field) => ( {widget.fields.map((field) => (
+1 -1
View File
@@ -22,7 +22,7 @@ describe("widgets/suwayomi/component", () => {
const service = { widget: { type: "suwayomi" } }; const service = { widget: { type: "suwayomi" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["download", "nondownload", "read", "unread"]); expect(service.widget.fields).toBeUndefined();
expect(container.querySelectorAll(".service-block")).toHaveLength(4); expect(container.querySelectorAll(".service-block")).toHaveLength(4);
expect(screen.getByText("suwayomi.download")).toBeInTheDocument(); expect(screen.getByText("suwayomi.download")).toBeInTheDocument();
expect(screen.getByText("suwayomi.nondownload")).toBeInTheDocument(); expect(screen.getByText("suwayomi.nondownload")).toBeInTheDocument();
+5 -5
View File
@@ -2,18 +2,18 @@ import Block from "components/services/widget/block";
import Container from "components/services/widget/container"; import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api"; import useWidgetAPI from "utils/proxy/use-widget-api";
import withWidgetFields from "utils/widget-fields";
export default function Component({ service }) { const DEFAULT_FIELDS = ["connected", "enabled", "total"];
export default function Component({ service: configuredService }) {
const service = withWidgetFields(configuredService, DEFAULT_FIELDS);
const { widget } = service; const { widget } = service;
const endpoint = widget.version === 2 ? "clientv2" : "client"; const endpoint = widget.version === 2 ? "clientv2" : "client";
const { data: infoData, error: infoError } = useWidgetAPI(widget, endpoint); const { data: infoData, error: infoError } = useWidgetAPI(widget, endpoint);
if (!widget.fields) {
widget.fields = ["connected", "enabled", "total"];
}
if (infoError || infoData?.statusCode > 400) { if (infoError || infoData?.statusCode > 400) {
return <Container service={service} error={infoError ?? { message: infoData.statusMessage, data: infoData }} />; return <Container service={service} error={infoError ?? { message: infoData.statusMessage, data: infoData }} />;
} }
+1 -1
View File
@@ -28,7 +28,7 @@ describe("widgets/wgeasy/component", () => {
const service = { widget: { type: "wgeasy" } }; const service = { widget: { type: "wgeasy" } };
const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } }); const { container } = renderWithProviders(<Component service={service} />, { settings: { hideErrors: false } });
expect(service.widget.fields).toEqual(["connected", "enabled", "total"]); expect(service.widget.fields).toBeUndefined();
// Container filters by widget.fields; "disabled" is not included by default. // Container filters by widget.fields; "disabled" is not included by default.
expect(container.querySelectorAll(".service-block")).toHaveLength(3); expect(container.querySelectorAll(".service-block")).toHaveLength(3);
expect(screen.getByText("wgeasy.connected")).toBeInTheDocument(); expect(screen.getByText("wgeasy.connected")).toBeInTheDocument();