78e808bc54
- Sessions page: replaced CreateSessionForm with workspace selector + ToolStarter - Fetches workspaces, shows dropdown, then renders ToolStarter for selected workspace - Removed old project/repo/tool-type/config-profile/clone-mode flow - Workspace cards: new WorkspaceInstanceChips component fetches and displays running instances per workspace with status-colored chips and open links - Styles: .instance-chip variants (running/starting/error), .tool-starter-header Quality gates: tsc --noEmit clean, pytest workspaces API (9 passed, 1 skipped)
78 lines
2.0 KiB
TypeScript
78 lines
2.0 KiB
TypeScript
/** Card component for displaying a workspace. */
|
|
|
|
import { Link } from "react-router-dom";
|
|
import { Icon } from "./icon";
|
|
import { WorkspaceInstanceChips } from "./workspace-instance-chips";
|
|
import type { Workspace } from "../types/workspace";
|
|
|
|
export interface WorkspaceCardProps {
|
|
workspace: Workspace;
|
|
loading?: boolean;
|
|
onStartTool: (workspace: Workspace) => void;
|
|
onSync: (workspace: Workspace) => void;
|
|
onDelete: (workspace: Workspace) => void;
|
|
}
|
|
|
|
export function WorkspaceCard({
|
|
workspace,
|
|
loading = false,
|
|
onStartTool,
|
|
onSync,
|
|
onDelete,
|
|
}: WorkspaceCardProps) {
|
|
const statusClass =
|
|
workspace.status === "ready"
|
|
? "status-ready"
|
|
: workspace.status === "syncing"
|
|
? "status-syncing"
|
|
: "status-error";
|
|
|
|
return (
|
|
<article className={`card workspace-card ${loading ? "loading" : ""}`}>
|
|
<Link
|
|
to={`/workspaces/${workspace.id}`}
|
|
className="workspace-header-link"
|
|
>
|
|
<div className="workspace-header">
|
|
<h4>{workspace.name}</h4>
|
|
<span className={`status-badge ${statusClass}`}>
|
|
{workspace.status}
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
<div className="workspace-meta">
|
|
<p className="workspace-project">
|
|
{workspace.project_name} / {workspace.repo_name}
|
|
</p>
|
|
<p className="workspace-branch">
|
|
<Icon name="branch" size="sm" /> {workspace.branch}
|
|
</p>
|
|
<WorkspaceInstanceChips workspaceId={workspace.id} />
|
|
</div>
|
|
<div className="workspace-actions">
|
|
<button
|
|
className="btn btn-primary"
|
|
onClick={() => onStartTool(workspace)}
|
|
disabled={loading}
|
|
>
|
|
<Icon name="play" size="sm" /> Start Tool
|
|
</button>
|
|
<button
|
|
className="btn btn-secondary"
|
|
onClick={() => onSync(workspace)}
|
|
disabled={loading}
|
|
>
|
|
<Icon name="refresh" size="sm" /> Sync
|
|
</button>
|
|
<button
|
|
className="btn btn-danger"
|
|
onClick={() => onDelete(workspace)}
|
|
disabled={loading}
|
|
>
|
|
<Icon name="delete" size="sm" /> Delete
|
|
</button>
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|