From a9b24e59ec41de0b53243bf80aa56c7e2da387d4 Mon Sep 17 00:00:00 2001 From: RockChinQ Date: Thu, 27 Aug 2026 14:55:59 +0800 Subject: [PATCH] refactor(agents): use shadcn processor type toggle --- .../agents/components/AgentCreateContent.tsx | 100 ++++++------------ web/tests/e2e/crud-smoke.spec.ts | 30 +++--- 2 files changed, 50 insertions(+), 80 deletions(-) diff --git a/web/src/app/home/agents/components/AgentCreateContent.tsx b/web/src/app/home/agents/components/AgentCreateContent.tsx index 9e6e8a972..66d7cd613 100644 --- a/web/src/app/home/agents/components/AgentCreateContent.tsx +++ b/web/src/app/home/agents/components/AgentCreateContent.tsx @@ -1,16 +1,14 @@ import { useState } from 'react'; -import type React from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; -import { Bot, CheckCircle2, Workflow } from 'lucide-react'; +import { Bot, Workflow } from 'lucide-react'; import { httpClient } from '@/app/infra/http/HttpClient'; import { AgentKind } from '@/app/infra/entities/api'; -import { cn } from '@/lib/utils'; import { Button } from '@/components/ui/button'; -import { Badge } from '@/components/ui/badge'; +import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'; import { Card, CardContent, @@ -79,26 +77,18 @@ export default function AgentCreateContent({ }); } - const typeOptions: Array<{ - kind: AgentKind; - icon: React.ElementType; - title: string; - description: string; - badge: string; - }> = [ + const typeOptions = [ { - kind: 'agent', + kind: 'agent' as const, icon: Bot, title: t('agents.agentType'), - description: t('agents.agentTypeDescription'), - badge: t('agents.allEvents'), + helper: t('agents.allEvents'), }, { - kind: 'pipeline', + kind: 'pipeline' as const, icon: Workflow, title: t('agents.pipelineType'), - description: t('agents.pipelineTypeDescription'), - badge: t('agents.messageEventsOnly'), + helper: t('agents.messageEventsOnly'), }, ]; @@ -131,63 +121,41 @@ export default function AgentCreateContent({

-
+ { + if (value) handleKindChange(value as AgentKind); + }} + variant="outline" + spacing={3} + className="grid w-full gap-3 sm:grid-cols-2 lg:grid-cols-1" + > {typeOptions.map((option) => { const Icon = option.icon; - const selected = kind === option.kind; return ( - - - - - + + + + + + {option.title} + + + {option.helper} + + + ); })} -
+ diff --git a/web/tests/e2e/crud-smoke.spec.ts b/web/tests/e2e/crud-smoke.spec.ts index 5b1495d48..201ecec72 100644 --- a/web/tests/e2e/crud-smoke.spec.ts +++ b/web/tests/e2e/crud-smoke.spec.ts @@ -97,7 +97,7 @@ test.describe('frontend CRUD smoke flows', () => { await expect(page).toHaveURL(/\/home\/bots\?id=bot-1$/); await page.goto('/home/agents?id=new'); - await page.getByRole('button', { name: /^Pipeline/ }).click(); + await page.getByRole('radio', { name: /^Pipeline/ }).click(); await page.locator('input[name="name"]').fill('Viewer Pipeline'); await page .locator('input[name="description"]') @@ -173,18 +173,20 @@ test.describe('frontend CRUD smoke flows', () => { await page.goto('/home/agents?id=new'); const agentTypeCard = page.locator('[data-processor-kind="agent"]'); const pipelineTypeCard = page.locator('[data-processor-kind="pipeline"]'); - await expect(agentTypeCard).toHaveAttribute('data-slot', 'card'); - await expect(pipelineTypeCard).toHaveAttribute('data-slot', 'card'); - await expect( - agentTypeCard.getByRole('button', { name: /^Agent/ }), - ).toHaveAttribute('aria-pressed', 'true'); + await expect(agentTypeCard).toHaveAttribute( + 'data-slot', + 'toggle-group-item', + ); + await expect(pipelineTypeCard).toHaveAttribute( + 'data-slot', + 'toggle-group-item', + ); + await expect(agentTypeCard).toHaveAttribute('aria-checked', 'true'); await expect(page.getByTestId('agent-diagram')).toBeVisible(); await expect(page.getByTestId('pipeline-diagram')).toHaveCount(0); - await page.getByRole('button', { name: /^Pipeline/ }).click(); - await expect( - pipelineTypeCard.getByRole('button', { name: /^Pipeline/ }), - ).toHaveAttribute('aria-pressed', 'true'); + await page.getByRole('radio', { name: /^Pipeline/ }).click(); + await expect(pipelineTypeCard).toHaveAttribute('aria-checked', 'true'); await expect(page.getByTestId('pipeline-diagram')).toBeVisible(); await expect(page.getByTestId('agent-diagram')).toHaveCount(0); @@ -734,7 +736,7 @@ test.describe('pipeline advanced flows', () => { // Create a pipeline await page.goto('/home/agents?id=new'); - await page.getByRole('button', { name: /^Pipeline/ }).click(); + await page.getByRole('radio', { name: /^Pipeline/ }).click(); await page.locator('input[name="name"]').fill('Tab Test Pipeline'); await submit(page); @@ -765,7 +767,7 @@ test.describe('pipeline advanced flows', () => { // Create a pipeline await page.goto('/home/agents?id=new'); - await page.getByRole('button', { name: /^Pipeline/ }).click(); + await page.getByRole('radio', { name: /^Pipeline/ }).click(); await page.locator('input[name="name"]').fill('Dirty Form Pipeline'); await submit(page); @@ -787,7 +789,7 @@ test.describe('pipeline advanced flows', () => { await installLangBotApiMocks(page, { authenticated: true }); await page.goto('/home/agents?id=new'); - await page.getByRole('button', { name: /^Pipeline/ }).click(); + await page.getByRole('radio', { name: /^Pipeline/ }).click(); // Submit without filling name await submit(page); @@ -1038,7 +1040,7 @@ test.describe('cross-resource flows', () => { // Create a pipeline first await page.goto('/home/agents?id=new'); - await page.getByRole('button', { name: /^Pipeline/ }).click(); + await page.getByRole('radio', { name: /^Pipeline/ }).click(); await page.locator('input[name="name"]').fill('Production Pipeline'); await submit(page); await expect(page).toHaveURL(/\/home\/agents\?id=pipeline-1$/);