From 58cbd337b5d1f41f23b200fe69fc844544037ad9 Mon Sep 17 00:00:00 2001 From: lyzno1 <92089059+lyzno1@users.noreply.github.com> Date: Sat, 6 Sep 2025 22:54:36 +0800 Subject: [PATCH] fix: improve test run menu and checklist ui (#25300) --- .../components/workflow/header/checklist.tsx | 4 +- .../workflow/header/run-and-history.tsx | 14 +-- ...est-run-dropdown.tsx => test-run-menu.tsx} | 10 +-- .../hooks/use-dynamic-test-run-options.tsx | 90 +++++++------------ 4 files changed, 44 insertions(+), 74 deletions(-) rename web/app/components/workflow/header/{test-run-dropdown.tsx => test-run-menu.tsx} (93%) diff --git a/web/app/components/workflow/header/checklist.tsx b/web/app/components/workflow/header/checklist.tsx index d596381fb5..b3c7d966d5 100644 --- a/web/app/components/workflow/header/checklist.tsx +++ b/web/app/components/workflow/header/checklist.tsx @@ -119,8 +119,8 @@ const WorkflowChecklist = ({ {node.title} -
- +
+ {t('workflow.panel.goTo')} diff --git a/web/app/components/workflow/header/run-and-history.tsx b/web/app/components/workflow/header/run-and-history.tsx index 6626f7f226..a707f8a9b2 100644 --- a/web/app/components/workflow/header/run-and-history.tsx +++ b/web/app/components/workflow/header/run-and-history.tsx @@ -16,8 +16,8 @@ import { import { WorkflowRunningStatus } from '../types' import ViewHistory from './view-history' import Checklist from './checklist' -import TestRunDropdown, { type TestRunDropdownRef } from './test-run-dropdown' -import type { TriggerOption } from './test-run-dropdown' +import TestRunMenu, { type TestRunMenuRef } from './test-run-menu' +import type { TriggerOption } from './test-run-menu' import { useDynamicTestRunOptions } from '../hooks/use-dynamic-test-run-options' import cn from '@/utils/classnames' import { @@ -36,12 +36,12 @@ const RunMode = memo(() => { const workflowRunningData = useStore(s => s.workflowRunningData) const isRunning = workflowRunningData?.result.status === WorkflowRunningStatus.Running const dynamicOptions = useDynamicTestRunOptions() - const testRunDropdownRef = useRef(null) + const testRunMenuRef = useRef(null) useEffect(() => { // @ts-expect-error - Dynamic property for backward compatibility with keyboard shortcuts window._toggleTestRunDropdown = () => { - testRunDropdownRef.current?.toggle() + testRunMenuRef.current?.toggle() } return () => { // @ts-expect-error - Dynamic property cleanup @@ -89,8 +89,8 @@ const RunMode = memo(() => {
) : ( - @@ -105,7 +105,7 @@ const RunMode = memo(() => { {t('workflow.common.run')}
- + ) } { diff --git a/web/app/components/workflow/header/test-run-dropdown.tsx b/web/app/components/workflow/header/test-run-menu.tsx similarity index 93% rename from web/app/components/workflow/header/test-run-dropdown.tsx rename to web/app/components/workflow/header/test-run-menu.tsx index 73c11b37c3..8abef9698f 100644 --- a/web/app/components/workflow/header/test-run-dropdown.tsx +++ b/web/app/components/workflow/header/test-run-menu.tsx @@ -22,17 +22,17 @@ export type TestRunOptions = { runAll?: TriggerOption } -type TestRunDropdownProps = { +type TestRunMenuProps = { options: TestRunOptions onSelect: (option: TriggerOption) => void children: React.ReactNode } -export type TestRunDropdownRef = { +export type TestRunMenuRef = { toggle: () => void } -const TestRunDropdown = forwardRef(({ +const TestRunMenu = forwardRef(({ options, onSelect, children, @@ -107,6 +107,6 @@ const TestRunDropdown = forwardRef(({ ) }) -TestRunDropdown.displayName = 'TestRunDropdown' +TestRunMenu.displayName = 'TestRunMenu' -export default TestRunDropdown +export default TestRunMenu diff --git a/web/app/components/workflow/hooks/use-dynamic-test-run-options.tsx b/web/app/components/workflow/hooks/use-dynamic-test-run-options.tsx index cba3a9cd2e..aca9a3389f 100644 --- a/web/app/components/workflow/hooks/use-dynamic-test-run-options.tsx +++ b/web/app/components/workflow/hooks/use-dynamic-test-run-options.tsx @@ -3,14 +3,12 @@ import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import { BlockEnum, type CommonNodeType } from '../types' import { getWorkflowEntryNode } from '../utils/workflow-entry' -import type { TestRunOptions, TriggerOption } from '../header/test-run-dropdown' -import Home from '@/app/components/base/icons/src/vender/workflow/Home' -import { Schedule, TriggerAll, WebhookLine } from '@/app/components/base/icons/src/vender/workflow' -import AppIcon from '@/app/components/base/app-icon' +import type { TestRunOptions, TriggerOption } from '../header/test-run-menu' +import { TriggerAll } from '@/app/components/base/icons/src/vender/workflow' +import BlockIcon from '../block-icon' import { useStore } from '../store' import { canFindTool } from '@/utils' -import { CollectionType } from '@/app/components/tools/types' -import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' +import { useAllTriggerPlugins } from '@/service/use-triggers' export const useDynamicTestRunOptions = (): TestRunOptions => { const { t } = useTranslation() @@ -19,7 +17,7 @@ export const useDynamicTestRunOptions = (): TestRunOptions => { const customTools = useStore(s => s.customTools) const workflowTools = useStore(s => s.workflowTools) const mcpTools = useStore(s => s.mcpTools) - const { getIconUrl } = useGetIcon() + const { data: triggerPlugins } = useAllTriggerPlugins() return useMemo(() => { const allTriggers: TriggerOption[] = [] @@ -36,9 +34,10 @@ export const useDynamicTestRunOptions = (): TestRunOptions => { type: 'user_input', name: nodeData.title || t('workflow.blocks.start'), icon: ( -
- -
+ ), nodeId: node.id, enabled: true, @@ -50,9 +49,10 @@ export const useDynamicTestRunOptions = (): TestRunOptions => { type: 'schedule', name: nodeData.title || t('workflow.blocks.trigger-schedule'), icon: ( -
- -
+ ), nodeId: node.id, enabled: true, @@ -64,61 +64,30 @@ export const useDynamicTestRunOptions = (): TestRunOptions => { type: 'webhook', name: nodeData.title || t('workflow.blocks.trigger-webhook'), icon: ( -
- -
+ ), nodeId: node.id, enabled: true, }) } else if (nodeData.type === BlockEnum.TriggerPlugin) { - let icon let toolIcon: string | any - // 按照 use-workflow-search.tsx 的模式获取工具图标 if (nodeData.provider_id) { - let targetTools = workflowTools - if (nodeData.provider_type === CollectionType.builtIn) - targetTools = buildInTools - else if (nodeData.provider_type === CollectionType.custom) - targetTools = customTools - else if (nodeData.provider_type === CollectionType.mcp) - targetTools = mcpTools - + const targetTools = triggerPlugins || [] toolIcon = targetTools.find(toolWithProvider => canFindTool(toolWithProvider.id, nodeData.provider_id!))?.icon } - if (typeof toolIcon === 'string') { - const iconUrl = toolIcon.startsWith('http') ? toolIcon : getIconUrl(toolIcon) - icon = ( -
- ) - } - else if (toolIcon && typeof toolIcon === 'object' && 'content' in toolIcon) { - icon = ( - - ) - } - else { - icon = ( -
- P -
- ) - } + const icon = ( + + ) allTriggers.push({ id: node.id, @@ -139,9 +108,10 @@ export const useDynamicTestRunOptions = (): TestRunOptions => { type: 'user_input', name: (startNode.data as CommonNodeType)?.title || t('workflow.blocks.start'), icon: ( -
- -
+ ), nodeId: startNode.id, enabled: true, @@ -166,5 +136,5 @@ export const useDynamicTestRunOptions = (): TestRunOptions => { triggers: allTriggers, runAll, } - }, [nodes, buildInTools, customTools, workflowTools, mcpTools, getIconUrl, t]) + }, [nodes, buildInTools, customTools, workflowTools, mcpTools, triggerPlugins, t]) }