mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-14 02:46:37 +08:00
prettier
This commit is contained in:
@@ -1,18 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import {useMemo} from 'react';
|
||||
import {ExternalLink, FileKey} from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
import { ExternalLink, FileKey } from 'lucide-react';
|
||||
|
||||
import {EmptyStateWithBorder} from '@/components/layout/empty';
|
||||
import {Badge} from '@/components/ui/badge';
|
||||
import {Button} from '@/components/ui/button';
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from '@/components/ui/card';
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from '@/components/ui/table';
|
||||
import type {TlsCertificateItem, ZoneDomainItem} from '@/lib/services/openflare';
|
||||
import {formatDateTime} from '@/lib/utils';
|
||||
import { EmptyStateWithBorder } from '@/components/layout/empty';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import type {
|
||||
TlsCertificateItem,
|
||||
ZoneDomainItem,
|
||||
} from '@/lib/services/openflare';
|
||||
import { formatDateTime } from '@/lib/utils';
|
||||
|
||||
import {getCertificateStatus} from '../../components/website-utils';
|
||||
import { getCertificateStatus } from '../../components/website-utils';
|
||||
|
||||
export function ZoneCertificatesPanel({
|
||||
domains,
|
||||
@@ -22,14 +38,15 @@ export function ZoneCertificatesPanel({
|
||||
certificates: TlsCertificateItem[];
|
||||
}) {
|
||||
const certificateMap = useMemo(
|
||||
() => new Map(certificates.map((certificate) => [certificate.id, certificate])),
|
||||
() =>
|
||||
new Map(certificates.map((certificate) => [certificate.id, certificate])),
|
||||
[certificates],
|
||||
);
|
||||
|
||||
const boundCertificates = useMemo(() => {
|
||||
const rows = new Map<
|
||||
number,
|
||||
{certificate: TlsCertificateItem; domains: ZoneDomainItem[]}
|
||||
{ certificate: TlsCertificateItem; domains: ZoneDomainItem[] }
|
||||
>();
|
||||
|
||||
for (const domain of domains) {
|
||||
@@ -44,7 +61,7 @@ export function ZoneCertificatesPanel({
|
||||
if (existing) {
|
||||
existing.domains.push(domain);
|
||||
} else {
|
||||
rows.set(certificate.id, {certificate, domains: [domain]});
|
||||
rows.set(certificate.id, { certificate, domains: [domain] });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,28 +70,30 @@ export function ZoneCertificatesPanel({
|
||||
);
|
||||
}, [certificateMap, domains]);
|
||||
|
||||
const unboundCount = domains.filter((domain) => domain.cert_id == null).length;
|
||||
const unboundCount = domains.filter(
|
||||
(domain) => domain.cert_id == null,
|
||||
).length;
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Card className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-start justify-between gap-3 space-y-0">
|
||||
<div className='space-y-4'>
|
||||
<Card className='shadow-none'>
|
||||
<CardHeader className='flex flex-row items-start justify-between gap-3 space-y-0'>
|
||||
<div>
|
||||
<CardTitle className="text-base">本 Zone 使用的证书</CardTitle>
|
||||
<CardTitle className='text-base'>本 Zone 使用的证书</CardTitle>
|
||||
<CardDescription>
|
||||
证书在全局证书库管理;此处仅展示已绑定到本 Zone 域名的证书。
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" className="h-7 text-xs" asChild>
|
||||
<Link href="/certificates">
|
||||
<Button variant='outline' size='sm' className='h-7 text-xs' asChild>
|
||||
<Link href='/certificates'>
|
||||
证书库
|
||||
<ExternalLink className="ml-1 size-3.5" />
|
||||
<ExternalLink className='ml-1 size-3.5' />
|
||||
</Link>
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<CardContent className='space-y-3'>
|
||||
{unboundCount > 0 ? (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className='text-xs text-muted-foreground'>
|
||||
还有 {unboundCount} 个域名未绑定证书,可在「域名」Tab 中选择证书。
|
||||
</p>
|
||||
) : null}
|
||||
@@ -82,10 +101,10 @@ export function ZoneCertificatesPanel({
|
||||
{boundCertificates.length === 0 ? (
|
||||
<EmptyStateWithBorder
|
||||
icon={FileKey}
|
||||
description="暂无绑定证书。请先在域名行选择证书,或前往证书库导入/申请。"
|
||||
description='暂无绑定证书。请先在域名行选择证书,或前往证书库导入/申请。'
|
||||
/>
|
||||
) : (
|
||||
<div className="rounded-lg border">
|
||||
<div className='rounded-lg border'>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@@ -96,30 +115,35 @@ export function ZoneCertificatesPanel({
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{boundCertificates.map(({certificate, domains: boundDomains}) => {
|
||||
const status = getCertificateStatus(certificate);
|
||||
return (
|
||||
<TableRow key={certificate.id}>
|
||||
<TableCell className="font-medium">
|
||||
{certificate.name}
|
||||
<p className="mt-0.5 text-xs text-muted-foreground">
|
||||
{certificate.primary_domain || `证书 #${certificate.id}`}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline" className="text-[10px]">
|
||||
{status.label}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="max-w-xs truncate text-muted-foreground">
|
||||
{boundDomains.map((domain) => domain.domain).join(' · ')}
|
||||
</TableCell>
|
||||
<TableCell className="text-muted-foreground">
|
||||
{formatDateTime(certificate.not_after)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
{boundCertificates.map(
|
||||
({ certificate, domains: boundDomains }) => {
|
||||
const status = getCertificateStatus(certificate);
|
||||
return (
|
||||
<TableRow key={certificate.id}>
|
||||
<TableCell className='font-medium'>
|
||||
{certificate.name}
|
||||
<p className='mt-0.5 text-xs text-muted-foreground'>
|
||||
{certificate.primary_domain ||
|
||||
`证书 #${certificate.id}`}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant='outline' className='text-[10px]'>
|
||||
{status.label}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className='max-w-xs truncate text-muted-foreground'>
|
||||
{boundDomains
|
||||
.map((domain) => domain.domain)
|
||||
.join(' · ')}
|
||||
</TableCell>
|
||||
<TableCell className='text-muted-foreground'>
|
||||
{formatDateTime(certificate.not_after)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user