Fix tool install-state, inherit program description, declutter Tools cards
- Tool detail showed installed tools as 'Not installed': /deployments/{name}
populated 'installed' for path deployments but left 'active' null, and
ToolDetail keyed off 'active'. Now the endpoint sets active=installed for path,
and ToolDetail reads 'installed' directly (verified: on-PATH ⇒ True, else False).
- A deployment now inherits its program's description by default: copied at
creation (CLI create + API _save_deployment on new deployments) + a one-time
patchup of existing ones (29 deployments).
- Tools page cards no longer list deployments (ProgramCard showDeployments=false) —
the lens already scopes to the tool; the deployment list is a Programs-catalog thing.
This commit is contained in:
@@ -9,9 +9,16 @@ interface ProgramCardProps {
|
||||
// "/tools" so a tool card opens its tool detail page (a tool is 1:1 with its
|
||||
// program, same name).
|
||||
linkBase?: string
|
||||
// Whether to list the program's deployments. The Programs catalog shows them;
|
||||
// a kind-specific lens (e.g. Tools) is already looking at one deployment, so off.
|
||||
showDeployments?: boolean
|
||||
}
|
||||
|
||||
export function ProgramCard({ program, linkBase = "/programs" }: ProgramCardProps) {
|
||||
export function ProgramCard({
|
||||
program,
|
||||
linkBase = "/programs",
|
||||
showDeployments = true,
|
||||
}: ProgramCardProps) {
|
||||
// The dot reflects the uniform lifecycle state (a tool on PATH, a service
|
||||
// running, a static site served). Lifecycle controls live on the detail page's
|
||||
// Deployment section, not here — a card just shows state and links through.
|
||||
@@ -38,19 +45,21 @@ export function ProgramCard({ program, linkBase = "/programs" }: ProgramCardProp
|
||||
<StackBadge stack={program.stack} />
|
||||
</div>
|
||||
|
||||
{/* A program has no kind of its own — show its deployments (name · kind). */}
|
||||
{program.deployments.length > 0 ? (
|
||||
<div className="flex flex-col gap-1 mb-2">
|
||||
{program.deployments.map((d) => (
|
||||
<div key={d.name} className="flex items-center gap-1.5 text-xs">
|
||||
<span className="font-mono text-[var(--muted)]">{d.name}</span>
|
||||
<KindBadge kind={d.kind} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-[var(--muted)] italic mb-2">no deployment</p>
|
||||
)}
|
||||
{/* A program has no kind of its own — show its deployments (name · kind).
|
||||
Suppressed on kind-specific lenses (e.g. Tools) which already scope to one. */}
|
||||
{showDeployments &&
|
||||
(program.deployments.length > 0 ? (
|
||||
<div className="flex flex-col gap-1 mb-2">
|
||||
{program.deployments.map((d) => (
|
||||
<div key={d.name} className="flex items-center gap-1.5 text-xs">
|
||||
<span className="font-mono text-[var(--muted)]">{d.name}</span>
|
||||
<KindBadge kind={d.kind} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-[var(--muted)] italic mb-2">no deployment</p>
|
||||
))}
|
||||
|
||||
{program.description && (
|
||||
<p className="text-sm text-[var(--muted)]">{program.description}</p>
|
||||
|
||||
@@ -5,9 +5,10 @@ import { ProgramCard } from "./ProgramCard"
|
||||
interface ProgramListProps {
|
||||
programs: ProgramSummary[]
|
||||
linkBase?: string // where each card links (default "/programs")
|
||||
showDeployments?: boolean // list each program's deployments on the card (default true)
|
||||
}
|
||||
|
||||
export function ProgramList({ programs, linkBase }: ProgramListProps) {
|
||||
export function ProgramList({ programs, linkBase, showDeployments }: ProgramListProps) {
|
||||
const [search, setSearch] = useState("")
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
@@ -39,7 +40,12 @@ export function ProgramList({ programs, linkBase }: ProgramListProps) {
|
||||
) : (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{filtered.map((program) => (
|
||||
<ProgramCard key={program.id} program={program} linkBase={linkBase} />
|
||||
<ProgramCard
|
||||
key={program.id}
|
||||
program={program}
|
||||
linkBase={linkBase}
|
||||
showDeployments={showDeployments}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user