From fa65ae3d1c555cfb9a8a7a3fce2259e7f3d12638 Mon Sep 17 00:00:00 2001 From: Paul Payne Date: Wed, 1 Jul 2026 08:35:37 -0700 Subject: [PATCH] Dashboard: public routes link to their public URL; drop editable behavior field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Gateway route table: a public route's address now links to its public URL (green, with the tunnel icon) instead of the internal one. - Program detail: remove the editable `behavior` selector — behavior is a derived label now and drives no logic, so editing it was meaningless (the stored value is preserved on save via the manifest spread). --- app/src/components/GatewayPanel.tsx | 47 ++++++++++----------- app/src/components/detail/ProgramFields.tsx | 13 ------ 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/app/src/components/GatewayPanel.tsx b/app/src/components/GatewayPanel.tsx index ed2087d..82c8426 100644 --- a/app/src/components/GatewayPanel.tsx +++ b/app/src/components/GatewayPanel.tsx @@ -89,30 +89,29 @@ export function GatewayPanel({ gateway, statuses }: GatewayPanelProps) { className="border-b border-[var(--border)] last:border-b-0 hover:bg-black/20 transition-colors" > - {url ? ( - - {route.address} - - - ) : ( - route.address - )} - {route.public_url && ( - - public - - )} + {(() => { + // A public route links to its public URL; otherwise the + // internal subdomain URL. + const primaryUrl = route.public_url || url + const isPublic = !!route.public_url + return primaryUrl ? ( + + {isPublic && } + {route.address} + + + ) : ( + route.address + ) + })()} diff --git a/app/src/components/detail/ProgramFields.tsx b/app/src/components/detail/ProgramFields.tsx index de94a32..d42aa3a 100644 --- a/app/src/components/detail/ProgramFields.tsx +++ b/app/src/components/detail/ProgramFields.tsx @@ -28,7 +28,6 @@ export function ProgramFields({ program, onSave, onDelete }: Props) { const [description, setDescription] = useState((m.description as string) ?? "") const [source, setSource] = useState((m.source as string) ?? "") - const [behavior, setBehavior] = useState((m.behavior as string) ?? "") const [stack, setStack] = useState((m.stack as string) ?? "") const [version, setVersion] = useState((m.version as string) ?? "") const [repo, setRepo] = useState((m.repo as string) ?? "") @@ -56,7 +55,6 @@ export function ProgramFields({ program, onSave, onDelete }: Props) { delete config.id config.description = description || undefined config.source = source || undefined - config.behavior = behavior || undefined config.stack = stack || undefined config.version = version || undefined config.repo = repo || undefined @@ -99,17 +97,6 @@ export function ProgramFields({ program, onSave, onDelete }: Props) { placeholder="/data/repos/my-prog" hint="The working copy on disk. Castle runs dev verbs and builds here. Absolute path, or repo: for castle's own programs." /> - - -