From e3150e66a4150627e0f069d6d473faec4b930c1a Mon Sep 17 00:00:00 2001 From: RockChinQ Date: Tue, 25 Aug 2026 12:36:57 +0800 Subject: [PATCH] refactor(web): use shadcn processor navigation --- .../agents/components/AgentFormComponent.tsx | 55 +++++------ .../ProcessorDetailWorkbench.tsx | 8 +- .../pipeline-form/PipelineFormComponent.tsx | 91 ++++++++----------- .../e2e/processor-detail-workbench.spec.ts | 26 +++--- .../unit/processor-detail-workbench.test.mjs | 6 +- 5 files changed, 78 insertions(+), 108 deletions(-) diff --git a/web/src/app/home/agents/components/AgentFormComponent.tsx b/web/src/app/home/agents/components/AgentFormComponent.tsx index 709df912f..5a28e1d7f 100644 --- a/web/src/app/home/agents/components/AgentFormComponent.tsx +++ b/web/src/app/home/agents/components/AgentFormComponent.tsx @@ -14,6 +14,7 @@ import { 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 { Switch } from '@/components/ui/switch'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; @@ -430,40 +431,26 @@ export default function AgentFormComponent({ className="mb-2 flex h-full min-h-0 min-w-0 flex-1 flex-col" >
diff --git a/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx b/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx index 11e8cce5e..733046242 100644 --- a/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx +++ b/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx @@ -1,5 +1,6 @@ import { ReactNode, useState } from 'react'; import { BarChart3, Bug, Settings } from 'lucide-react'; +import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Tooltip, @@ -69,12 +70,13 @@ export default function ProcessorDetailWorkbench({ {status && ( - {status.label} - +

{status.label}

diff --git a/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx b/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx index f91a468c5..d0d4c5c2c 100644 --- a/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx +++ b/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx @@ -8,6 +8,7 @@ import { import DynamicFormComponent from '@/app/home/components/dynamic-form/DynamicFormComponent'; import { getDefaultValues } from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; import { Button } from '@/components/ui/button'; +import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; @@ -31,7 +32,6 @@ import { import { toast } from 'sonner'; import { useTranslation } from 'react-i18next'; import { extractI18nObject } from '@/i18n/I18nProvider'; -import { cn } from '@/lib/utils'; import { Card, CardContent, @@ -580,64 +580,45 @@ export default function PipelineFormComponent({ {/* Keep the primary pipeline flow visible while editing. */} {formLabelList.length > 1 && (
+ )} diff --git a/web/tests/e2e/processor-detail-workbench.spec.ts b/web/tests/e2e/processor-detail-workbench.spec.ts index 79b290bfe..817abb0de 100644 --- a/web/tests/e2e/processor-detail-workbench.spec.ts +++ b/web/tests/e2e/processor-detail-workbench.spec.ts @@ -33,15 +33,15 @@ test.describe('processor detail workbench', () => { .toBe(0); expect(debugBox!.y).toBeGreaterThanOrEqual(0); - const flow = configPanel.locator('ol'); - await expect(flow.getByRole('button').nth(0)).toContainText( + const flow = configPanel.getByRole('tablist'); + await expect(flow.getByRole('tab').nth(0)).toContainText( 'Basic Information', ); - await expect(flow.getByRole('button').nth(1)).toContainText( + await expect(flow.getByRole('tab').nth(1)).toContainText( 'Bindable Event Range', ); - await expect(flow.getByRole('button').nth(2)).toContainText('Runner'); - await expect(flow.getByRole('button').nth(3)).toContainText('Local Agent'); + await expect(flow.getByRole('tab').nth(2)).toContainText('Runner'); + await expect(flow.getByRole('tab').nth(3)).toContainText('Local Agent'); await expect(configPanel.getByLabel('Name')).toBeVisible(); await expect(configPanel.getByLabel('Icon')).toBeVisible(); @@ -56,11 +56,11 @@ test.describe('processor detail workbench', () => { ), ).toBeVisible(); - await flow.getByRole('button').nth(1).click(); + await flow.getByRole('tab').nth(1).click(); await expect( configPanel.getByText('Bindable Event Range', { exact: true }).last(), ).toBeVisible(); - await flow.getByRole('button').nth(3).click(); + await flow.getByRole('tab').nth(3).click(); await expect( configPanel.getByText('Local Agent', { exact: true }).last(), ).toBeVisible(); @@ -91,18 +91,16 @@ test.describe('processor detail workbench', () => { .toBe(0); expect(debugBox!.y).toBeGreaterThanOrEqual(0); - const flow = configPanel.locator('ol'); - await expect(flow.getByRole('button').nth(0)).toContainText( + const flow = configPanel.getByRole('tablist'); + await expect(flow.getByRole('tab').nth(0)).toContainText( 'Trigger Conditions', ); - await expect(flow.getByRole('button').nth(1)).toContainText( - 'AI Capabilities', - ); - await expect(flow.getByRole('button').nth(2)).toContainText( + await expect(flow.getByRole('tab').nth(1)).toContainText('AI Capabilities'); + await expect(flow.getByRole('tab').nth(2)).toContainText( 'Output Processing', ); - await flow.getByRole('button').nth(1).click(); + await flow.getByRole('tab').nth(1).click(); await expect( configPanel.getByText('Runtime', { exact: true }).last(), ).toBeVisible(); diff --git a/web/tests/unit/processor-detail-workbench.test.mjs b/web/tests/unit/processor-detail-workbench.test.mjs index e078391ae..c5be1962e 100644 --- a/web/tests/unit/processor-detail-workbench.test.mjs +++ b/web/tests/unit/processor-detail-workbench.test.mjs @@ -65,6 +65,8 @@ test('processor forms expose their primary orchestration flow horizontally', () pipelineForm, /const primarySectionNames = \['trigger', 'ai', 'output'\]/, ); - assert.match(agentForm, /grid min-w-\[44rem\] grid-cols-4/); - assert.match(pipelineForm, /grid min-w-\[34rem\] grid-cols-3/); + assert.match(agentForm, /]*grid-cols-4/); + assert.match(pipelineForm, /]*grid-cols-3/); + assert.doesNotMatch(agentForm, /