From 114612a98490536fe20855b7a4de11d8d94997b2 Mon Sep 17 00:00:00 2001 From: RockChinQ Date: Tue, 25 Aug 2026 23:34:35 +0800 Subject: [PATCH] refactor(agent): move delete action to header --- .../app/home/agents/AgentDetailContent.tsx | 77 ++++- .../agents/components/AgentFormComponent.tsx | 299 ++++++------------ .../ProcessorDetailWorkbench.tsx | 3 + .../e2e/processor-detail-workbench.spec.ts | 49 ++- 4 files changed, 213 insertions(+), 215 deletions(-) diff --git a/web/src/app/home/agents/AgentDetailContent.tsx b/web/src/app/home/agents/AgentDetailContent.tsx index 2d682a335..8ef7bbd06 100644 --- a/web/src/app/home/agents/AgentDetailContent.tsx +++ b/web/src/app/home/agents/AgentDetailContent.tsx @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; +import { Trash2 } from 'lucide-react'; import { httpClient } from '@/app/infra/http/HttpClient'; import { useCurrentWorkspace } from '@/app/infra/http'; import { Agent } from '@/app/infra/entities/api'; @@ -11,6 +12,15 @@ import EntityBasicInfoDialog, { EntityBasicInfoValues, } from '@/app/home/components/entity-basic-info/EntityBasicInfoDialog'; import EntityTitleEditButton from '@/app/home/components/entity-basic-info/EntityTitleEditButton'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; import PipelineDetailContent from '@/app/home/pipelines/PipelineDetailContent'; import AgentCreateContent from './components/AgentCreateContent'; import AgentDebugPanel from './components/AgentDebugPanel'; @@ -34,6 +44,8 @@ export default function AgentDetailContent({ id }: { id: string }) { const [formDirty, setFormDirty] = useState(false); const [formSaving, setFormSaving] = useState(false); const [basicInfoOpen, setBasicInfoOpen] = useState(false); + const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false); + const [deleting, setDeleting] = useState(false); const [runnerStatus, setRunnerStatus] = useState( null, ); @@ -111,6 +123,25 @@ export default function AgentDetailContent({ id }: { id: string }) { } } + async function deleteAgent() { + setDeleting(true); + try { + await httpClient.deleteAgent(id); + toast.success(t('agents.deleteSuccess')); + setDeleteConfirmOpen(false); + await refreshPipelines(); + navigate('/home/agents'); + } catch (error) { + const message = + typeof error === 'object' && error && 'msg' in error + ? String((error as { msg?: string }).msg || '') + : ''; + toast.error(t('agents.deleteError') + message); + } finally { + setDeleting(false); + } + } + return ( <> setDeleteConfirmOpen(true)} + > + + {t('common.delete')} + + ) : undefined + } configTitle={t('pipelines.configuration')} configContent={
@@ -141,10 +185,6 @@ export default function AgentDetailContent({ id }: { id: string }) { } refreshPipelines(); }} - onDeleted={() => { - refreshPipelines(); - navigate('/home/agents'); - }} onDirtyChange={setFormDirty} onSavingChange={setFormSaving} onRunnerStatusChange={setRunnerStatus} @@ -181,6 +221,35 @@ export default function AgentDetailContent({ id }: { id: string }) { defaultEmoji="🤖" onSave={saveBasicInfo} /> + + + + {t('common.confirmDelete')} + + {t('agents.deleteConfirmation')} + + + + + + + + ); } diff --git a/web/src/app/home/agents/components/AgentFormComponent.tsx b/web/src/app/home/agents/components/AgentFormComponent.tsx index 46730a6f0..37b845b6e 100644 --- a/web/src/app/home/agents/components/AgentFormComponent.tsx +++ b/web/src/app/home/agents/components/AgentFormComponent.tsx @@ -13,7 +13,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; -import { Bot, Power, SlidersHorizontal, Trash2, Zap } from 'lucide-react'; +import { Bot, SlidersHorizontal, Zap } from 'lucide-react'; import { httpClient } from '@/app/infra/http/HttpClient'; import { Agent, ApiRespPluginSystemStatus } from '@/app/infra/entities/api'; import { @@ -22,7 +22,6 @@ import { } from '@/app/infra/entities/pipeline'; import DynamicFormComponent from '@/app/home/components/dynamic-form/DynamicFormComponent'; import { extractI18nObject } from '@/i18n/I18nProvider'; -import { Button } from '@/components/ui/button'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Textarea } from '@/components/ui/textarea'; import { @@ -32,13 +31,6 @@ import { CardHeader, CardTitle, } from '@/components/ui/card'; -import { - Dialog, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; import { Form, FormControl, @@ -58,17 +50,12 @@ export interface AgentRunnerStatus { interface AgentFormComponentProps { agentId: string; onFinish: (agent?: Partial) => void; - onDeleted: () => void; onDirtyChange?: (dirty: boolean) => void; onSavingChange?: (saving: boolean) => void; onRunnerStatusChange?: (status: AgentRunnerStatus) => void; } -export type AgentConfigSection = - | 'events' - | 'runner' - | 'runner_config' - | 'basic'; +export type AgentConfigSection = 'events' | 'runner' | 'runner_config'; export interface AgentFormHandle { openSection: (section: AgentConfigSection) => void; @@ -114,7 +101,6 @@ function AgentFormComponent( { agentId, onFinish, - onDeleted, onDirtyChange, onSavingChange, onRunnerStatusChange, @@ -128,8 +114,6 @@ function AgentFormComponent( useState(null); const [pluginStatusLoading, setPluginStatusLoading] = useState(true); const [pluginStatusError, setPluginStatusError] = useState(false); - const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); - const [isSaving, setIsSaving] = useState(false); const [activeSection, setActiveSection] = useState('events'); const isSavingRef = useRef(false); @@ -283,11 +267,6 @@ function AgentFormComponent( : t('pipelines.configuration'), icon: SlidersHorizontal, }, - { - name: 'basic', - label: t('common.management'), - icon: Power, - }, ]; const runnerStatus = useMemo(() => { @@ -472,7 +451,6 @@ function AgentFormComponent( }; isSavingRef.current = true; - setIsSaving(true); onSavingChange?.(true); try { await httpClient.updateAgent(agentId, agent); @@ -489,7 +467,6 @@ function AgentFormComponent( return false; } finally { isSavingRef.current = false; - setIsSaving(false); onSavingChange?.(false); } }, @@ -533,192 +510,110 @@ function AgentFormComponent( [form, saveValues], ); - function confirmDelete() { - httpClient - .deleteAgent(agentId) - .then(() => { - toast.success(t('agents.deleteSuccess')); - setShowDeleteConfirm(false); - onDeleted(); - }) - .catch((err) => { - toast.error(t('agents.deleteError') + err.msg); - }); - } - return ( - <> -
-
- - + )} -
-
- {activeSection === 'runner' && ( -
- {runnerSelectorStage - ? renderDynamicStage(runnerSelectorStage) - : !runnerConfigSchema && ( - - - - {t('agents.runnerSettings')} - - - {t('agents.noRunnerMetadata')} - - - - )} -
- )} - - {activeSection === 'runner_config' && ( -
- {activeRunnerStage ? ( - renderDynamicStage(activeRunnerStage) - ) : ( - - - {t('agents.runnerSettings')} - - {t('agents.noRunnerMetadata')} - - - - )} -
- )} - - {activeSection === 'events' && ( - - - {t('agents.bindableEvents')} - - {t('agents.bindableEventsDescription')} - - - - ( - - {t('agents.supportedEvents')} - -