visual improvements

This commit is contained in:
miloschwartz
2026-04-29 13:44:35 -07:00
parent d3870f4920
commit e173f59d89
3 changed files with 27 additions and 143 deletions

View File

@@ -453,6 +453,13 @@ export default function ClientResourcesTable({
return (
<div className="flex items-center gap-2 min-w-0">
<div className="">
<CopyToClipboard
text={url}
isLink={isSafeUrlForLink(url)}
displayText={url}
/>
</div>
{did ? (
<PrivateResourceCertAccessIndicator
orgId={resourceRow.orgId}
@@ -460,13 +467,6 @@ export default function ClientResourcesTable({
fullDomain={fullDomain}
/>
) : null}
<div className="min-w-0 flex-1">
<CopyToClipboard
text={url}
isLink={isSafeUrlForLink(url)}
displayText={url}
/>
</div>
</div>
);
}

View File

@@ -1,6 +1,6 @@
"use client";
import { Button } from "@app/components/ui/button";
import CertificateStatus from "@app/components/CertificateStatus";
import {
Popover,
PopoverAnchor,
@@ -8,12 +8,7 @@ import {
} from "@app/components/ui/popover";
import { useCertificate } from "@app/hooks/useCertificate";
import { cn } from "@app/lib/cn";
import {
CheckCircle2,
Clock,
RotateCw,
XCircle
} from "lucide-react";
import { CheckCircle2, Clock, XCircle } from "lucide-react";
import { useTranslations } from "next-intl";
import { useCallback, useEffect, useRef, useState } from "react";
@@ -53,16 +48,6 @@ function getStatusIcon(status: string) {
}
}
function shouldShowRefreshButton(status: string, updatedAt: number) {
return (
status === "failed" ||
status === "expired" ||
(status === "requested" &&
updatedAt &&
new Date(updatedAt * 1000).getTime() < Date.now() - 5 * 60 * 1000)
);
}
export function PrivateResourceCertAccessIndicator({
orgId,
domainId,
@@ -72,13 +57,12 @@ export function PrivateResourceCertAccessIndicator({
const [open, setOpen] = useState(false);
const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const { cert, certLoading, certError, refreshing, refreshCert } =
useCertificate({
orgId,
domainId,
fullDomain,
autoFetch: true
});
const { cert, certLoading, certError } = useCertificate({
orgId,
domainId,
fullDomain,
autoFetch: true
});
const clearCloseTimer = useCallback(() => {
if (closeTimerRef.current != null) {
@@ -101,10 +85,6 @@ export function PrivateResourceCertAccessIndicator({
return () => clearCloseTimer();
}, [clearCloseTimer]);
const handleRefresh = async () => {
await refreshCert();
};
if (certLoading) {
return (
<div
@@ -115,9 +95,6 @@ export function PrivateResourceCertAccessIndicator({
);
}
const isPending = cert?.status === "pending";
const disableWildcard = cert?.domainType === "wildcard";
let TriggerIcon = Clock;
let triggerIconClass = "text-muted-foreground";
if (certError) {
@@ -155,7 +132,7 @@ export function PrivateResourceCertAccessIndicator({
</button>
</PopoverAnchor>
<PopoverContent
className="w-72 space-y-3 p-4"
className="w-72 p-4"
align="start"
side="bottom"
sideOffset={6}
@@ -163,106 +140,13 @@ export function PrivateResourceCertAccessIndicator({
onMouseLeave={scheduleClose}
onOpenAutoFocus={(e) => e.preventDefault()}
>
<div className="space-y-2">
<div className="text-sm font-medium text-muted-foreground">
{t("certificateStatus")}
</div>
{certError ? (
<span className="inline-flex items-center gap-1.5 text-sm">
<XCircle className="h-4 w-4 shrink-0 text-red-500" />
{certError}
</span>
) : !cert ? (
<span className="inline-flex items-center gap-1.5 text-sm">
<Clock className="h-4 w-4 shrink-0 text-muted-foreground" />
{t("none", { defaultValue: "None" })}
</span>
) : (
<>
{isPending && !disableWildcard ? (
<Button
variant="ghost"
className="h-auto p-0 text-sm font-normal"
onClick={handleRefresh}
disabled={refreshing}
title={t("restartCertificate", {
defaultValue: "Restart Certificate"
})}
>
<span className="inline-flex items-center gap-2">
{(() => {
const StatusIcon = getStatusIcon(
cert.status
);
return (
<StatusIcon
className={`h-4 w-4 shrink-0 ${getStatusColor(cert.status)}`}
/>
);
})()}
{cert.status.charAt(0).toUpperCase() +
cert.status.slice(1)}
<RotateCw
className={`h-3 w-3 ${refreshing ? "animate-spin" : ""}`}
/>
</span>
</Button>
) : (
<span className="text-sm">
<span className="inline-flex items-center gap-2">
{(() => {
const StatusIcon = getStatusIcon(
cert.status
);
return (
<StatusIcon
className={`h-4 w-4 shrink-0 ${getStatusColor(cert.status)}`}
/>
);
})()}
{cert.status.charAt(0).toUpperCase() +
cert.status.slice(1)}
{shouldShowRefreshButton(
cert.status,
cert.updatedAt
) && !disableWildcard ? (
<Button
size="icon"
variant="ghost"
className="p-0 w-3 h-auto align-middle"
onClick={handleRefresh}
disabled={refreshing}
title={t("restartCertificate", {
defaultValue:
"Restart Certificate"
})}
>
<RotateCw
className={`w-3 h-3 ${refreshing ? "animate-spin" : ""}`}
/>
</Button>
) : null}
</span>
</span>
)}
{cert.errorMessage &&
(cert.status === "failed" ||
cert.status === "expired") ? (
<p className="text-xs text-muted-foreground break-all">
{cert.errorMessage}
</p>
) : null}
{cert.expiresAt && cert.status === "valid" ? (
<p className="text-xs text-muted-foreground">
{t("expiresAt")}:{" "}
{new Date(
cert.expiresAt
).toLocaleDateString()}
</p>
) : null}
</>
)}
</div>
<CertificateStatus
orgId={orgId}
domainId={domainId}
fullDomain={fullDomain}
autoFetch
showLabel
/>
</PopoverContent>
</Popover>
);

View File

@@ -52,7 +52,7 @@ function aggregateStatusDotClass(status: AggregateSitesStatus): string {
return "bg-neutral-500";
case "unknown":
default:
return "bg-transparent";
return "border border-muted-foreground/50 bg-transparent";
}
}
@@ -107,10 +107,10 @@ export function ResourceSitesStatusCell({
className={cn(
"h-2 w-2 shrink-0 rounded-full",
!hasKnownStatus
? "bg-transparent"
? "border border-muted-foreground/50 bg-transparent"
: isOnline
? "bg-green-500"
: "bg-neutral-500"
? "bg-green-500"
: "bg-neutral-500"
)}
/>
<span className="truncate">