app: cross-link entity pages along graph edges

- service/static/tool/job detail pages now link back to their program;
  backfill the program ref on registry-only static+job details (the
  registry Deployment carries no program ref).
- new RelatedDeployments card surfaces a deployment's requires edges both
  directions (Depends on / Required by) as links; references render inert.
- replace the service detail Subdomain/Served-at rows with a launch icon
  in the header that opens the gateway URL in a new tab.
This commit is contained in:
2026-07-07 13:27:46 -07:00
parent 5beebfd739
commit ea59d846bc
5 changed files with 179 additions and 46 deletions

View File

@@ -1,11 +1,12 @@
import { useParams } from "react-router-dom"
import { Clock } from "lucide-react"
import { useParams, Link } from "react-router-dom"
import { Clock, Package } from "lucide-react"
import { useJob } from "@/services/api/hooks"
import { LogViewer } from "@/components/LogViewer"
import { DetailHeader } from "@/components/detail/DetailHeader"
import { ServiceControls } from "@/components/detail/ServiceControls"
import { SystemdPanel } from "@/components/detail/SystemdPanel"
import { ConfigPanel } from "@/components/detail/ConfigPanel"
import { RelatedDeployments } from "@/components/detail/RelatedDeployments"
export function ScheduledDetailPage() {
const { name } = useParams<{ name: string }>()
@@ -39,20 +40,32 @@ export function ScheduledDetailPage() {
<ServiceControls name={deployment.id} enabled={deployment.enabled} />
</DetailHeader>
{deployment.schedule && (
<div className="bg-[var(--card)] border border-[var(--border)] rounded-lg p-5 mb-6">
<h2 className="text-sm font-semibold text-[var(--muted)] uppercase tracking-wider mb-3">
Schedule
</h2>
<div className="grid grid-cols-2 gap-x-6 gap-y-2 text-sm">
<span className="text-[var(--muted)]">Cron</span>
<span className="flex items-center gap-2 min-w-0 break-all font-mono">
<Clock size={14} className="shrink-0 text-[var(--muted)]" />
{deployment.schedule}
</span>
</div>
<div className="bg-[var(--card)] border border-[var(--border)] rounded-lg p-5 mb-6">
<div className="grid grid-cols-2 gap-x-6 gap-y-2 text-sm">
{deployment.schedule && (
<>
<span className="text-[var(--muted)]">Cron</span>
<span className="flex items-center gap-2 min-w-0 break-all font-mono">
<Clock size={14} className="shrink-0 text-[var(--muted)]" />
{deployment.schedule}
</span>
</>
)}
{deployment.program && (
<>
<span className="text-[var(--muted)]">Program</span>
<Link
to={`/programs/${deployment.program}`}
className="flex items-center gap-1.5 min-w-0 text-[var(--primary)] hover:underline"
>
<Package size={14} className="shrink-0" /> {deployment.program}
</Link>
</>
)}
</div>
)}
</div>
<RelatedDeployments name={deployment.id} />
<ConfigPanel deployment={deployment} configSection="jobs" onRefetch={refetch} />