import { useId, useState } from "react" import { useParams } from "react-router-dom" import { AlertTriangle, Loader2, Play, RefreshCw, TriangleAlert } from "lucide-react" import { DiffView } from "@/components/DiffView" import { DomainHistory } from "@/components/DomainHistory" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { Label } from "@/components/ui/label" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { useApplyDomain, useCheckDomain, useCreateTemplateFromZone, useDomains, useZoneRecords, } from "@/hooks/useApi" import { cn } from "@/lib/utils" export function DomainDiffPage() { const { id = "" } = useParams() const domains = useDomains() const domain = domains.data?.find((d) => d.id === id) const hasTemplate = !!domain?.templateId const check = useCheckDomain(id, hasTemplate) const apply = useApplyDomain(id) // Пока список доменов не загружен, hasTemplate недостоверно (false по // умолчанию из-за domain === undefined) — не дёргаем provider-запрос // записей зоны, пока не будет точно известно, что шаблона нет. const zoneRecords = useZoneRecords(id, !domains.isPending && !hasTemplate) const createTemplateFromZone = useCreateTemplateFromZone() const [applyPrunes, setApplyPrunes] = useState(false) const pruneCheckboxId = useId() const changeset = check.data const hasPrunes = (changeset?.prunes.length ?? 0) > 0 const hasUpdates = (changeset?.updates.length ?? 0) > 0 const pruneWarning = applyPrunes && hasPrunes const recordList = zoneRecords.data ?? [] function onApply() { apply.mutate({ applyUpdates: true, applyPrunes }) } function onCreateTemplateFromZone() { createTemplateFromZone.mutate(id) } if (domains.isPending) { return (
Загрузка…
) } return (
domain / check

{id}

{hasTemplate && ( )}
{!hasTemplate && ( <>
Шаблон не привязан — дифф недоступен. Ниже текущие записи зоны.
Создать шаблон-эталон из текущего состояния зоны (без NS/SOA).
{createTemplateFromZone.isError && ( {createTemplateFromZone.error.message} )} {zoneRecords.isPending && (
Загружаю записи зоны…
)} {zoneRecords.isError && (
Не удалось получить записи зоны {zoneRecords.error.message}
)} {recordList.length > 0 && ( Тип Имя TTL Значение {recordList.map((r, i) => ( {r.type} {r.name} {r.ttl} {r.values.join("\n")} ))}
)} )} {hasTemplate && check.isPending && (
Вычисляю дифф…
)} {hasTemplate && check.isError && (
Не удалось получить дифф {check.error.message}
)} {hasTemplate && changeset && ( <>
{pruneWarning && (
Будет безвозвратно удалено записей:{" "} {changeset.prunes.length}. Действие необратимо.
)}
{apply.isError ? ( {apply.error.message} ) : apply.isSuccess ? ( Применено ✓ ) : ( {hasUpdates || (applyPrunes && hasPrunes) ? "Готово к применению" : "Изменений для применения нет"} )}
)}
) }