Stage 2: App — split the one editor into typed program/service/job forms

The single service-shaped DeploymentFields was reused for all three sections,
so the program page bled service fields (port/proxy/health) and couldn't edit
program config, and the job page couldn't edit its schedule. Replaced it with:

- ProgramFields  — description, source, stack, behavior, version, repo/ref,
  system deps (+ read-only commands). Edits the program catalog entry.
- ServiceFields  — run target, port, port_env, health, proxy path + host,
  env/secrets. Prefills correctly now (Stage 1) and round-trips through PUT.
- JobFields      — schedule, run target, env/secrets.

ConfigPanel selects the form by section. Shared Field/TextField/useEnvSecrets/
FormFooter helpers in detail/fields.tsx. Retired DeploymentFields. run editing
only touches python/command specs (container/node/remote run blocks preserved).

Verified: GET service manifest → PUT back validates 200. App type-checks/builds.
This commit is contained in:
2026-06-14 15:34:07 -07:00
parent 1c37380cec
commit 73698fafe7
7 changed files with 483 additions and 265 deletions

View File

@@ -3,8 +3,10 @@ import { useNavigate } from "react-router-dom"
import { useQueryClient } from "@tanstack/react-query"
import { Check } from "lucide-react"
import { apiClient } from "@/services/api/client"
import type { AnyDetail } from "@/types"
import { DeploymentFields } from "@/components/DeploymentFields"
import type { AnyDetail, ProgramDetail, ServiceDetail, JobDetail } from "@/types"
import { ProgramFields } from "./ProgramFields"
import { ServiceFields } from "./ServiceFields"
import { JobFields } from "./JobFields"
interface ConfigPanelProps {
deployment: AnyDetail
@@ -61,11 +63,25 @@ export function ConfigPanel({ deployment, configSection, onRefetch }: ConfigPane
<h2 className="text-sm font-semibold text-[var(--muted)] uppercase tracking-wider mb-4">
Configuration
</h2>
<DeploymentFields
deployment={deployment}
onSave={handleSave}
onDelete={handleDelete}
/>
{configSection === "programs" ? (
<ProgramFields
program={deployment as ProgramDetail}
onSave={handleSave}
onDelete={handleDelete}
/>
) : configSection === "services" ? (
<ServiceFields
service={deployment as ServiceDetail}
onSave={handleSave}
onDelete={handleDelete}
/>
) : (
<JobFields
job={deployment as JobDetail}
onSave={handleSave}
onDelete={handleDelete}
/>
)}
</div>
</>
)