DnsRecordCard.tsx 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { CopyOutlined, ReloadOutlined } from '@ant-design/icons';
  2. import { Alert, Button, Card, Space, Tooltip, Typography } from 'antd';
  3. import { useI18n } from '../../frontend/i18n/react';
  4. import type { DnsRecord } from '../../frontend/types';
  5. import { StatusTag } from '../common/StatusTag';
  6. interface DnsRecordCardProps {
  7. record: DnsRecord;
  8. loading?: boolean;
  9. onCopy: (value: string) => void;
  10. onRecheck: () => void;
  11. }
  12. export function DnsRecordCard({ record, loading, onCopy, onRecheck }: DnsRecordCardProps) {
  13. const { t } = useI18n();
  14. const currentValues = Array.isArray(record.current)
  15. ? record.current
  16. : record.current
  17. ? [record.current]
  18. : [];
  19. return (
  20. <Card
  21. className="dns-record-card"
  22. title={
  23. <Space wrap>
  24. <span>{record.label}</span>
  25. <StatusTag record={record} />
  26. </Space>
  27. }
  28. extra={<Typography.Text code>{record.type}</Typography.Text>}
  29. >
  30. <Space direction="vertical" size={14} className="full-width">
  31. <DnsValueRow label={t('dnsRecord.hostname')} value={record.host} onCopy={onCopy} />
  32. <DnsValueRow label={t('dnsRecord.targetValue')} value={record.value || '-'} onCopy={onCopy} />
  33. <div>
  34. <Typography.Text type="secondary">{t('dnsRecord.currentValue')}</Typography.Text>
  35. {currentValues.length ? (
  36. <Space direction="vertical" size={8} className="full-width value-stack">
  37. {currentValues.map((value) => (
  38. <Typography.Paragraph key={value} code copyable className="dns-code-block">
  39. {value}
  40. </Typography.Paragraph>
  41. ))}
  42. </Space>
  43. ) : (
  44. <Typography.Paragraph type="secondary" className="dns-empty-value">
  45. {t('dnsRecord.emptyCurrent')}
  46. </Typography.Paragraph>
  47. )}
  48. </div>
  49. {record.key === 'ptr' ? (
  50. <Alert
  51. type="info"
  52. showIcon
  53. message={t('dnsRecord.ptrHint')}
  54. />
  55. ) : null}
  56. {(record.warnings || []).map((warning) => (
  57. <Alert key={warning} type="warning" showIcon message={warning} />
  58. ))}
  59. <Button icon={<ReloadOutlined />} loading={loading} onClick={onRecheck}>
  60. {t('dnsRecord.recheck')}
  61. </Button>
  62. </Space>
  63. </Card>
  64. );
  65. }
  66. function DnsValueRow({
  67. label,
  68. value,
  69. onCopy
  70. }: {
  71. label: string;
  72. value: string;
  73. onCopy: (value: string) => void;
  74. }) {
  75. const { t } = useI18n();
  76. return (
  77. <div className="dns-value-row">
  78. <Typography.Text type="secondary">{label}</Typography.Text>
  79. <Typography.Paragraph code copyable className="dns-code-block">
  80. {value}
  81. </Typography.Paragraph>
  82. <Tooltip title={`${t('dnsRecord.copyLabel')}${label}`}>
  83. <Button icon={<CopyOutlined />} onClick={() => onCopy(value)} aria-label={`${t('dnsRecord.copyLabel')}${label}`} />
  84. </Tooltip>
  85. </div>
  86. );
  87. }