diff --git a/application/src/components/ssl-domain/SSLCertificateActions.tsx b/application/src/components/ssl-domain/SSLCertificateActions.tsx index 9a86843..a1a2148 100644 --- a/application/src/components/ssl-domain/SSLCertificateActions.tsx +++ b/application/src/components/ssl-domain/SSLCertificateActions.tsx @@ -7,7 +7,7 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button"; -import { MoreHorizontal, RefreshCw, Edit, Trash2 } from "lucide-react"; +import { MoreHorizontal, RefreshCw, Edit, Trash2, Eye } from "lucide-react"; import { SSLCertificate } from "@/types/ssl.types"; import { triggerImmediateCheck } from "@/services/sslCertificateService"; import { toast } from "sonner"; @@ -15,12 +15,14 @@ import { useLanguage } from "@/contexts/LanguageContext"; interface SSLCertificateActionsProps { certificate: SSLCertificate; + onView: (certificate: SSLCertificate) => void; onEdit: (certificate: SSLCertificate) => void; onDelete: (certificate: SSLCertificate) => void; } export const SSLCertificateActions = ({ certificate, + onView, onEdit, onDelete }: SSLCertificateActionsProps) => { @@ -43,6 +45,10 @@ export const SSLCertificateActions = ({ + onView(certificate)}> + + {t('view')} + Check diff --git a/application/src/components/ssl-domain/SSLCertificateDetailDialog.tsx b/application/src/components/ssl-domain/SSLCertificateDetailDialog.tsx new file mode 100644 index 0000000..df23233 --- /dev/null +++ b/application/src/components/ssl-domain/SSLCertificateDetailDialog.tsx @@ -0,0 +1,219 @@ + +import React from "react"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Badge } from "@/components/ui/badge"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Separator } from "@/components/ui/separator"; +import { SSLCertificate } from "@/types/ssl.types"; +import { SSLStatusBadge } from "./SSLStatusBadge"; +import { useLanguage } from "@/contexts/LanguageContext"; + +interface SSLCertificateDetailDialogProps { + certificate: SSLCertificate | null; + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export const SSLCertificateDetailDialog = ({ + certificate, + open, + onOpenChange, +}: SSLCertificateDetailDialogProps) => { + const { t } = useLanguage(); + + if (!certificate) return null; + + return ( + + + + {t('sslCertificateDetails')} + + {t('viewDetailedInformation')} {certificate.domain} + + + +
+ {/* Domain & Status Overview */} + + + + {certificate.domain} + + + + +
+
+
+

{t('status')}

+ +
+
+

{t('daysLeft')}

+ + {certificate.days_left} {t('days')} + +
+
+
+
+

{t('validFrom')}

+

+ {certificate.valid_from ? new Date(certificate.valid_from).toLocaleString() : 'N/A'} +

+
+
+

{t('validUntil')}

+

+ {certificate.valid_till ? new Date(certificate.valid_till).toLocaleString() : 'N/A'} +

+
+
+
+
+

{t('validityPeriod')}

+

{certificate.validity_days || 0} {t('days')}

+
+ {certificate.resolved_ip && ( +
+

{t('resolvedIP')}

+

{certificate.resolved_ip}

+
+ )} +
+
+
+
+ + {/* Certificate Information */} + + + {t('certificateDetails')} + + +
+
+
+

{t('issuedTo')}

+

{certificate.issued_to || 'N/A'}

+
+
+

{t('issuer')}

+

{certificate.issuer_o || certificate.issuer_cn || 'N/A'}

+
+ {certificate.issuer_cn && certificate.issuer_cn !== certificate.issuer_o && ( +
+

Issuer Common Name

+

{certificate.issuer_cn}

+
+ )} +
+
+ {certificate.serial_number && ( +
+

{t('serialNumber')}

+

{certificate.serial_number}

+
+ )} + {certificate.cert_alg && ( +
+

{t('algorithm')}

+

{certificate.cert_alg}

+
+ )} +
+
+ + {certificate.cert_sans && ( +
+

{t('subjectAlternativeNames')}

+
+

{certificate.cert_sans}

+
+
+ )} +
+
+ + {/* Monitoring Configuration */} + + + {t('monitoringConfiguration')} + + +
+
+

{t('warningThreshold')}

+

{certificate.warning_threshold} {t('days')}

+
+
+

{t('expiryThreshold')}

+

{certificate.expiry_threshold} {t('days')}

+
+
+

Check Interval

+

{certificate.check_interval || 1} {t('days')}

+
+
+

{t('notificationChannel')}

+

{certificate.notification_channel || 'N/A'}

+
+
+ + {certificate.last_notified && ( +
+

{t('lastNotified')}

+

{new Date(certificate.last_notified).toLocaleString()}

+
+ )} +
+
+ + {/* System Information */} + + + {t('technicalInformation')} + + +
+
+ {certificate.check_at && ( +
+

Next Check

+

{new Date(certificate.check_at).toLocaleString()}

+
+ )} + {certificate.created && ( +
+

{t('created')}

+

{new Date(certificate.created).toLocaleString()}

+
+ )} +
+
+ {certificate.updated && ( +
+

{t('lastUpdated')}

+

{new Date(certificate.updated).toLocaleString()}

+
+ )} +
+

Certificate ID

+

{certificate.id}

+
+
+
+
+
+
+
+
+ ); +}; \ No newline at end of file diff --git a/application/src/components/ssl-domain/SSLCertificatesTable.tsx b/application/src/components/ssl-domain/SSLCertificatesTable.tsx index 64825d8..03177f7 100644 --- a/application/src/components/ssl-domain/SSLCertificatesTable.tsx +++ b/application/src/components/ssl-domain/SSLCertificatesTable.tsx @@ -1,4 +1,3 @@ - import React, { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { Plus } from "lucide-react"; @@ -33,6 +32,7 @@ import { SSLStatusBadge } from "./SSLStatusBadge"; import { AddSSLCertificateForm } from "./AddSSLCertificateForm"; import { EditSSLCertificateForm } from "./EditSSLCertificateForm"; import { SSLCertificateActions } from "./SSLCertificateActions"; +import { SSLCertificateDetailDialog } from "./SSLCertificateDetailDialog"; import { fetchSSLCertificates, addSSLCertificate, deleteSSLCertificate } from "@/services/sslCertificateService"; import { pb } from "@/lib/pocketbase"; import { SSLCertificate } from "@/types/ssl.types"; @@ -45,6 +45,7 @@ export const SSLCertificatesTable = () => { const [showAddDialog, setShowAddDialog] = useState(false); const [showEditDialog, setShowEditDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false); + const [showViewDialog, setShowViewDialog] = useState(false); const [selectedCertificate, setSelectedCertificate] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); @@ -111,6 +112,11 @@ export const SSLCertificatesTable = () => { } }; + const openViewDialog = (certificate: SSLCertificate) => { + setSelectedCertificate(certificate); + setShowViewDialog(true); + }; + const openEditDialog = (certificate: SSLCertificate) => { setSelectedCertificate(certificate); setShowEditDialog(true); @@ -168,6 +174,7 @@ export const SSLCertificatesTable = () => { @@ -185,6 +192,13 @@ export const SSLCertificatesTable = () => { + {/* View Certificate Dialog */} + + {/* Add Certificate Dialog */}