Gateway panel: link route addresses (open in new tab)

Each route address is a subdomain label now, so render it as a link to its full
https://<subdomain>.<domain> URL (via subdomainUrl), opening in a new tab. Falls
back to plain text on a bare host (off mode) where no subdomain URL exists.
This commit is contained in:
2026-06-30 21:08:23 -07:00
parent 478e3c57dd
commit f14ef3f40b

View File

@@ -1,8 +1,9 @@
import { useMemo, useState } from "react" import { useMemo, useState } from "react"
import { Link } from "react-router-dom" import { Link } from "react-router-dom"
import { Globe, RefreshCw, FileText } from "lucide-react" import { Globe, RefreshCw, FileText, ExternalLink } from "lucide-react"
import type { GatewayInfo, HealthStatus } from "@/types" import type { GatewayInfo, HealthStatus } from "@/types"
import { useGatewayReload, useCaddyfile } from "@/services/api/hooks" import { useGatewayReload, useCaddyfile } from "@/services/api/hooks"
import { subdomainUrl } from "@/lib/labels"
import { HealthBadge } from "./HealthBadge" import { HealthBadge } from "./HealthBadge"
interface GatewayPanelProps { interface GatewayPanelProps {
@@ -76,12 +77,28 @@ export function GatewayPanel({ gateway, statuses }: GatewayPanelProps) {
// Health applies to proxy/remote targets (a running service); // Health applies to proxy/remote targets (a running service);
// static targets are files on disk. // static targets are files on disk.
const health = route.kind !== "static" && route.name ? statusMap.get(route.name) : undefined const health = route.kind !== "static" && route.name ? statusMap.get(route.name) : undefined
// The address is a subdomain label — link to its full https URL.
const url = subdomainUrl(route.address)
return ( return (
<tr <tr
key={`${route.address}-${route.node}`} key={`${route.address}-${route.node}`}
className="border-b border-[var(--border)] last:border-b-0 hover:bg-black/20 transition-colors" className="border-b border-[var(--border)] last:border-b-0 hover:bg-black/20 transition-colors"
> >
<td className="px-4 py-2 font-mono text-[var(--primary)]">{route.address}</td> <td className="px-4 py-2 font-mono text-[var(--primary)]">
{url ? (
<a
href={url}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 hover:underline"
>
{route.address}
<ExternalLink size={11} className="opacity-60 shrink-0" />
</a>
) : (
route.address
)}
</td>
<td className="px-4 py-2"> <td className="px-4 py-2">
<KindBadge kind={route.kind} /> <KindBadge kind={route.kind} />
</td> </td>