feat(kanban): Add ability to delete in-progress cards with auto agent stop

- Add delete button to in_progress cards that are not currently running
- Update handleDeleteFeature to stop running agents before deleting
- Show confirmation message mentioning agent will be stopped when card is running
- Add test utilities for delete in-progress feature testing

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Cody Seibert
2025-12-09 01:43:44 -05:00
parent ef5584a488
commit 0be9d751fe
4 changed files with 148 additions and 9 deletions

View File

@@ -152,6 +152,7 @@ export function BoardView() {
...f,
id: f.id || `feature-${index}-${Date.now()}`,
status: f.status || "backlog",
startedAt: f.startedAt, // Preserve startedAt timestamp
})
);
setFeatures(featuresWithIds);
@@ -256,6 +257,7 @@ export function BoardView() {
description: f.description,
steps: f.steps,
status: f.status,
startedAt: f.startedAt,
}));
await api.writeFile(
`${currentProject.path}/.automaker/feature_list.json`,
@@ -325,13 +327,14 @@ export function BoardView() {
return;
}
// Move the feature
moveFeature(featureId, targetStatus);
// If moved to in_progress, trigger the agent
// Move the feature and set startedAt if moving to in_progress
if (targetStatus === "in_progress") {
// Update with startedAt timestamp
updateFeature(featureId, { status: targetStatus, startedAt: new Date().toISOString() });
console.log("[Board] Feature moved to in_progress, starting agent...");
await handleRunFeature(draggedFeature);
} else {
moveFeature(featureId, targetStatus);
}
};
@@ -358,8 +361,34 @@ export function BoardView() {
setEditingFeature(null);
};
const handleDeleteFeature = (featureId: string) => {
if (window.confirm("Are you sure you want to delete this feature?")) {
const handleDeleteFeature = async (featureId: string) => {
const feature = features.find((f) => f.id === featureId);
if (!feature) return;
// Check if the feature is currently running
const isRunning = runningAutoTasks.includes(featureId);
const confirmMessage = isRunning
? "This feature has an agent running. Deleting it will stop the agent. Are you sure you want to delete this feature?"
: "Are you sure you want to delete this feature?";
if (window.confirm(confirmMessage)) {
// If the feature is running, stop the agent first
if (isRunning) {
try {
await autoMode.stopFeature(featureId);
toast.success("Agent stopped", {
description: `Stopped and deleted: ${feature.description.slice(0, 50)}${feature.description.length > 50 ? "..." : ""}`,
});
} catch (error) {
console.error("[Board] Error stopping feature before delete:", error);
toast.error("Failed to stop agent", {
description: "The feature will still be deleted.",
});
}
}
// Remove the feature
removeFeature(featureId);
}
};

View File

@@ -13,6 +13,7 @@ import {
import { Button } from "@/components/ui/button";
import { Feature } from "@/store/app-store";
import { GripVertical, Edit, CheckCircle2, Circle, Loader2, Trash2, Eye, PlayCircle, RotateCcw, StopCircle } from "lucide-react";
import { CountUpTimer } from "@/components/ui/count-up-timer";
interface KanbanCardProps {
feature: Feature;
@@ -60,9 +61,18 @@ export function KanbanCard({ feature, onEdit, onDelete, onViewOutput, onVerify,
>
<CardHeader className="p-3 pb-2">
{isCurrentAutoTask && (
<div className="absolute top-2 right-2 flex items-center gap-1 bg-purple-500/20 border border-purple-500 rounded px-2 py-0.5">
<div className="absolute top-2 right-2 flex items-center gap-2 bg-purple-500/20 border border-purple-500 rounded px-2 py-0.5">
<Loader2 className="w-4 h-4 text-purple-400 animate-spin" />
<span className="text-xs text-purple-400 font-medium">Running...</span>
{feature.startedAt && (
<CountUpTimer startedAt={feature.startedAt} className="text-purple-400" />
)}
</div>
)}
{/* Show timer for in_progress cards that aren't currently running */}
{!isCurrentAutoTask && feature.status === "in_progress" && feature.startedAt && (
<div className="absolute top-2 right-2">
<CountUpTimer startedAt={feature.startedAt} className="text-yellow-500" />
</div>
)}
<div className="flex items-start gap-2">
@@ -193,6 +203,18 @@ export function KanbanCard({ feature, onEdit, onDelete, onViewOutput, onVerify,
Output
</Button>
)}
<Button
variant="ghost"
size="sm"
className="h-7 text-xs text-destructive hover:text-destructive hover:bg-destructive/10"
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
data-testid={`delete-inprogress-feature-${feature.id}`}
>
<Trash2 className="w-3 h-3" />
</Button>
</>
)}
{!isCurrentAutoTask && feature.status !== "in_progress" && (