feat(sabnzbd): add archived history options to the Downloads widget (#6515)

This commit is contained in:
Sobe Silvertree authored and GitHub committed 2026-10-05 14:51:03 +02:00
1 parent 4dbe4343e5
commit 67196975f3
13 files changed
+428 -7

No files matched your search

@@ -319,6 +319,8 @@ export default function DownloadClientsWidget({
const downloadsQuery = clientApi.widget.downloads.getJobsAndStatuses.useQuery({
integrationIds,
limitPerIntegration: options.limitPerIntegration,
includeArchivedHistory: options.includeArchivedHistory,
historyWindowDays: options.historyWindowDays,
});
const currentItems = getUsableWidgetQueryData(downloadsQuery);
const availableItems = useMemo(() => currentItems?.filter((item) => item.data !== null) ?? [], [currentItems]);
@@ -0,0 +1,38 @@
import { describe, expect, test } from "vitest";
import { definition } from ".";
describe("Downloads widget history options", () => {
test.each([1, 7, 14, 28])("accepts an arbitrary %i-day window", (days) => {
const options = definition.createOptions();
expect(options.historyWindowDays.validate.safeParse(days).success).toBe(true);
});
test.each([0, -1, 1.5, "7"])("rejects an invalid day window %s", (days) => {
const options = definition.createOptions();
expect(options.historyWindowDays.validate.safeParse(days).success).toBe(false);
});
test("only matches results for its own archive settings", () => {
const input = {
integrationIds: ["sabnzbd-1"],
limitPerIntegration: 50,
includeArchivedHistory: true,
historyWindowDays: 7,
};
const scope = {
itemId: "widget-1",
boardId: "board-1",
integrationIds: input.integrationIds,
options: input,
runtimeQueries: [],
};
const query = { path: ["widget", "downloads", "getJobsAndStatuses"], input };
expect(definition.queryMatcher(query, scope)).toBe(true);
expect(definition.queryMatcher({ ...query, input: { ...input, historyWindowDays: 14 } }, scope)).toBe(false);
expect(definition.queryMatcher({ ...query, input: { ...input, includeArchivedHistory: false } }, scope)).toBe(
false,
);
});
});
+19
View File
@@ -30,6 +30,8 @@ export const { definition, componentLoader } = createWidgetDefinition("downloads
widgetQueryInputMatches(input, {
integrationIds: scope.integrationIds,
limitPerIntegration: scope.options.limitPerIntegration,
includeArchivedHistory: scope.options.includeArchivedHistory,
historyWindowDays: scope.options.historyWindowDays,
}),
refetchInterval: 10,
createOptions() {
@@ -62,6 +64,16 @@ export const { definition, componentLoader } = createWidgetDefinition("downloads
showCompletedHttp: factory.switch({
defaultValue: true,
}),
includeArchivedHistory: factory.switch({
defaultValue: false,
withDescription: true,
}),
historyWindowDays: factory.number({
defaultValue: 7,
validate: z.number().int().min(1),
step: 1,
withDescription: true,
}),
activeTorrentThreshold: factory.number({
validate: z.number().min(0),
defaultValue: 0,
@@ -89,6 +101,13 @@ export const { definition, componentLoader } = createWidgetDefinition("downloads
{
columnOrder: { shouldHide: () => true },
columnWidths: { shouldHide: () => true },
includeArchivedHistory: {
shouldHide: (_, integrationKinds) => !integrationKinds.includes("sabNzbd"),
},
historyWindowDays: {
shouldHide: ({ includeArchivedHistory }, integrationKinds) =>
!integrationKinds.includes("sabNzbd") || !includeArchivedHistory,
},
showCompletedUsenet: {
shouldHide: (_, integrationKinds) =>
!getIntegrationKindsByCategory("usenet").some((kinds) => integrationKinds.includes(kinds)),