diff --git a/app/(main)/data-collection/page.tsx b/app/(main)/data-collection/page.tsx index f1b5a252..ce5aad20 100644 --- a/app/(main)/data-collection/page.tsx +++ b/app/(main)/data-collection/page.tsx @@ -25,6 +25,7 @@ import { type SchedulerRunRowDto, type UptimeSettingsDto, } from "@/lib/scheduler-settings" +import { listSchedulerRuns } from "@/shared/api/scheduler" import { requestJson, ApiClientError } from "@/shared/api/http-client" import { parseSchedulerRunSnapshot, @@ -585,6 +586,9 @@ function DataCollectionContent() { const [certRenewIntervalDraft, setCertRenewIntervalDraft] = useState("21600") const [renewBeforeDaysDraft, setRenewBeforeDaysDraft] = useState("30") const [schedulerRuns, setSchedulerRuns] = useState([]) + const [runsKnown, setRunsKnown] = useState(false) + const [runsError, setRunsError] = useState(null) + const [runsReceivedAt, setRunsReceivedAt] = useState(null) const [runFilterJobKey, setRunFilterJobKey] = useState("") const [runNowJobKey, setRunNowJobKey] = useState(null) const [schedulerSaveBusy, setSchedulerSaveBusy] = useState(false) @@ -623,17 +627,14 @@ function DataCollectionContent() { setCollectorError(null) setPageBusy(true) try { - const runsQuery = - runFilterJobKey && SCHEDULER_JOB_KEYS.includes(runFilterJobKey as (typeof SCHEDULER_JOB_KEYS)[number]) - ? `?limit=80&jobKey=${encodeURIComponent(runFilterJobKey)}` - : "?limit=80" + const runsFilter = runFilterJobKey && SCHEDULER_JOB_KEYS.includes(runFilterJobKey as (typeof SCHEDULER_JOB_KEYS)[number]) ? runFilterJobKey as (typeof SCHEDULER_JOB_KEYS)[number] : undefined const [trafficRes, serversApiRes, uptimeRes, internetPathRes, certRenewRes, runsRes] = await Promise.allSettled([ apiFetch("/api/traffic/settings", { signal }), apiFetch("/api/servers-api-ping/settings", { signal }), apiFetch("/api/uptime/settings", { signal }), apiFetch("/api/internet-path/settings", { signal }), apiFetch<{ enabled: boolean; intervalSec: number; renewBeforeDays: number }>("/api/certificates/renew-settings", { signal }), - apiFetch<{ runs: SchedulerRunRowDto[] }>(`/api/scheduler/runs${runsQuery}`, { signal }), + listSchedulerRuns(backendUrl, { limit: 80, jobKey: runsFilter }, { signal }), ]) if (!current()) return @@ -699,14 +700,17 @@ function DataCollectionContent() { const runsPayload = readSettled(runsRes) if (runsPayload) { - setSchedulerRuns(runsPayload.runs ?? []) + setSchedulerRuns(runsPayload.runs) + setRunsKnown(true); setRunsError(null); setRunsReceivedAt(new Date().toISOString()) + } else if (runsRes.status === "rejected") { + setRunsError(extractApiError(runsRes.reason)) } } catch (e) { if (current()) setCollectorError(e instanceof Error ? e.message : "Не удалось загрузить данные") } finally { if (current()) setPageBusy(false) } - }, [apiFetch, isLive, runFilterJobKey]) + }, [apiFetch, backendUrl, isLive, runFilterJobKey]) const persistSchedulerDrafts = useCallback(async (overrides: SchedulerToggleOverrides = {}) => { const trafficEnabled = overrides.trafficEnabled ?? draftTrafficEnabled @@ -1041,8 +1045,8 @@ function DataCollectionContent() { }, { label: "Журнал (в списке)", - value: String(schedulerRuns.length), - sub: errorRunsInView ? `${errorRunsInView} с ошибкой` : "ошибок в показанных — нет", + value: runsKnown ? String(schedulerRuns.length) : "—", + sub: runsError ? (runsKnown ? "Показана последняя подтверждённая история" : "История не получена") : runsKnown ? (errorRunsInView ? `${errorRunsInView} с ошибкой` : "ошибок в показанных — нет") : "Ожидание истории", icon: , }, ] @@ -1260,7 +1264,7 @@ function DataCollectionContent() {