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])
}