fix(ui): проверить доступность и адаптивность сертификатов
This commit is contained in:
1 parent
f5a71728ac
commit
16fa6eb5d8
17 files changed
+101
-37
No files matched your search
@@ -4,13 +4,13 @@ import type { CertificateView } from "@/lib/certificate-view"
|
||||
|
||||
function CertificateExpandedDetail({ cert }: { cert: CertificateView }) {
|
||||
return (
|
||||
<div className="px-10 pb-4 grid grid-cols-2 sm:grid-cols-4 gap-4 text-xs border-t border-border/50 pt-3">
|
||||
<div className="min-w-0 [overflow-wrap:anywhere] px-5 sm:px-10 pb-4 grid grid-cols-2 sm:grid-cols-4 gap-4 text-xs border-t border-border/50 pt-3">
|
||||
<div>
|
||||
<p className="text-muted-foreground mb-1">Размер ключа</p>
|
||||
<p className="font-mono font-medium">{cert.keySize === null ? "Неизвестен" : cert.keySize + " бит"}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground mb-1">Действителен с</p>
|
||||
<p className="text-muted-foreground mb-1">Начало срока</p>
|
||||
<p className="font-mono">{cert.validFrom ?? "Дата неизвестна"}</p>
|
||||
</div>
|
||||
<div>
|
||||
@@ -31,6 +31,8 @@ function CertificateExpandedDetail({ cert }: { cert: CertificateView }) {
|
||||
{cert.trusted === null ? "Неизвестно" : cert.trusted ? "Да (доверенный)" : "Нет (не доверенный)"}
|
||||
</p>
|
||||
</div>
|
||||
{"rawValidFrom" in cert && !cert.validFrom && cert.rawValidFrom && <p className="col-span-2 sm:col-span-4 text-muted-foreground">Начало срока не удалось определить. Значение RouterOS: <span className="font-mono">{cert.rawValidFrom}</span></p>}
|
||||
{"rawValidUntil" in cert && !cert.validUntil && cert.rawValidUntil && <p className="col-span-2 sm:col-span-4 text-muted-foreground">Окончание срока не удалось определить. Значение RouterOS: <span className="font-mono">{cert.rawValidUntil}</span></p>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -38,3 +38,10 @@ test("expired and positive observed days stay distinct", () => {
|
||||
assert.match(renderToStaticMarkup(<CertDaysCell cert={{ ...cert, daysLeft: -3 }} />), /Истёк 3д назад/)
|
||||
assert.match(renderToStaticMarkup(<CertDaysCell cert={{ ...cert, daysLeft: 40 }} />), /40д осталось/)
|
||||
})
|
||||
|
||||
test("unparsed RouterOS dates remain explicit raw values without claiming valid dates", () => {
|
||||
const details = renderToStaticMarkup(<CertificateExpandedDetail cert={{ ...cert, rawValidFrom: "oct/01/2026 12:00:00", rawValidUntil: "oct/01/2027 12:00:00" }} />)
|
||||
assert.match(details, /Начало срока не удалось определить/)
|
||||
assert.match(details, /Окончание срока не удалось определить/)
|
||||
assert.ok(details.includes("oct/01/2026 12:00:00"))
|
||||
})
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import type { Server } from "@/lib/data"
|
||||
import type { CertificateView } from "@/lib/certificate-view"
|
||||
import { CertDaysCell } from "@/components/data-grids/certificate-days-cell"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Flag } from "@/components/flag"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { DataGridShell } from "@/components/data-grids/shared/data-grid-shell"
|
||||
@@ -40,27 +41,27 @@ const STATUS_CONFIG: Record<
|
||||
> = {
|
||||
unknown: {
|
||||
label: "Неизвестен",
|
||||
icon: <CircleHelpIcon className="size-4 text-muted-foreground" />,
|
||||
icon: <CircleHelpIcon aria-hidden="true" className="size-4 text-muted-foreground" />,
|
||||
badge: "bg-muted text-muted-foreground border-border",
|
||||
row: "",
|
||||
},
|
||||
valid: {
|
||||
label: "Действителен",
|
||||
icon: <BadgeCheckIcon className="size-4 text-emerald-500" />,
|
||||
badge: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20",
|
||||
icon: <BadgeCheckIcon aria-hidden="true" className="size-4 text-success" />,
|
||||
badge: "bg-success/10 text-success border-success/20",
|
||||
row: "",
|
||||
},
|
||||
expired: {
|
||||
label: "Истёк",
|
||||
icon: <ShieldOffIcon className="size-4 text-red-500" />,
|
||||
badge: "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20",
|
||||
row: "bg-red-500/5",
|
||||
icon: <ShieldOffIcon aria-hidden="true" className="size-4 text-destructive" />,
|
||||
badge: "bg-destructive/10 text-destructive border-destructive/20",
|
||||
row: "bg-destructive/5",
|
||||
},
|
||||
revoked: {
|
||||
label: "Отозван",
|
||||
icon: <ShieldAlertIcon className="size-4 text-amber-500" />,
|
||||
badge: "bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20",
|
||||
row: "bg-amber-500/5",
|
||||
icon: <ShieldAlertIcon aria-hidden="true" className="size-4 text-warning" />,
|
||||
badge: "bg-warning/10 text-warning border-warning/20",
|
||||
row: "bg-warning/5",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -87,11 +88,13 @@ function CertificatesDataGrid({ certificates, serverMap, isLoading, emptyTitle =
|
||||
const expanded = row.getIsExpanded()
|
||||
return (
|
||||
<div className="flex items-start gap-2 min-w-0">
|
||||
<Button type="button" variant="ghost" size="icon" className="size-11 sm:size-8 shrink-0" aria-label={"Детали сертификата " + cert.name} aria-expanded={expanded} onClick={event => { event.stopPropagation(); row.toggleExpanded() }}>
|
||||
{expanded ? (
|
||||
<ChevronDownIcon className="size-3.5 mt-0.5 shrink-0 text-muted-foreground" />
|
||||
<ChevronDownIcon aria-hidden="true" className="size-3.5 mt-0.5 shrink-0 text-muted-foreground" />
|
||||
) : (
|
||||
<ChevronRightIcon className="size-3.5 mt-0.5 shrink-0 text-muted-foreground/40" />
|
||||
<ChevronRightIcon aria-hidden="true" className="size-3.5 mt-0.5 shrink-0 text-muted-foreground/40" />
|
||||
)}
|
||||
</Button>
|
||||
<div className="min-w-0">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<span className="shrink-0">{cfg.icon}</span>
|
||||
|
||||
Reference in new issue
Block a user