Dashboard: public routes link to their public URL; drop editable behavior field
- 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).
This commit is contained in:
@@ -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"
|
||||
>
|
||||
<td className="px-4 py-2 font-mono text-[var(--primary)]">
|
||||
{url ? (
|
||||
{(() => {
|
||||
// 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 ? (
|
||||
<a
|
||||
href={url}
|
||||
href={primaryUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 hover:underline"
|
||||
title={primaryUrl}
|
||||
className={`inline-flex items-center gap-1 hover:underline ${
|
||||
isPublic ? "text-green-500" : ""
|
||||
}`}
|
||||
>
|
||||
{isPublic && <Cable size={11} className="shrink-0" />}
|
||||
{route.address}
|
||||
<ExternalLink size={11} className="opacity-60 shrink-0" />
|
||||
</a>
|
||||
) : (
|
||||
route.address
|
||||
)}
|
||||
{route.public_url && (
|
||||
<a
|
||||
href={route.public_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={route.public_url}
|
||||
className="ml-2 inline-flex items-center gap-1 text-[0.65rem] px-1.5 py-0.5 rounded bg-green-500/15 text-green-500 hover:bg-green-500/25"
|
||||
>
|
||||
<Cable size={10} /> public
|
||||
</a>
|
||||
)}
|
||||
)
|
||||
})()}
|
||||
</td>
|
||||
<td className="px-4 py-2">
|
||||
<KindBadge kind={route.kind} />
|
||||
|
||||
@@ -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:<name> for castle's own programs."
|
||||
/>
|
||||
<Field
|
||||
label="Behavior"
|
||||
hint="What this program is. tool = a CLI you invoke; daemon = a long-running server; frontend = a web UI. Drives how it activates and deploys."
|
||||
>
|
||||
<select value={behavior} onChange={(e) => setBehavior(e.target.value)} className={`w-48 ${SELECT}`}>
|
||||
<option value="">(none)</option>
|
||||
<option value="tool">tool</option>
|
||||
<option value="daemon">daemon</option>
|
||||
<option value="frontend">frontend</option>
|
||||
</select>
|
||||
</Field>
|
||||
<Field
|
||||
label="Stack"
|
||||
hint="Optional toolchain template — seeds default dev-verb commands and a scaffold for new code. Leave empty and declare commands below to wire in any repo."
|
||||
|
||||
Reference in New Issue
Block a user