mirror of
https://github.com/gethomepage/homepage.git
synced 2026-09-27 06:21:18 -07:00
Change: use status field as primary queue detail (#6859)
Docker CI / Docker Build & Push (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
Lint / Linting Checks (push) Has been cancelled
Release Drafter / Update Release Draft (push) Has been cancelled
Release Drafter / Auto Label PR (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Docker CI / Docker Build & Push (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
Lint / Linting Checks (push) Has been cancelled
Release Drafter / Update Release Draft (push) Has been cancelled
Release Drafter / Auto Label PR (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
This commit is contained in:
@@ -1,14 +1,37 @@
|
||||
import Block from "components/services/widget/block";
|
||||
import Container from "components/services/widget/container";
|
||||
import { useTranslation } from "next-i18next/pages";
|
||||
import { useCallback } from "react";
|
||||
|
||||
import QueueEntry from "../../components/widgets/queue/queueEntry";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
function getProgress(sizeLeft, size) {
|
||||
return sizeLeft === 0 ? 100 : (1 - sizeLeft / size) * 100;
|
||||
if (!Number.isFinite(size) || size <= 0) return 0;
|
||||
return Math.min(100, Math.max(0, (1 - sizeLeft / size) * 100));
|
||||
}
|
||||
|
||||
function formatDownloadState(downloadState) {
|
||||
switch (downloadState) {
|
||||
case "importBlocked":
|
||||
return "import blocked";
|
||||
case "importPending":
|
||||
return "import pending";
|
||||
case "failedPending":
|
||||
return "failed pending";
|
||||
default:
|
||||
return downloadState;
|
||||
}
|
||||
}
|
||||
|
||||
function getActivity(status, trackedDownloadState) {
|
||||
const completedStates = ["importBlocked", "importPending", "importing", "failedPending"];
|
||||
const downloadState =
|
||||
status === "completed" && completedStates.includes(trackedDownloadState)
|
||||
? trackedDownloadState
|
||||
: (status ?? trackedDownloadState);
|
||||
|
||||
return formatDownloadState(downloadState);
|
||||
}
|
||||
|
||||
export default function Component({ service }) {
|
||||
@@ -19,17 +42,6 @@ export default function Component({ service }) {
|
||||
const { data: queuedData, error: queuedError } = useWidgetAPI(widget, "queue/status");
|
||||
const { data: queueDetailsData, error: queueDetailsError } = useWidgetAPI(widget, "queue/details");
|
||||
|
||||
const formatDownloadState = useCallback((downloadState) => {
|
||||
switch (downloadState) {
|
||||
case "importPending":
|
||||
return "import pending";
|
||||
case "failedPending":
|
||||
return "failed pending";
|
||||
default:
|
||||
return downloadState;
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (moviesError || queuedError || queueDetailsError) {
|
||||
const finalError = moviesError ?? queuedError ?? queueDetailsError;
|
||||
return <Container service={service} error={finalError} />;
|
||||
@@ -62,7 +74,7 @@ export default function Component({ service }) {
|
||||
progress={getProgress(queueEntry.sizeLeft, queueEntry.size)}
|
||||
timeLeft={queueEntry.timeLeft}
|
||||
title={moviesData.all.find((entry) => entry.id === queueEntry.movieId)?.title ?? t("radarr.unknown")}
|
||||
activity={formatDownloadState(queueEntry.trackedDownloadState)}
|
||||
activity={getActivity(queueEntry.status, queueEntry.trackedDownloadState)}
|
||||
key={`${queueEntry.movieId}-${queueEntry.sizeLeft}`}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -10,7 +10,11 @@ const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
|
||||
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
|
||||
|
||||
vi.mock("../../components/widgets/queue/queueEntry", () => ({
|
||||
default: ({ title }) => <div data-testid="queue-entry">{title}</div>,
|
||||
default: ({ title, activity, progress }) => (
|
||||
<div data-testid="queue-entry" data-activity={activity} data-progress={progress}>
|
||||
{title}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
import Component from "./component";
|
||||
@@ -37,11 +41,37 @@ describe("widgets/radarr/component", () => {
|
||||
it("renders counts and queue entries when enabled", () => {
|
||||
useWidgetAPI.mockImplementation((_widget, endpoint) => {
|
||||
if (endpoint === "movie")
|
||||
return { data: { wanted: 1, missing: 2, have: 3, all: [{ id: 10, title: "Movie" }] }, error: undefined };
|
||||
return {
|
||||
data: {
|
||||
wanted: 1,
|
||||
missing: 2,
|
||||
have: 3,
|
||||
all: [
|
||||
{ id: 10, title: "Queued Movie" },
|
||||
{ id: 11, title: "Imported Movie" },
|
||||
],
|
||||
},
|
||||
error: undefined,
|
||||
};
|
||||
if (endpoint === "queue/status") return { data: { totalCount: 1 }, error: undefined };
|
||||
if (endpoint === "queue/details")
|
||||
return {
|
||||
data: [{ movieId: 10, sizeLeft: 50, size: 100, timeLeft: "1m", trackedDownloadState: "importPending" }],
|
||||
data: [
|
||||
{
|
||||
movieId: 10,
|
||||
sizeLeft: 0,
|
||||
size: 0,
|
||||
status: "queued",
|
||||
trackedDownloadState: "downloading",
|
||||
},
|
||||
{
|
||||
movieId: 11,
|
||||
sizeLeft: 0,
|
||||
size: 100,
|
||||
status: "completed",
|
||||
trackedDownloadState: "importPending",
|
||||
},
|
||||
],
|
||||
error: undefined,
|
||||
};
|
||||
return { data: undefined, error: undefined };
|
||||
@@ -54,6 +84,11 @@ describe("widgets/radarr/component", () => {
|
||||
expectBlockValue(container, "radarr.missing", 2);
|
||||
expectBlockValue(container, "radarr.queued", 1);
|
||||
expectBlockValue(container, "radarr.movies", 3);
|
||||
expect(screen.getAllByTestId("queue-entry").map((el) => el.textContent)).toEqual(["Movie"]);
|
||||
const queueEntries = screen.getAllByTestId("queue-entry");
|
||||
expect(queueEntries.map((el) => el.textContent)).toEqual(["Queued Movie", "Imported Movie"]);
|
||||
expect(queueEntries.map((el) => [el.dataset.activity, el.dataset.progress])).toEqual([
|
||||
["queued", "0"],
|
||||
["import pending", "100"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,8 +36,8 @@ const widget = {
|
||||
status: entry.status,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
const downloadingA = a.trackedDownloadState === "downloading";
|
||||
const downloadingB = b.trackedDownloadState === "downloading";
|
||||
const downloadingA = (a.status ?? a.trackedDownloadState) === "downloading";
|
||||
const downloadingB = (b.status ?? b.trackedDownloadState) === "downloading";
|
||||
if (downloadingA && !downloadingB) {
|
||||
return -1;
|
||||
}
|
||||
@@ -45,8 +45,8 @@ const widget = {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const percentA = a.sizeLeft / a.size;
|
||||
const percentB = b.sizeLeft / b.size;
|
||||
const percentA = a.size > 0 ? a.sizeLeft / a.size : 1;
|
||||
const percentB = b.size > 0 ? b.sizeLeft / b.size : 1;
|
||||
if (percentA < percentB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, it } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { expectWidgetConfigShape } from "test-utils/widget-config";
|
||||
|
||||
@@ -8,4 +8,29 @@ describe("radarr widget config", () => {
|
||||
it("exports a valid widget config", () => {
|
||||
expectWidgetConfigShape(widget);
|
||||
});
|
||||
|
||||
it("sorts active downloads ahead of queued downloads", () => {
|
||||
const queue = widget.mappings["queue/details"].map(
|
||||
Buffer.from(
|
||||
JSON.stringify([
|
||||
{
|
||||
movieId: 1,
|
||||
status: "queued",
|
||||
trackedDownloadState: "downloading",
|
||||
size: 0,
|
||||
sizeleft: 0,
|
||||
},
|
||||
{
|
||||
movieId: 2,
|
||||
status: "downloading",
|
||||
trackedDownloadState: "downloading",
|
||||
size: 100,
|
||||
sizeleft: 50,
|
||||
},
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
expect(queue.map((entry) => entry.movieId)).toEqual([2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
import Block from "components/services/widget/block";
|
||||
import Container from "components/services/widget/container";
|
||||
import { useTranslation } from "next-i18next/pages";
|
||||
import { useCallback } from "react";
|
||||
|
||||
import QueueEntry from "../../components/widgets/queue/queueEntry";
|
||||
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
function getProgress(sizeLeft, size) {
|
||||
return sizeLeft === 0 ? 100 : (1 - sizeLeft / size) * 100;
|
||||
if (!Number.isFinite(size) || size <= 0) return 0;
|
||||
return Math.min(100, Math.max(0, (1 - sizeLeft / size) * 100));
|
||||
}
|
||||
|
||||
function formatDownloadState(downloadState) {
|
||||
switch (downloadState) {
|
||||
case "importBlocked":
|
||||
return "import blocked";
|
||||
case "importPending":
|
||||
return "import pending";
|
||||
case "failedPending":
|
||||
return "failed pending";
|
||||
default:
|
||||
return downloadState;
|
||||
}
|
||||
}
|
||||
|
||||
function getActivity(status, trackedDownloadState) {
|
||||
const completedStates = ["importBlocked", "importPending", "importing", "failedPending"];
|
||||
const downloadState =
|
||||
status === "completed" && completedStates.includes(trackedDownloadState)
|
||||
? trackedDownloadState
|
||||
: (status ?? trackedDownloadState);
|
||||
|
||||
return formatDownloadState(downloadState);
|
||||
}
|
||||
|
||||
function getTitle(queueEntry, seriesData) {
|
||||
@@ -30,17 +53,6 @@ export default function Component({ service }) {
|
||||
const { data: seriesData, error: seriesError } = useWidgetAPI(widget, "series");
|
||||
const { data: queueDetailsData, error: queueDetailsError } = useWidgetAPI(widget, "queue/details");
|
||||
|
||||
const formatDownloadState = useCallback((downloadState) => {
|
||||
switch (downloadState) {
|
||||
case "importPending":
|
||||
return "import pending";
|
||||
case "failedPending":
|
||||
return "failed pending";
|
||||
default:
|
||||
return downloadState;
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (wantedError || queuedError || seriesError || queueDetailsError) {
|
||||
const finalError = wantedError ?? queuedError ?? seriesError ?? queueDetailsError;
|
||||
return <Container service={service} error={finalError} />;
|
||||
@@ -71,7 +83,7 @@ export default function Component({ service }) {
|
||||
progress={getProgress(queueEntry.sizeLeft, queueEntry.size)}
|
||||
timeLeft={queueEntry.timeLeft}
|
||||
title={getTitle(queueEntry, seriesData) ?? t("sonarr.unknown")}
|
||||
activity={formatDownloadState(queueEntry.trackedDownloadState)}
|
||||
activity={getActivity(queueEntry.status, queueEntry.trackedDownloadState)}
|
||||
key={`${queueEntry.seriesId}-${queueEntry.episodeId}`}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -10,7 +10,11 @@ const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
|
||||
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
|
||||
|
||||
vi.mock("../../components/widgets/queue/queueEntry", () => ({
|
||||
default: ({ title }) => <div data-testid="queue-entry">{title}</div>,
|
||||
default: ({ title, activity, progress }) => (
|
||||
<div data-testid="queue-entry" data-activity={activity} data-progress={progress}>
|
||||
{title}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
import Component from "./component";
|
||||
@@ -44,10 +48,19 @@ describe("widgets/sonarr/component", () => {
|
||||
{
|
||||
seriesId: 10,
|
||||
episodeId: 1,
|
||||
episodeTitle: "Ep",
|
||||
sizeLeft: 50,
|
||||
episodeTitle: "Queued Ep",
|
||||
sizeLeft: 0,
|
||||
size: 0,
|
||||
status: "queued",
|
||||
trackedDownloadState: "downloading",
|
||||
},
|
||||
{
|
||||
seriesId: 10,
|
||||
episodeId: 2,
|
||||
episodeTitle: "Imported Ep",
|
||||
sizeLeft: 0,
|
||||
size: 100,
|
||||
timeLeft: "1m",
|
||||
status: "completed",
|
||||
trackedDownloadState: "importPending",
|
||||
},
|
||||
],
|
||||
@@ -63,6 +76,11 @@ describe("widgets/sonarr/component", () => {
|
||||
expectBlockValue(container, "sonarr.wanted", 1);
|
||||
expectBlockValue(container, "sonarr.queued", 2);
|
||||
expectBlockValue(container, "sonarr.series", 1);
|
||||
expect(screen.getAllByTestId("queue-entry").map((el) => el.textContent)).toEqual(["Show: Ep"]);
|
||||
const queueEntries = screen.getAllByTestId("queue-entry");
|
||||
expect(queueEntries.map((el) => el.textContent)).toEqual(["Show: Queued Ep", "Show: Imported Ep"]);
|
||||
expect(queueEntries.map((el) => [el.dataset.activity, el.dataset.progress])).toEqual([
|
||||
["queued", "0"],
|
||||
["import pending", "100"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,8 +38,8 @@ const widget = {
|
||||
status: entry.status,
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
const downloadingA = a.trackedDownloadState === "downloading";
|
||||
const downloadingB = b.trackedDownloadState === "downloading";
|
||||
const downloadingA = (a.status ?? a.trackedDownloadState) === "downloading";
|
||||
const downloadingB = (b.status ?? b.trackedDownloadState) === "downloading";
|
||||
if (downloadingA && !downloadingB) {
|
||||
return -1;
|
||||
}
|
||||
@@ -47,8 +47,8 @@ const widget = {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const percentA = a.sizeLeft / a.size;
|
||||
const percentB = b.sizeLeft / b.size;
|
||||
const percentA = a.size > 0 ? a.sizeLeft / a.size : 1;
|
||||
const percentB = b.size > 0 ? b.sizeLeft / b.size : 1;
|
||||
if (percentA < percentB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, it } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { expectWidgetConfigShape } from "test-utils/widget-config";
|
||||
|
||||
@@ -8,4 +8,29 @@ describe("sonarr widget config", () => {
|
||||
it("exports a valid widget config", () => {
|
||||
expectWidgetConfigShape(widget);
|
||||
});
|
||||
|
||||
it("sorts active downloads ahead of queued downloads", () => {
|
||||
const queue = widget.mappings["queue/details"].map(
|
||||
Buffer.from(
|
||||
JSON.stringify([
|
||||
{
|
||||
episodeId: 1,
|
||||
status: "queued",
|
||||
trackedDownloadState: "downloading",
|
||||
size: 0,
|
||||
sizeleft: 0,
|
||||
},
|
||||
{
|
||||
episodeId: 2,
|
||||
status: "downloading",
|
||||
trackedDownloadState: "downloading",
|
||||
size: 100,
|
||||
sizeleft: 50,
|
||||
},
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
expect(queue.map((entry) => entry.episodeId)).toEqual([2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user