feat: add ComponentGrid and ComponentTable components for displaying components in grid and table formats
feat: implement HealthBadge and RoleBadge components for displaying health status and roles feat: create LogViewer component for streaming logs of services feat: develop SecretsEditor for managing secrets with CRUD operations feat: introduce ToolCard component for displaying tool information style: add global CSS variables and styles for consistent theming feat: set up API client for handling requests to the backend feat: implement hooks for fetching components, statuses, and tools feat: create routes for dashboard, component details, and tools feat: add service management endpoints for starting, stopping, and restarting services feat: implement event bus for handling real-time updates via SSE feat: create health check and logs endpoints for monitoring services feat: add tests for health and tools endpoints to ensure functionality chore: update project configuration files and dependencies for better development experience
This commit is contained in:
56
app/src/components/ComponentGrid.tsx
Normal file
56
app/src/components/ComponentGrid.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { ComponentSummary, HealthStatus } from "@/types"
|
||||
import { ComponentCard } from "./ComponentCard"
|
||||
|
||||
const ROLE_ORDER = ["service", "tool", "worker", "job", "frontend", "remote", "containerized"]
|
||||
const ROLE_LABELS: Record<string, string> = {
|
||||
service: "Services",
|
||||
tool: "Tools",
|
||||
worker: "Workers",
|
||||
job: "Jobs",
|
||||
frontend: "Frontends",
|
||||
remote: "Remote",
|
||||
containerized: "Containers",
|
||||
}
|
||||
|
||||
interface ComponentGridProps {
|
||||
components: ComponentSummary[]
|
||||
statuses: HealthStatus[]
|
||||
}
|
||||
|
||||
export function ComponentGrid({ components, statuses }: ComponentGridProps) {
|
||||
const statusMap = new Map(statuses.map((s) => [s.id, s]))
|
||||
|
||||
// Group by primary role
|
||||
const groups = new Map<string, ComponentSummary[]>()
|
||||
for (const comp of components) {
|
||||
const primary = comp.roles[0] ?? "tool"
|
||||
const list = groups.get(primary) ?? []
|
||||
list.push(comp)
|
||||
groups.set(primary, list)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
{ROLE_ORDER.map((role) => {
|
||||
const items = groups.get(role)
|
||||
if (!items?.length) return null
|
||||
return (
|
||||
<section key={role}>
|
||||
<h2 className="text-lg font-semibold mb-3 text-[var(--muted)]">
|
||||
{ROLE_LABELS[role] ?? role}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{items.map((comp) => (
|
||||
<ComponentCard
|
||||
key={comp.id}
|
||||
component={comp}
|
||||
health={statusMap.get(comp.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user