fix: replace native confirm dialog with React dialog for agent deletion
- Replace synchronous confirm() with proper React Dialog component - Add state management for delete confirmation dialog - Prevent immediate deletion before user confirmation - Add loading states and proper error handling - Improve UX with clear confirmation message and responsive design
This commit is contained in:
@@ -30,6 +30,14 @@ import {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
import { api, type Agent, type AgentRunWithMetrics } from "@/lib/api";
|
import { api, type Agent, type AgentRunWithMetrics } from "@/lib/api";
|
||||||
import { save, open } from "@tauri-apps/plugin-dialog";
|
import { save, open } from "@tauri-apps/plugin-dialog";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
@@ -87,6 +95,9 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
|
|||||||
const [selectedAgent, setSelectedAgent] = useState<Agent | null>(null);
|
const [selectedAgent, setSelectedAgent] = useState<Agent | null>(null);
|
||||||
const [selectedRunId, setSelectedRunId] = useState<number | null>(null);
|
const [selectedRunId, setSelectedRunId] = useState<number | null>(null);
|
||||||
const [showGitHubBrowser, setShowGitHubBrowser] = useState(false);
|
const [showGitHubBrowser, setShowGitHubBrowser] = useState(false);
|
||||||
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
|
const [agentToDelete, setAgentToDelete] = useState<Agent | null>(null);
|
||||||
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
|
|
||||||
const AGENTS_PER_PAGE = 9; // 3x3 grid
|
const AGENTS_PER_PAGE = 9; // 3x3 grid
|
||||||
|
|
||||||
@@ -122,20 +133,46 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteAgent = async (id: number) => {
|
/**
|
||||||
if (!confirm("Are you sure you want to delete this agent?")) return;
|
* Initiates the delete agent process by showing the confirmation dialog
|
||||||
|
* @param agent - The agent to be deleted
|
||||||
|
*/
|
||||||
|
const handleDeleteAgent = (agent: Agent) => {
|
||||||
|
setAgentToDelete(agent);
|
||||||
|
setShowDeleteDialog(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirms and executes the agent deletion
|
||||||
|
* Only called when user explicitly confirms the deletion
|
||||||
|
*/
|
||||||
|
const confirmDeleteAgent = async () => {
|
||||||
|
if (!agentToDelete?.id) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await api.deleteAgent(id);
|
setIsDeleting(true);
|
||||||
|
await api.deleteAgent(agentToDelete.id);
|
||||||
setToast({ message: "Agent deleted successfully", type: "success" });
|
setToast({ message: "Agent deleted successfully", type: "success" });
|
||||||
await loadAgents();
|
await loadAgents();
|
||||||
await loadRuns(); // Reload runs as they might be affected
|
await loadRuns(); // Reload runs as they might be affected
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to delete agent:", err);
|
console.error("Failed to delete agent:", err);
|
||||||
setToast({ message: "Failed to delete agent", type: "error" });
|
setToast({ message: "Failed to delete agent", type: "error" });
|
||||||
|
} finally {
|
||||||
|
setIsDeleting(false);
|
||||||
|
setShowDeleteDialog(false);
|
||||||
|
setAgentToDelete(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the delete operation and closes the dialog
|
||||||
|
*/
|
||||||
|
const cancelDeleteAgent = () => {
|
||||||
|
setShowDeleteDialog(false);
|
||||||
|
setAgentToDelete(null);
|
||||||
|
};
|
||||||
|
|
||||||
const handleEditAgent = (agent: Agent) => {
|
const handleEditAgent = (agent: Agent) => {
|
||||||
setSelectedAgent(agent);
|
setSelectedAgent(agent);
|
||||||
setView("edit");
|
setView("edit");
|
||||||
@@ -473,7 +510,7 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
|
|||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => handleDeleteAgent(agent.id!)}
|
onClick={() => handleDeleteAgent(agent)}
|
||||||
className="flex items-center gap-1 text-destructive hover:text-destructive"
|
className="flex items-center gap-1 text-destructive hover:text-destructive"
|
||||||
title="Delete agent"
|
title="Delete agent"
|
||||||
>
|
>
|
||||||
@@ -571,6 +608,50 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
|
|||||||
setToast({ message: "Agent imported successfully from GitHub", type: "success" });
|
setToast({ message: "Agent imported successfully from GitHub", type: "success" });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Delete Confirmation Dialog */}
|
||||||
|
<Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||||
|
<DialogContent className="sm:max-w-md">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="flex items-center gap-2">
|
||||||
|
<Trash2 className="h-5 w-5 text-destructive" />
|
||||||
|
Delete Agent
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Are you sure you want to delete the agent "{agentToDelete?.name}"?
|
||||||
|
This action cannot be undone and will permanently remove the agent and all its associated data.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={cancelDeleteAgent}
|
||||||
|
disabled={isDeleting}
|
||||||
|
className="w-full sm:w-auto"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
onClick={confirmDeleteAgent}
|
||||||
|
disabled={isDeleting}
|
||||||
|
className="w-full sm:w-auto"
|
||||||
|
>
|
||||||
|
{isDeleting ? (
|
||||||
|
<>
|
||||||
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2" />
|
||||||
|
Deleting...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Trash2 className="h-4 w-4 mr-2" />
|
||||||
|
Delete Agent
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user