refactor: Rename component pages to program pages and remove tools concept
The 'tools' concept was just a filtered view of programs and added unnecessary complexity to the frontend. This commit: - Removes ToolCard.tsx and Tools.tsx (pages/components never used in router) - Renames ComponentDetail.tsx → ProgramDetail.tsx (exports ProgramDetailPage) - Renames ComponentRedirect.tsx → ProgramRedirect.tsx (exports ProgramRedirect) - Updates imports in routes.tsx to match new file names - Fixes stale comment in hooks.ts Frontend naming now aligns with the unified programs model.
This commit is contained in:
@@ -1,57 +0,0 @@
|
|||||||
import { Link } from "react-router-dom"
|
|
||||||
import { Terminal } from "lucide-react"
|
|
||||||
import type { ProgramSummary } from "@/types"
|
|
||||||
import { runnerLabel } from "@/lib/labels"
|
|
||||||
|
|
||||||
interface ToolCardProps {
|
|
||||||
tool: ProgramSummary
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ToolCard({ tool }: ToolCardProps) {
|
|
||||||
return (
|
|
||||||
<div className="bg-[var(--card)] border border-[var(--border)] rounded-lg p-5">
|
|
||||||
<div className="flex items-start justify-between mb-2">
|
|
||||||
<Link
|
|
||||||
to={`/component/${tool.id}`}
|
|
||||||
className="text-base font-semibold hover:text-[var(--primary)] transition-colors"
|
|
||||||
>
|
|
||||||
{tool.id}
|
|
||||||
</Link>
|
|
||||||
{tool.installed && (
|
|
||||||
<span className="text-xs px-2 py-0.5 rounded bg-green-900/30 text-green-400 border border-green-800">
|
|
||||||
installed
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{tool.description && (
|
|
||||||
<p className="text-sm text-[var(--muted)] mb-3">{tool.description}</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex items-center gap-3 text-xs text-[var(--muted)] mb-3">
|
|
||||||
{tool.runner && (
|
|
||||||
<span className="flex items-center gap-1">
|
|
||||||
<Terminal size={12} />
|
|
||||||
{runnerLabel(tool.runner)}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{tool.version && (
|
|
||||||
<span className="font-mono">v{tool.version}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{tool.system_dependencies.length > 0 && (
|
|
||||||
<div className="flex flex-wrap gap-1">
|
|
||||||
{tool.system_dependencies.map((dep) => (
|
|
||||||
<span
|
|
||||||
key={dep}
|
|
||||||
className="text-xs px-2 py-0.5 rounded bg-amber-900/30 text-amber-400 border border-amber-800"
|
|
||||||
>
|
|
||||||
{dep}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ import { DetailHeader } from "@/components/detail/DetailHeader"
|
|||||||
import { ConfigPanel } from "@/components/detail/ConfigPanel"
|
import { ConfigPanel } from "@/components/detail/ConfigPanel"
|
||||||
import { ProgramActions, ActionOutputPanel, type ActionOutput } from "@/components/ProgramActions"
|
import { ProgramActions, ActionOutputPanel, type ActionOutput } from "@/components/ProgramActions"
|
||||||
|
|
||||||
export function ComponentDetailPage() {
|
export function ProgramDetailPage() {
|
||||||
useEventStream()
|
useEventStream()
|
||||||
const { name } = useParams<{ name: string }>()
|
const { name } = useParams<{ name: string }>()
|
||||||
const { data: component, isLoading, error, refetch } = useProgram(name ?? "")
|
const { data: component, isLoading, error, refetch } = useProgram(name ?? "")
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useParams, Navigate } from "react-router-dom"
|
import { useParams, Navigate } from "react-router-dom"
|
||||||
import { useComponent } from "@/services/api/hooks"
|
import { useComponent } from "@/services/api/hooks"
|
||||||
|
|
||||||
export function ComponentRedirect() {
|
export function ProgramRedirect() {
|
||||||
const { name } = useParams<{ name: string }>()
|
const { name } = useParams<{ name: string }>()
|
||||||
const { data: component, isLoading, error } = useComponent(name ?? "")
|
const { data: component, isLoading, error } = useComponent(name ?? "")
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Link } from "react-router-dom"
|
|
||||||
import { ArrowLeft } from "lucide-react"
|
|
||||||
import { usePrograms } from "@/services/api/hooks"
|
|
||||||
import { ToolCard } from "@/components/ToolCard"
|
|
||||||
|
|
||||||
export function ToolsPage() {
|
|
||||||
const { data: tools, isLoading } = usePrograms("tool")
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="max-w-6xl mx-auto px-6 py-8">
|
|
||||||
<Link to="/" className="text-[var(--primary)] hover:underline flex items-center gap-1 mb-6">
|
|
||||||
<ArrowLeft size={16} /> Back
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<h1 className="text-3xl font-bold mb-2">Tools</h1>
|
|
||||||
<p className="text-sm text-[var(--muted)] mb-8">
|
|
||||||
CLI utilities installed to PATH via castle and run with uv.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{isLoading ? (
|
|
||||||
<p className="text-[var(--muted)]">Loading tools...</p>
|
|
||||||
) : tools?.length ? (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
||||||
{tools.map((tool) => (
|
|
||||||
<ToolCard key={tool.id} tool={tool} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p className="text-[var(--muted)]">No tools registered.</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -2,8 +2,8 @@ import { createBrowserRouter } from "react-router-dom"
|
|||||||
import { Dashboard } from "@/pages/Dashboard"
|
import { Dashboard } from "@/pages/Dashboard"
|
||||||
import { ServiceDetailPage } from "@/pages/ServiceDetail"
|
import { ServiceDetailPage } from "@/pages/ServiceDetail"
|
||||||
import { ScheduledDetailPage } from "@/pages/ScheduledDetail"
|
import { ScheduledDetailPage } from "@/pages/ScheduledDetail"
|
||||||
import { ComponentDetailPage } from "@/pages/ComponentDetail"
|
import { ProgramDetailPage } from "@/pages/ProgramDetail"
|
||||||
import { ComponentRedirect } from "@/pages/ComponentRedirect"
|
import { ProgramRedirect } from "@/pages/ProgramRedirect"
|
||||||
import { NodeDetailPage } from "@/pages/NodeDetail"
|
import { NodeDetailPage } from "@/pages/NodeDetail"
|
||||||
|
|
||||||
export const router = createBrowserRouter([
|
export const router = createBrowserRouter([
|
||||||
@@ -21,11 +21,11 @@ export const router = createBrowserRouter([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/programs/:name",
|
path: "/programs/:name",
|
||||||
element: <ComponentDetailPage />,
|
element: <ProgramDetailPage />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/component/:name",
|
path: "/component/:name",
|
||||||
element: <ComponentRedirect />,
|
element: <ProgramRedirect />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/node/:hostname",
|
path: "/node/:hostname",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import type {
|
|||||||
NodeDetail,
|
NodeDetail,
|
||||||
} from "@/types"
|
} from "@/types"
|
||||||
|
|
||||||
// Legacy compat hook — used by ConfigEditorPage and ComponentRedirect
|
// Legacy compat hook — used by ConfigEditorPage and ProgramRedirect
|
||||||
export function useComponent(name: string) {
|
export function useComponent(name: string) {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ["components", name],
|
queryKey: ["components", name],
|
||||||
|
|||||||
Reference in New Issue
Block a user