From 0515faadfdb2c36084a33dcf43084d06561ab080 Mon Sep 17 00:00:00 2001 From: Paul Payne Date: Sun, 14 Jun 2026 12:13:41 -0700 Subject: [PATCH] refactor(app): rename Component* UI widgets to accurate domain names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard widgets were named after the old 'component' concept. Renamed each to what it actually renders: - ComponentCard → ServiceCard (ServiceSummary, /services/, service actions) - ComponentTable → ProgramTable (ProgramSummary[], the program catalog) - ComponentEditor→ DeploymentEditor (DeploymentDetail, the unified type) - ComponentFields→ DeploymentFields (AnyDetail) - AddComponent → AddDeployment Also purged the domain term 'component' from the rest of the app: the useComponent hook → useDeployment, ConfigPanel + the three detail pages' `component` prop/var → `deployment`, and the gateway/node table headers (Component → Program / Deployment). Props renamed to match (component → service / program / deployment). The React UI directory app/src/components/ keeps its conventional name. App type-checks and builds clean. --- .../{AddComponent.tsx => AddDeployment.tsx} | 10 ++-- ...mponentEditor.tsx => DeploymentEditor.tsx} | 20 +++---- ...mponentFields.tsx => DeploymentFields.tsx} | 24 ++++----- app/src/components/GatewayPanel.tsx | 2 +- .../{ComponentTable.tsx => ProgramTable.tsx} | 30 +++++------ .../{ComponentCard.tsx => ServiceCard.tsx} | 40 +++++++------- app/src/components/ServiceSection.tsx | 4 +- app/src/components/detail/ConfigPanel.tsx | 10 ++-- app/src/pages/ConfigEditor.tsx | 12 ++--- app/src/pages/Dashboard.tsx | 4 +- app/src/pages/NodeDetail.tsx | 2 +- app/src/pages/ProgramDetail.tsx | 52 +++++++++---------- app/src/pages/ProgramRedirect.tsx | 10 ++-- app/src/pages/ScheduledDetail.tsx | 30 +++++------ app/src/pages/ServiceDetail.tsx | 46 ++++++++-------- app/src/services/api/hooks.ts | 4 +- app/src/types/index.ts | 2 +- 17 files changed, 151 insertions(+), 151 deletions(-) rename app/src/components/{AddComponent.tsx => AddDeployment.tsx} (95%) rename app/src/components/{ComponentEditor.tsx => DeploymentEditor.tsx} (67%) rename app/src/components/{ComponentFields.tsx => DeploymentFields.tsx} (92%) rename app/src/components/{ComponentTable.tsx => ProgramTable.tsx} (85%) rename app/src/components/{ComponentCard.tsx => ServiceCard.tsx} (77%) diff --git a/app/src/components/AddComponent.tsx b/app/src/components/AddDeployment.tsx similarity index 95% rename from app/src/components/AddComponent.tsx rename to app/src/components/AddDeployment.tsx index 098a97e..31c6aa2 100644 --- a/app/src/components/AddComponent.tsx +++ b/app/src/components/AddDeployment.tsx @@ -36,12 +36,12 @@ const TEMPLATES: Record> = { empty: {}, } -interface AddComponentProps { +interface AddDeploymentProps { onAdd: (name: string, config: Record) => Promise existingNames: string[] } -export function AddComponent({ onAdd, existingNames }: AddComponentProps) { +export function AddDeployment({ onAdd, existingNames }: AddDeploymentProps) { const [open, setOpen] = useState(false) const [name, setName] = useState("") const [description, setDescription] = useState("") @@ -100,7 +100,7 @@ export function AddComponent({ onAdd, existingNames }: AddComponentProps) { onClick={() => setOpen(true)} className="w-full flex items-center justify-center gap-2 p-4 border border-dashed border-[var(--border)] rounded-lg text-[var(--muted)] hover:text-[var(--foreground)] hover:border-[var(--primary)] transition-colors" > - Add component + Add entry ) } @@ -108,7 +108,7 @@ export function AddComponent({ onAdd, existingNames }: AddComponentProps) { return (
-

New component

+

New entry

@@ -150,7 +150,7 @@ export function AddComponent({ onAdd, existingNames }: AddComponentProps) { setDescription(e.target.value)} - placeholder="What does this component do?" + placeholder="What does this entry do?" className="w-full bg-black/30 border border-[var(--border)] rounded px-3 py-1.5 text-sm focus:outline-none focus:border-[var(--primary)]" /> diff --git a/app/src/components/ComponentEditor.tsx b/app/src/components/DeploymentEditor.tsx similarity index 67% rename from app/src/components/ComponentEditor.tsx rename to app/src/components/DeploymentEditor.tsx index 1aa70f2..8aef4f4 100644 --- a/app/src/components/ComponentEditor.tsx +++ b/app/src/components/DeploymentEditor.tsx @@ -1,17 +1,17 @@ import { useState } from "react" import { ChevronDown, ChevronRight } from "lucide-react" import type { DeploymentDetail } from "@/types" -import { ComponentFields } from "./ComponentFields" +import { DeploymentFields } from "./DeploymentFields" import { BehaviorBadge } from "./BehaviorBadge" import { StackBadge } from "./StackBadge" -interface ComponentEditorProps { - component: DeploymentDetail +interface DeploymentEditorProps { + deployment: DeploymentDetail onSave: (name: string, config: Record) => Promise onDelete: (name: string) => Promise } -export function ComponentEditor({ component, onSave, onDelete }: ComponentEditorProps) { +export function DeploymentEditor({ deployment, onSave, onDelete }: DeploymentEditorProps) { const [expanded, setExpanded] = useState(false) return ( @@ -22,19 +22,19 @@ export function ComponentEditor({ component, onSave, onDelete }: ComponentEditor >
{expanded ? : } - {component.id} - {component.description} + {deployment.id} + {deployment.description}
- - + +
{expanded && (
- diff --git a/app/src/components/ComponentFields.tsx b/app/src/components/DeploymentFields.tsx similarity index 92% rename from app/src/components/ComponentFields.tsx rename to app/src/components/DeploymentFields.tsx index 1ab6683..2349bc7 100644 --- a/app/src/components/ComponentFields.tsx +++ b/app/src/components/DeploymentFields.tsx @@ -4,16 +4,16 @@ import type { AnyDetail } from "@/types" import { runnerLabel } from "@/lib/labels" import { SecretsEditor } from "./SecretsEditor" -interface ComponentFieldsProps { - component: AnyDetail +interface DeploymentFieldsProps { + deployment: AnyDetail onSave: (name: string, config: Record) => Promise onDelete?: (name: string) => Promise } const SECRET_RE = /^\$\{secret:([^}]+)\}$/ -export function ComponentFields({ component, onSave, onDelete }: ComponentFieldsProps) { - const m = component.manifest +export function DeploymentFields({ deployment, onSave, onDelete }: DeploymentFieldsProps) { + const m = deployment.manifest const [saving, setSaving] = useState(false) const [saved, setSaved] = useState(false) @@ -93,7 +93,7 @@ export function ComponentFields({ component, onSave, onDelete }: ComponentFields delete config.proxy } - await onSave(component.id, config) + await onSave(deployment.id, config) setSaved(true) setTimeout(() => setSaved(false), 2000) } finally { @@ -122,7 +122,7 @@ export function ComponentFields({ component, onSave, onDelete }: ComponentFields )} - {("managed" in component && component.managed || port) && ( + {("managed" in deployment && deployment.managed || port) && ( )} - {("managed" in component && component.managed || healthPath) && ( + {("managed" in deployment && deployment.managed || healthPath) && ( )} - {"managed" in component && ( + {"managed" in deployment && ( - {component.managed ? "Yes" : "No"} + {deployment.managed ? "Yes" : "No"} )} @@ -217,13 +217,13 @@ export function ComponentFields({ component, onSave, onDelete }: ComponentFields {onDelete ? ( ) : (
diff --git a/app/src/components/GatewayPanel.tsx b/app/src/components/GatewayPanel.tsx index 93b0b3b..d77d527 100644 --- a/app/src/components/GatewayPanel.tsx +++ b/app/src/components/GatewayPanel.tsx @@ -63,7 +63,7 @@ export function GatewayPanel({ gateway, statuses }: GatewayPanelProps) { Path - Component + Program Port {multiNode && ( Node diff --git a/app/src/components/ComponentTable.tsx b/app/src/components/ProgramTable.tsx similarity index 85% rename from app/src/components/ComponentTable.tsx rename to app/src/components/ProgramTable.tsx index 8f728b7..aea4838 100644 --- a/app/src/components/ComponentTable.tsx +++ b/app/src/components/ProgramTable.tsx @@ -6,14 +6,14 @@ import { BehaviorBadge } from "./BehaviorBadge" import { StackBadge } from "./StackBadge" import { ProgramActions } from "./ProgramActions" -interface ComponentTableProps { - components: ProgramSummary[] +interface ProgramTableProps { + programs: ProgramSummary[] } type SortKey = "id" | "stack" | "behavior" type SortDir = "asc" | "desc" -export function ComponentTable({ components }: ComponentTableProps) { +export function ProgramTable({ programs }: ProgramTableProps) { const [search, setSearch] = useState("") const [sortKey, setSortKey] = useState("id") const [sortDir, setSortDir] = useState("asc") @@ -28,14 +28,14 @@ export function ComponentTable({ components }: ComponentTableProps) { } const filtered = useMemo(() => { - if (!search) return components + if (!search) return programs const q = search.toLowerCase() - return components.filter( + return programs.filter( (c) => c.id.toLowerCase().includes(q) || (c.description?.toLowerCase().includes(q) ?? false), ) - }, [components, search]) + }, [programs, search]) const sorted = useMemo(() => { const dir = sortDir === "asc" ? 1 : -1 @@ -76,7 +76,7 @@ export function ComponentTable({ components }: ComponentTableProps) { {sorted.map((comp) => ( - + ))} {sorted.length === 0 && ( @@ -120,30 +120,30 @@ function SortHeader({ ) } -function ComponentRow({ component }: { component: ProgramSummary }) { +function ProgramRow({ program }: { program: ProgramSummary }) { return ( - {component.id} + {program.id} - {component.description && ( + {program.description && (

- {component.description} + {program.description}

)} - + - + - + ) diff --git a/app/src/components/ComponentCard.tsx b/app/src/components/ServiceCard.tsx similarity index 77% rename from app/src/components/ComponentCard.tsx rename to app/src/components/ServiceCard.tsx index 389cf60..8a45214 100644 --- a/app/src/components/ComponentCard.tsx +++ b/app/src/components/ServiceCard.tsx @@ -6,17 +6,17 @@ import { runnerLabel } from "@/lib/labels" import { HealthBadge } from "./HealthBadge" import { StackBadge } from "./StackBadge" -interface ComponentCardProps { - component: ServiceSummary +interface ServiceCardProps { + service: ServiceSummary health?: HealthStatus } -export function ComponentCard({ component, health }: ComponentCardProps) { - const hasHttp = component.port != null +export function ServiceCard({ service, health }: ServiceCardProps) { + const hasHttp = service.port != null const { mutate, isPending } = useServiceAction() const doAction = (action: string) => { - mutate({ name: component.id, action }) + mutate({ name: service.id, action }) } const isDown = health?.status === "down" @@ -25,10 +25,10 @@ export function ComponentCard({ component, health }: ComponentCardProps) {
- {component.id} + {service.id} {health ? ( @@ -38,38 +38,38 @@ export function ComponentCard({ component, health }: ComponentCardProps) {
- +
- {component.description && ( -

{component.description}

+ {service.description && ( +

{service.description}

)}
- {component.port && ( + {service.port && ( - :{component.port} + :{service.port} )} - {component.runner && ( + {service.runner && ( - {runnerLabel(component.runner)} + {runnerLabel(service.runner)} )} - {component.proxy_path && ( + {service.proxy_path && ( - {component.proxy_path} + {service.proxy_path} )} - {component.port && ( + {service.port && ( Docs @@ -77,7 +77,7 @@ export function ComponentCard({ component, health }: ComponentCardProps) { )}
- {component.managed && ( + {service.managed && (
{isDown && (