feat: add specialized trigger icons to workflow logs

- Create TriggerByDisplay component with appropriate colored icons
- Add dedicated Code icon for debugging triggers (blue background)
- Add KnowledgeRetrieval icon for RAG pipeline triggers (green background)
- Use existing webhook, schedule, and plugin icons with proper colors
- Add comprehensive i18n translations for Chinese, Japanese, and English
- Integrate icon display into workflow logs table
- Follow project color standards from block-icon component
This commit is contained in:
lyzno1
2025-09-29 12:46:49 +08:00
parent 2c3cf9a25e
commit 4b43196295
5 changed files with 141 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ArrowDownIcon } from '@heroicons/react/24/outline'
import DetailPanel from './detail'
import TriggerByDisplay from './trigger-by-display'
import type { WorkflowAppLogDetail, WorkflowLogsResponse } from '@/models/log'
import type { App } from '@/types/app'
import Loading from '@/app/components/base/loading'
@@ -159,7 +160,11 @@ const WorkflowAppLogList: FC<ILogs> = ({ logs, appDetail, onRefresh }) => {
{endUser}
</div>
</td>
{isWorkflow && <td className='p-3 pr-2'>{log.workflow_run.triggered_from}</td>}
{isWorkflow && (
<td className='p-3 pr-2'>
<TriggerByDisplay triggeredFrom={log.workflow_run.triggered_from || 'app-run'} />
</td>
)}
</tr>
})}
</tbody>

View File

@@ -0,0 +1,106 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import {
Code,
KnowledgeRetrieval,
Schedule,
WebhookLine,
WindowCursor,
} from '@/app/components/base/icons/src/vender/workflow'
import BlockIcon from '@/app/components/workflow/block-icon'
import { BlockEnum } from '@/app/components/workflow/types'
type TriggerByDisplayProps = {
triggeredFrom: string
className?: string
showText?: boolean
}
const getTriggerDisplayName = (triggeredFrom: string, t: any) => {
const nameMap: Record<string, string> = {
'debugging': t('appLog.triggerBy.debugging'),
'app-run': t('appLog.triggerBy.appRun'),
'webhook': t('appLog.triggerBy.webhook'),
'schedule': t('appLog.triggerBy.schedule'),
'plugin': t('appLog.triggerBy.plugin'),
'rag-pipeline-run': t('appLog.triggerBy.ragPipelineRun'),
'rag-pipeline-debugging': t('appLog.triggerBy.ragPipelineDebugging'),
}
return nameMap[triggeredFrom] || triggeredFrom
}
const getTriggerIcon = (triggeredFrom: string) => {
switch (triggeredFrom) {
case 'webhook':
return (
<div className='rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-blue-500 p-1 shadow-md'>
<WebhookLine className='h-4 w-4 text-text-primary-on-surface' />
</div>
)
case 'schedule':
return (
<div className='rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-500 p-1 shadow-md'>
<Schedule className='h-4 w-4 text-text-primary-on-surface' />
</div>
)
case 'plugin':
// For plugin triggers in logs, use a generic plugin icon since we don't have specific plugin info
// This matches the standard BlockIcon styling for TriggerPlugin
return (
<BlockIcon
type={BlockEnum.TriggerPlugin}
size="md"
/>
)
case 'debugging':
return (
<div className='rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-blue-500 p-1 shadow-md'>
<Code className='h-4 w-4 text-text-primary-on-surface' />
</div>
)
case 'rag-pipeline-run':
case 'rag-pipeline-debugging':
return (
<div className='rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-green-green-500 p-1 shadow-md'>
<KnowledgeRetrieval className='h-4 w-4 text-text-primary-on-surface' />
</div>
)
case 'app-run':
default:
// For user input types (app-run, etc.), use webapp icon
return (
<div className='rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-blue-brand-blue-brand-500 p-1 shadow-md'>
<WindowCursor className='h-4 w-4 text-text-primary-on-surface' />
</div>
)
}
}
const TriggerByDisplay: FC<TriggerByDisplayProps> = ({
triggeredFrom,
className = '',
showText = true,
}) => {
const { t } = useTranslation()
const displayName = getTriggerDisplayName(triggeredFrom, t)
const icon = getTriggerIcon(triggeredFrom)
return (
<div className={`flex items-center gap-1.5 ${className}`}>
<div className="flex items-center justify-center">
{icon}
</div>
{showText && (
<span className="system-sm-regular text-text-secondary">
{displayName}
</span>
)}
</div>
)
}
export default TriggerByDisplay

View File

@@ -95,6 +95,15 @@ const translation = {
iteration: 'Iteration',
finalProcessing: 'Final Processing',
},
triggerBy: {
debugging: 'Debugging',
appRun: 'WebApp',
webhook: 'Webhook',
schedule: 'Schedule',
plugin: 'Plugin',
ragPipelineRun: 'RAG Pipeline',
ragPipelineDebugging: 'RAG Debugging',
},
}
export default translation

View File

@@ -20,6 +20,7 @@ const translation = {
tokens: 'トークン',
user: 'エンドユーザーまたはアカウント',
version: 'バージョン',
triggered_from: 'トリガー方法',
},
pagination: {
previous: '前へ',
@@ -94,6 +95,15 @@ const translation = {
iteration: '反復',
finalProcessing: '最終処理',
},
triggerBy: {
debugging: 'デバッグ',
appRun: 'ウェブアプリ',
webhook: 'Webhook',
schedule: 'スケジュール',
plugin: 'プラグイン',
ragPipelineRun: 'RAGパイプライン',
ragPipelineDebugging: 'RAGデバッグ',
},
}
export default translation

View File

@@ -20,6 +20,7 @@ const translation = {
tokens: 'TOKENS',
user: '用户或账户',
version: '版本',
triggered_from: '触发方式',
},
pagination: {
previous: '上一页',
@@ -94,6 +95,15 @@ const translation = {
iteration: '迭代',
finalProcessing: '最终处理',
},
triggerBy: {
debugging: '调试',
appRun: '网页应用',
webhook: 'Webhook',
schedule: '定时任务',
plugin: '插件',
ragPipelineRun: 'RAG 流水线',
ragPipelineDebugging: 'RAG 调试',
},
}
export default translation