22 lines
2.2 KiB
Plaintext
22 lines
2.2 KiB
Plaintext
---
|
|
import Layout from "../layouts/Layout.astro";
|
|
import SourceBadge from "../components/SourceBadge.astro";
|
|
import DataLegend from "../components/DataLegend.astro";
|
|
import PageHero from "../components/PageHero.astro";
|
|
import StatePanel from "../components/StatePanel.astro";
|
|
import { ago, api, plural, sourceStatusLabel, type SourceStatus } from "../lib/api";
|
|
let sources: SourceStatus[] = [], unavailable = false;
|
|
try { sources = await api<SourceStatus[]>("/api/v1/source-status"); }
|
|
catch {
|
|
unavailable = true;
|
|
Astro.response.status = 503;
|
|
Astro.response.headers.set("Retry-After", "60");
|
|
Astro.response.headers.set("Cache-Control", "no-store");
|
|
}
|
|
---
|
|
<Layout title="Состояние источников — RF4 Spotter" description="Текущее безопасное состояние источников данных RF4 Spotter." noindex={unavailable} errorPage={unavailable}>
|
|
<PageHero eyebrow="Прозрачность данных" title="Статус источников" description="Пауза или изменение страницы не удаляют уже опубликованные данные." />
|
|
{unavailable ? <StatePanel tone="unavailable" title="Статус временно недоступен" description="Данные о состоянии источников не получены. Публичные наблюдения при этом не изменяются." /> : <section class="source-health-grid content-grid">{sources.map(source => <article data-status={source.status}><div><SourceBadge source={source.source_system}/><span class="health-state"><i></i>{sourceStatusLabel(source.status)}</span></div><h2>{source.name}</h2><strong>{source.observations} {plural(source.observations,["наблюдение","наблюдения","наблюдений"])}</strong><p>{source.status === "temporarily_limited" ? "Источник ограничен; опубликованные данные сохранены." : source.last_success_at ? `Последнее успешное обновление ${ago(source.last_success_at)}` : "Успешных запусков пока нет"}</p></article>)}</section>}
|
|
<DataLegend />
|
|
</Layout>
|