web: add checks status summary badge to zone viewer PageHeader

Add a ChecksSummaryBadge component that fetches domain-level checker statuses
and displays the worst status as a colored badge linking to the checks page.
This commit is contained in:
nemunaire 2026-04-16 11:18:06 +07:00
commit 33ef6b60e7
2 changed files with 57 additions and 3 deletions

View file

@ -0,0 +1,51 @@
<!--
This file is part of the happyDomain (R) project.
Copyright (c) 2022-2026 happyDomain
Authors: Pierre-Olivier Mercier, et al.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at <contact@happydomain.org>.
For AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script lang="ts">
import { Badge, Icon } from "@sveltestrap/sveltestrap";
import type { HappydnsStatus } from "$lib/api-base/types.gen";
import { getStatusColor, getStatusIcon, getStatusI18nKey } from "$lib/utils";
import { t } from "$lib/translations";
interface Props {
status: HappydnsStatus | undefined;
checksBase: string;
}
let { status, checksBase }: Props = $props();
</script>
{#if status !== undefined}
<a
href={checksBase}
class="text-decoration-none"
title={$t("domains.actions.checks")}
aria-label={$t("domains.actions.checks")}
>
<Badge color={getStatusColor(status)}>
<Icon name={getStatusIcon(status)} class="me-1" />
{$t(getStatusI18nKey(status))}
</Badge>
</a>
{/if}

View file

@ -25,18 +25,19 @@
import { Button, Col, Icon, Row, Spinner } from "@sveltestrap/sveltestrap";
import AliasModal from "$lib/components/modals/Alias.svelte";
import ChecksSummaryBadge from "$lib/components/checkers/ChecksSummaryBadge.svelte";
import PageTitle from "$lib/components/PageTitle.svelte";
import SubdomainItem from "./SubdomainItem.svelte";
import SubdomainList from "./SubdomainList.svelte";
import UserResource from "./UserResource.svelte";
import type { Domain } from "$lib/model/domain";
import type { HappydnsDomainWithCheckStatus } from "$lib/api-base/types.gen";
import type { Zone } from "$lib/model/zone";
import { domains_idx } from "$lib/stores/domains";
import { domainLink, domains_idx } from "$lib/stores/domains";
import { sortedDomains, sortedDomainsWithIntermediate, thisZone } from "$lib/stores/thiszone";
import { t } from "$lib/translations";
interface Props {
data: { domain: Domain; history: string; zoneId: string };
data: { domain: HappydnsDomainWithCheckStatus; history: string; zoneId: string };
}
let { data }: Props = $props();
@ -47,6 +48,7 @@
!!data.history &&
data.history !== data.domain.zone_history[0]
);
let checksBase = $derived(`/domains/${encodeURIComponent(domainLink(data.domain.id))}/checks`);
</script>
{#if !data.domain}
@ -67,6 +69,7 @@
{:else}
<div style="max-width: 100%;" class="w-100 pt-1 mb-5">
<PageTitle title={$t("zones.viewer")} subtitle={$t("zones.viewer-subtitle")} domain={data.domain.domain}>
<ChecksSummaryBadge status={data.domain.last_check_status} {checksBase} />
{#if isHistorical}
<span class="badge bg-warning text-dark">
<Icon name="clock-history" />