List only the sources an account uses on the source-priority page

The read and save of /api/auth/me/source-priority now carry inUse: the
ranked sources the account has connected or holds at least one
measurement from, one index probe per source. The settings page lists
only those, hides a metric nothing delivers, and opens one metric group
at a time, the first by default, with the winning source named on each
collapsed line. The ladders stay whole: moving a source swaps it with
its nearest listed neighbour, so a hidden source keeps its slot.
This commit is contained in:
Marc-André Bombeck committed 2026-10-08 20:40:39 +02:00
1 parent c816946140
commit 51374274aa
15 files changed
+956 -1475

No files matched your search

@@ -11,6 +11,10 @@ vi.mock("@/lib/db", () => ({
vi.mock("@/lib/auth/session", () => ({ getSession: vi.fn() }));
vi.mock("@/lib/integrations/sources-in-use", () => ({
getSourcesInUse: vi.fn().mockResolvedValue(["WITHINGS", "MANUAL"]),
}));
vi.mock("@/lib/auth/audit", () => ({
auditLog: vi.fn().mockResolvedValue(undefined),
}));
@@ -73,6 +77,17 @@ describe("GET /api/auth/me/source-priority", () => {
expect(env.data).toHaveProperty("metricPriority");
expect(env.data).toHaveProperty("deviceTypePriority");
});
it("carries the account's sources in use beside the ladders", async () => {
vi.mocked(getSession).mockResolvedValue(SESSION_OK as never);
vi.mocked(prisma.user.findUnique).mockResolvedValue({
sourcePriorityJson: null,
} as never);
const res = await (GET as () => Promise<Response>)();
const env = (await res.json()) as { data: { inUse: string[] } };
expect(env.data.inUse).toEqual(["WITHINGS", "MANUAL"]);
});
});
describe("PUT /api/auth/me/source-priority", () => {
+17 -5
View File
@@ -30,6 +30,7 @@ import { annotate } from "@/lib/logging/context";
import { auditLog } from "@/lib/auth/audit";
import { prisma } from "@/lib/db";
import { invalidateUserProfile } from "@/lib/cache/invalidate";
import { getSourcesInUse } from "@/lib/integrations/sources-in-use";
import {
parseSourcePriority,
sourcePrioritySchema,
@@ -41,11 +42,19 @@ export const GET = apiHandler(async () => {
const { user } = await requireAuth();
annotate({ action: { name: "auth.me.source-priority.get" } });
const row = await prisma.user.findUnique({
where: { id: user.id },
select: { sourcePriorityJson: true },
const [row, inUse] = await Promise.all([
prisma.user.findUnique({
where: { id: user.id },
select: { sourcePriorityJson: true },
}),
getSourcesInUse(user.id),
]);
// `inUse` is read-only context for the editor: which ranked sources this
// account has connected or holds data from. It never feeds the ladder.
return apiSuccess({
...parseSourcePriority(row?.sourcePriorityJson),
inUse,
});
return apiSuccess(parseSourcePriority(row?.sourcePriorityJson));
});
export const PUT = apiHandler(async (req: Request) => {
@@ -118,5 +127,8 @@ export const PUT = apiHandler(async (req: Request) => {
action: { name: "auth.me.source-priority.put" },
meta: { keys: Object.keys(parsed.data).length },
});
return apiSuccess(parseSourcePriority(parsed.data));
return apiSuccess({
...parseSourcePriority(parsed.data),
inUse: await getSourcesInUse(user.id),
});
});