mirror of https://github.com/kortix-ai/suna.git
Prevent multiple agent creation and improve mutation handling
Co-authored-by: markokraemer.mail <markokraemer.mail@gmail.com>
This commit is contained in:
parent
4657c1495f
commit
6b2602157e
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState, useMemo, useEffect } from 'react';
|
||||
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
||||
|
||||
|
@ -82,6 +82,7 @@ export default function AgentsPage() {
|
|||
const [publishDialog, setPublishDialog] = useState<PublishDialogData | null>(null);
|
||||
const [publishTags, setPublishTags] = useState<string[]>([]);
|
||||
const [publishingAgentId, setPublishingAgentId] = useState<string | null>(null);
|
||||
const [isCreatingNewAgent, setIsCreatingNewAgent] = useState(false);
|
||||
|
||||
const activeTab = useMemo(() => {
|
||||
return searchParams.get('tab') || 'my-agents';
|
||||
|
@ -250,9 +251,20 @@ export default function AgentsPage() {
|
|||
setEditDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleCreateNewAgent = () => {
|
||||
createNewAgentMutation.mutate();
|
||||
};
|
||||
const handleCreateNewAgent = useCallback(() => {
|
||||
if (isCreatingNewAgent || createNewAgentMutation.isPending) {
|
||||
return; // Prevent multiple clicks
|
||||
}
|
||||
|
||||
setIsCreatingNewAgent(true);
|
||||
|
||||
createNewAgentMutation.mutate(undefined, {
|
||||
onSettled: () => {
|
||||
// Reset the debounce state after mutation completes (success or error)
|
||||
setTimeout(() => setIsCreatingNewAgent(false), 1000);
|
||||
}
|
||||
});
|
||||
}, [isCreatingNewAgent, createNewAgentMutation]);
|
||||
|
||||
const handleInstallClick = (item: MarketplaceTemplate, e?: React.MouseEvent) => {
|
||||
if (e) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
@ -48,6 +48,7 @@ export const CreateAgentDialog = ({ isOpen, onOpenChange, onAgentCreated }: Crea
|
|||
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||
const [selectedCategory, setSelectedCategory] = useState<string>('All');
|
||||
const [formData, setFormData] = useState<AgentCreateRequest>(initialFormData);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const createAgentMutation = useCreateAgent();
|
||||
useEffect(() => {
|
||||
|
@ -109,19 +110,24 @@ export const CreateAgentDialog = ({ isOpen, onOpenChange, onAgentCreated }: Crea
|
|||
return tools;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formData.name.trim()) {
|
||||
const handleSubmit = useCallback(async () => {
|
||||
if (!formData.name.trim() || isSubmitting || createAgentMutation.isPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
await createAgentMutation.mutateAsync(formData);
|
||||
onOpenChange(false);
|
||||
onAgentCreated?.();
|
||||
} catch (error) {
|
||||
console.error('Error creating agent:', error);
|
||||
} finally {
|
||||
// Reset the debounce state after a delay
|
||||
setTimeout(() => setIsSubmitting(false), 1000);
|
||||
}
|
||||
};
|
||||
}, [formData, isSubmitting, createAgentMutation, onOpenChange, onAgentCreated]);
|
||||
|
||||
const handleCancel = () => {
|
||||
onOpenChange(false);
|
||||
|
@ -306,16 +312,16 @@ export const CreateAgentDialog = ({ isOpen, onOpenChange, onAgentCreated }: Crea
|
|||
<Button
|
||||
variant="outline"
|
||||
onClick={handleCancel}
|
||||
disabled={createAgentMutation.isPending}
|
||||
disabled={createAgentMutation.isPending || isSubmitting}
|
||||
className="px-6"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
disabled={createAgentMutation.isPending || !formData.name.trim()}
|
||||
disabled={createAgentMutation.isPending || isSubmitting || !formData.name.trim()}
|
||||
>
|
||||
{createAgentMutation.isPending ? (
|
||||
{createAgentMutation.isPending || isSubmitting ? (
|
||||
<>
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
Creating Agent
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
||||
import { Settings, ChevronRight, Bot, Presentation, FileSpreadsheet, Search, Plus, User, Check, ChevronDown } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
@ -61,6 +61,7 @@ export const AgentSelector: React.FC<AgentSelectorProps> = ({
|
|||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [highlightedIndex, setHighlightedIndex] = useState<number>(-1);
|
||||
const [isCreatingAgent, setIsCreatingAgent] = useState(false);
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -169,10 +170,21 @@ export const AgentSelector: React.FC<AgentSelectorProps> = ({
|
|||
router.push('/agents');
|
||||
};
|
||||
|
||||
const handleCreateAgent = () => {
|
||||
const handleCreateAgent = useCallback(() => {
|
||||
if (isCreatingAgent || createNewAgentMutation.isPending) {
|
||||
return; // Prevent multiple clicks
|
||||
}
|
||||
|
||||
setIsCreatingAgent(true);
|
||||
setIsOpen(false);
|
||||
createNewAgentMutation.mutate();
|
||||
};
|
||||
|
||||
createNewAgentMutation.mutate(undefined, {
|
||||
onSettled: () => {
|
||||
// Reset the debounce state after mutation completes (success or error)
|
||||
setTimeout(() => setIsCreatingAgent(false), 1000);
|
||||
}
|
||||
});
|
||||
}, [isCreatingAgent, createNewAgentMutation]);
|
||||
|
||||
const renderAgentItem = (agent: any, index: number) => {
|
||||
const isSelected = agent.id === selectedAgentId;
|
||||
|
@ -339,10 +351,11 @@ export const AgentSelector: React.FC<AgentSelectorProps> = ({
|
|||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleCreateAgent}
|
||||
className="text-xs flex items-center gap-2 rounded-xl hover:bg-accent/40 transition-all duration-200 text-muted-foreground hover:text-foreground px-4 py-2"
|
||||
disabled={isCreatingAgent || createNewAgentMutation.isPending}
|
||||
className="text-xs flex items-center gap-2 rounded-xl hover:bg-accent/40 transition-all duration-200 text-muted-foreground hover:text-foreground px-4 py-2 disabled:opacity-50"
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
Create Agent
|
||||
{isCreatingAgent || createNewAgentMutation.isPending ? 'Creating...' : 'Create Agent'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue