diff --git a/src/utils/proxy/handlers/generic.js b/src/utils/proxy/handlers/generic.js
index e7653c708..8ee1c41dd 100644
--- a/src/utils/proxy/handlers/generic.js
+++ b/src/utils/proxy/handlers/generic.js
@@ -49,7 +49,7 @@ export default async function genericProxyHandler(req, res, map) {
}
}
- const [status, contentType, data] = await httpProxy(url, params);
+ const [status, contentType, data, responseHeaders] = await httpProxy(url, params);
let resultData = data;
@@ -63,7 +63,7 @@ export default async function genericProxyHandler(req, res, map) {
.status(status)
.json({ error: { message: "Invalid data", url: sanitizeErrorURL(url), data: resultData } });
}
- if (map) resultData = map(resultData);
+ if (map) resultData = map(resultData, responseHeaders);
}
if (contentType) res.setHeader("Content-Type", contentType);
diff --git a/src/utils/proxy/handlers/generic.test.js b/src/utils/proxy/handlers/generic.test.js
index 7edca813d..14c622030 100644
--- a/src/utils/proxy/handlers/generic.test.js
+++ b/src/utils/proxy/handlers/generic.test.js
@@ -253,4 +253,20 @@ describe("utils/proxy/handlers/generic", () => {
expect(res.statusCode).toBe(200);
expect(res.body).toEqual({ mapped: true });
});
+
+ it("passes the response headers to the mapping function", async () => {
+ getServiceWidget.mockResolvedValue({
+ type: "testservice",
+ url: "http://example",
+ });
+ httpProxy.mockResolvedValueOnce([200, "application/json", { ok: true }, { "x-total-count": "42" }]);
+
+ const req = { method: "GET", query: { group: "g", service: "svc", endpoint: "api", index: "0" } };
+ const res = createMockRes();
+
+ await genericProxyHandler(req, res, (data, headers) => ({ total: headers["x-total-count"] }));
+
+ expect(res.statusCode).toBe(200);
+ expect(res.body).toEqual({ total: "42" });
+ });
});
diff --git a/src/widgets/gitea/component.jsx b/src/widgets/gitea/component.jsx
index 3b0b078fd..8cc688c4f 100644
--- a/src/widgets/gitea/component.jsx
+++ b/src/widgets/gitea/component.jsx
@@ -7,15 +7,15 @@ export default function Component({ service }) {
const { data: giteaNotifications, error: giteaNotificationsError } = useWidgetAPI(widget, "notifications");
const { data: giteaIssues, error: giteaIssuesError } = useWidgetAPI(widget, "issues");
+ const { data: giteaPulls, error: giteaPullsError } = useWidgetAPI(widget, "pulls");
const { data: giteaRepositories, error: giteaRepositoriesError } = useWidgetAPI(widget, "repositories");
- if (giteaNotificationsError || giteaIssuesError || giteaRepositoriesError) {
- return (
-
- );
+ const error = giteaNotificationsError ?? giteaIssuesError ?? giteaPullsError ?? giteaRepositoriesError;
+ if (error) {
+ return ;
}
- if (!giteaNotifications || !giteaIssues || !giteaRepositories) {
+ if (!giteaNotifications || !giteaIssues || !giteaPulls || !giteaRepositories) {
return (
@@ -28,10 +28,10 @@ export default function Component({ service }) {
return (
-
-
-
-
+
+
+
+
);
}
diff --git a/src/widgets/gitea/component.test.jsx b/src/widgets/gitea/component.test.jsx
index c0325bba1..13c4167ed 100644
--- a/src/widgets/gitea/component.test.jsx
+++ b/src/widgets/gitea/component.test.jsx
@@ -20,6 +20,7 @@ describe("widgets/gitea/component", () => {
useWidgetAPI
.mockReturnValueOnce({ data: undefined, error: undefined }) // notifications
.mockReturnValueOnce({ data: undefined, error: undefined }) // issues
+ .mockReturnValueOnce({ data: undefined, error: undefined }) // pulls
.mockReturnValueOnce({ data: undefined, error: undefined }); // repositories
const { container } = renderWithProviders(, {
@@ -38,6 +39,7 @@ describe("widgets/gitea/component", () => {
useWidgetAPI
.mockReturnValueOnce({ data: undefined, error: undefined })
.mockReturnValueOnce({ data: undefined, error: { message: "nope" } })
+ .mockReturnValueOnce({ data: undefined, error: undefined })
.mockReturnValueOnce({ data: undefined, error: undefined });
renderWithProviders(, {
@@ -48,22 +50,20 @@ describe("widgets/gitea/component", () => {
expect(screen.getByText("nope")).toBeInTheDocument();
});
- it("renders computed counts when loaded", () => {
+ it("renders total counts when loaded", () => {
useWidgetAPI
- .mockReturnValueOnce({ data: [{ id: 1 }, { id: 2 }], error: undefined })
- .mockReturnValueOnce({
- data: { issues: [{ id: 1 }], pulls: [{ id: 1 }, { id: 2 }, { id: 3 }] },
- error: undefined,
- })
- .mockReturnValueOnce({ data: { data: [{ id: 1 }] }, error: undefined });
+ .mockReturnValueOnce({ data: { count: 2 }, error: undefined })
+ .mockReturnValueOnce({ data: { count: 1234 }, error: undefined })
+ .mockReturnValueOnce({ data: { count: 0 }, error: undefined })
+ .mockReturnValueOnce({ data: { count: 56 }, error: undefined });
const { container } = renderWithProviders(, {
settings: { hideErrors: false },
});
expectBlockValue(container, "gitea.notifications", 2);
- expectBlockValue(container, "gitea.issues", 1);
- expectBlockValue(container, "gitea.pulls", 3);
- expectBlockValue(container, "gitea.repositories", 1);
+ expectBlockValue(container, "gitea.issues", 1234);
+ expectBlockValue(container, "gitea.pulls", 0);
+ expectBlockValue(container, "gitea.repositories", 56);
});
});
diff --git a/src/widgets/gitea/widget.js b/src/widgets/gitea/widget.js
index 003a6710d..2d7261a80 100644
--- a/src/widgets/gitea/widget.js
+++ b/src/widgets/gitea/widget.js
@@ -1,26 +1,31 @@
-import { asJson } from "utils/proxy/api-helpers";
import genericProxyHandler from "utils/proxy/handlers/generic";
+// Get total from header to avoid pagination limit
+export function totalCount(data, headers) {
+ const count = parseInt(headers?.["x-total-count"], 10);
+ return { count: Number.isNaN(count) ? null : count };
+}
+
const widget = {
api: "{url}/api/v1/{endpoint}?access_token={key}",
proxyHandler: genericProxyHandler,
mappings: {
notifications: {
- endpoint: "notifications",
+ endpoint: "notifications?limit=1",
+ map: totalCount,
},
issues: {
- endpoint: "repos/issues/search",
- map: (data) => {
- const items = asJson(data);
- return {
- pulls: items.filter((issue) => issue.pull_request),
- issues: items.filter((issue) => !issue.pull_request),
- };
- },
+ endpoint: "repos/issues/search?type=issues&limit=1",
+ map: totalCount,
+ },
+ pulls: {
+ endpoint: "repos/issues/search?type=pulls&limit=1",
+ map: totalCount,
},
repositories: {
- endpoint: "repos/search",
+ endpoint: "repos/search?limit=1",
+ map: totalCount,
},
},
};
diff --git a/src/widgets/gitea/widget.test.js b/src/widgets/gitea/widget.test.js
index 1039ad7ce..525e91058 100644
--- a/src/widgets/gitea/widget.test.js
+++ b/src/widgets/gitea/widget.test.js
@@ -2,19 +2,20 @@ import { describe, expect, it } from "vitest";
import { expectWidgetConfigShape } from "test-utils/widget-config";
-import widget from "./widget";
+import widget, { totalCount } from "./widget";
describe("gitea widget config", () => {
it("exports a valid widget config", () => {
expectWidgetConfigShape(widget);
});
- it("splits issues and pull requests", () => {
- const result = widget.mappings.issues.map(
- Buffer.from(JSON.stringify([{ id: 1, pull_request: {} }, { id: 2 }, { id: 3 }])),
- );
+ it("reads the total count from the X-Total-Count header", () => {
+ expect(totalCount(Buffer.from("[]"), { "x-total-count": "1234" })).toEqual({ count: 1234 });
+ expect(totalCount(Buffer.from("[]"), { "x-total-count": "0" })).toEqual({ count: 0 });
+ });
- expect(result.pulls.map((i) => i.id)).toEqual([1]);
- expect(result.issues.map((i) => i.id)).toEqual([2, 3]);
+ it("returns a null count when the header is missing", () => {
+ expect(totalCount(Buffer.from("[{}]"), {})).toEqual({ count: null });
+ expect(totalCount(Buffer.from("[{}]"), undefined)).toEqual({ count: null });
});
});