mirror of https://github.com/langgenius/dify.git
feat(trigger): implement trigger plugin block selector following tools pattern (#25204)
This commit is contained in:
parent
d8f6f9ce19
commit
9f8c159583
|
|
@ -1,18 +1,18 @@
|
|||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import type { ToolWithProvider } from '../../types'
|
||||
import type { TriggerWithProvider } from '../types'
|
||||
import type { Tool } from '@/app/components/tools/types'
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { ToolDefaultValue } from '../types'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import type { Tool } from '@/app/components/tools/types'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import BlockIcon from '../../block-icon'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type Props = {
|
||||
provider: ToolWithProvider
|
||||
provider: TriggerWithProvider
|
||||
payload: Tool
|
||||
disabled?: boolean
|
||||
isAdded?: boolean
|
||||
|
|
@ -55,20 +55,20 @@ const TriggerPluginActionItem: FC<Props> = ({
|
|||
if (disabled) return
|
||||
const params: Record<string, string> = {}
|
||||
if (payload.parameters) {
|
||||
payload.parameters.forEach((item) => {
|
||||
payload.parameters.forEach((item: any) => {
|
||||
params[item.name] = ''
|
||||
})
|
||||
}
|
||||
onSelect(BlockEnum.TriggerPlugin, {
|
||||
provider_id: provider.id,
|
||||
provider_type: provider.type,
|
||||
provider_type: provider.type as string,
|
||||
provider_name: provider.name,
|
||||
tool_name: payload.name,
|
||||
tool_label: payload.label[language],
|
||||
tool_description: payload.description[language],
|
||||
title: payload.label[language],
|
||||
is_team_authorization: provider.is_team_authorization,
|
||||
output_schema: payload.output_schema,
|
||||
output_schema: payload.output_schema || {},
|
||||
paramSchemas: payload.parameters,
|
||||
params,
|
||||
meta: provider.meta,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import cn from '@/utils/classnames'
|
|||
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import { CollectionType } from '../../../tools/types'
|
||||
import type { ToolWithProvider } from '../../types'
|
||||
import type { TriggerWithProvider } from '../types'
|
||||
import { BlockEnum } from '../../types'
|
||||
import type { ToolDefaultValue } from '../types'
|
||||
import TriggerPluginActionItem from './action-item'
|
||||
|
|
@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next'
|
|||
|
||||
type Props = {
|
||||
className?: string
|
||||
payload: ToolWithProvider
|
||||
payload: TriggerWithProvider
|
||||
hasSearchText: boolean
|
||||
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ const TriggerPluginItem: FC<Props> = ({
|
|||
if (payload.type === CollectionType.workflow)
|
||||
return t('workflow.tabs.workflowTool')
|
||||
|
||||
return ''
|
||||
return payload.author || ''
|
||||
}, [payload.author, payload.type, t])
|
||||
|
||||
return (
|
||||
|
|
@ -88,7 +88,7 @@ const TriggerPluginItem: FC<Props> = ({
|
|||
tool_description: tool.description[language],
|
||||
title: tool.label[language],
|
||||
is_team_authorization: payload.is_team_authorization,
|
||||
output_schema: tool.output_schema,
|
||||
output_schema: tool.output_schema || {},
|
||||
paramSchemas: tool.parameters,
|
||||
params,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
import { memo, useEffect, useMemo } from 'react'
|
||||
import { useAllBuiltInTools } from '@/service/use-tools'
|
||||
import { useAllTriggerPlugins } from '@/service/use-triggers'
|
||||
import TriggerPluginItem from './item'
|
||||
import type { BlockEnum } from '../../types'
|
||||
import type { ToolDefaultValue } from '../types'
|
||||
|
|
@ -19,11 +19,12 @@ const TriggerPluginList = ({
|
|||
onContentStateChange,
|
||||
tags = [],
|
||||
}: TriggerPluginListProps) => {
|
||||
const { data: buildInTools = [] } = useAllBuiltInTools()
|
||||
const { data: triggerPluginsData } = useAllTriggerPlugins()
|
||||
const language = useGetLanguage()
|
||||
|
||||
const triggerPlugins = useMemo(() => {
|
||||
return buildInTools.filter((toolWithProvider) => {
|
||||
// Follow exact same pattern as tools
|
||||
return (triggerPluginsData || []).filter((toolWithProvider) => {
|
||||
if (toolWithProvider.tools.length === 0) return false
|
||||
|
||||
// Filter by search text
|
||||
|
|
@ -37,7 +38,7 @@ const TriggerPluginList = ({
|
|||
|
||||
return true
|
||||
})
|
||||
}, [buildInTools, searchText, language])
|
||||
}, [triggerPluginsData, searchText, language])
|
||||
|
||||
const hasContent = triggerPlugins.length > 0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import type { PluginMeta } from '../../plugins/types'
|
||||
import type { Collection, Tool } from '../../tools/types'
|
||||
import type { TypeWithI18N } from '../../base/form/types'
|
||||
|
||||
export enum TabsEnum {
|
||||
Start = 'start',
|
||||
|
|
@ -50,3 +52,51 @@ export type ToolValue = {
|
|||
extra?: Record<string, any>
|
||||
credential_id?: string
|
||||
}
|
||||
|
||||
// Backend API types - exact match with Python definitions
|
||||
export type TriggerParameter = {
|
||||
name: string
|
||||
label: TypeWithI18N
|
||||
description?: TypeWithI18N
|
||||
type: string
|
||||
required?: boolean
|
||||
default?: any
|
||||
}
|
||||
|
||||
export type TriggerIdentity = {
|
||||
author: string
|
||||
name: string
|
||||
version: string
|
||||
}
|
||||
|
||||
export type TriggerDescription = {
|
||||
human: TypeWithI18N
|
||||
llm: TypeWithI18N
|
||||
}
|
||||
|
||||
export type TriggerApiEntity = {
|
||||
name: string
|
||||
identity: TriggerIdentity
|
||||
description: TriggerDescription
|
||||
parameters: TriggerParameter[]
|
||||
output_schema?: Record<string, any>
|
||||
}
|
||||
|
||||
export type TriggerProviderApiEntity = {
|
||||
author: string
|
||||
name: string
|
||||
label: TypeWithI18N
|
||||
description: TypeWithI18N
|
||||
icon?: string
|
||||
icon_dark?: string
|
||||
tags: string[]
|
||||
plugin_id?: string
|
||||
plugin_unique_identifier?: string
|
||||
triggers: TriggerApiEntity[]
|
||||
}
|
||||
|
||||
// Frontend types - compatible with ToolWithProvider
|
||||
export type TriggerWithProvider = Collection & {
|
||||
tools: Tool[] // Use existing Tool type for compatibility
|
||||
meta: PluginMeta
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,74 @@
|
|||
import { useQuery } from '@tanstack/react-query'
|
||||
import { get } from './base'
|
||||
import type { ToolWithProvider } from '@/app/components/workflow/types'
|
||||
import type { TriggerProviderApiEntity, TriggerWithProvider } from '@/app/components/workflow/block-selector/types'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
|
||||
const NAME_SPACE = 'triggers'
|
||||
|
||||
// Get all plugins that support trigger functionality
|
||||
// TODO: Backend API not implemented yet - replace with actual triggers endpoint
|
||||
// Convert backend API response to frontend ToolWithProvider format
|
||||
const convertToTriggerWithProvider = (provider: TriggerProviderApiEntity): TriggerWithProvider => {
|
||||
return {
|
||||
// Collection fields
|
||||
id: provider.plugin_id || provider.name,
|
||||
name: provider.name,
|
||||
author: provider.author,
|
||||
description: provider.description, // Already TypeWithI18N format
|
||||
icon: provider.icon || '',
|
||||
label: provider.label, // Already TypeWithI18N format
|
||||
type: CollectionType.builtIn,
|
||||
team_credentials: {},
|
||||
is_team_authorization: false,
|
||||
allow_delete: false,
|
||||
labels: provider.tags || [],
|
||||
plugin_id: provider.plugin_id,
|
||||
|
||||
// ToolWithProvider fields - convert "triggers" to "tools"
|
||||
tools: provider.triggers.map(trigger => ({
|
||||
name: trigger.name,
|
||||
author: provider.author,
|
||||
label: trigger.description.human, // Already TypeWithI18N format
|
||||
description: trigger.description.llm, // Already TypeWithI18N format
|
||||
parameters: trigger.parameters.map(param => ({
|
||||
name: param.name,
|
||||
label: param.label, // Already TypeWithI18N format
|
||||
human_description: param.description || param.label,
|
||||
type: param.type,
|
||||
form: param.type,
|
||||
llm_description: JSON.stringify(param.description || {}),
|
||||
required: param.required || false,
|
||||
default: param.default || '',
|
||||
options: [],
|
||||
})),
|
||||
labels: provider.tags || [],
|
||||
output_schema: trigger.output_schema || {},
|
||||
})),
|
||||
|
||||
meta: {
|
||||
version: '1.0',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Main hook - follows exact same pattern as tools
|
||||
export const useAllTriggerPlugins = (enabled = true) => {
|
||||
return useQuery<ToolWithProvider[]>({
|
||||
return useQuery<TriggerWithProvider[]>({
|
||||
queryKey: [NAME_SPACE, 'all'],
|
||||
queryFn: () => get<ToolWithProvider[]>('/workspaces/current/triggers/plugins'),
|
||||
queryFn: async () => {
|
||||
const response = await get<TriggerProviderApiEntity[]>('/workspaces/current/triggers')
|
||||
return response.map(convertToTriggerWithProvider)
|
||||
},
|
||||
enabled,
|
||||
})
|
||||
}
|
||||
|
||||
// Get trigger-capable plugins by type (schedule, webhook, etc.)
|
||||
// TODO: Backend API not implemented yet - replace with actual triggers endpoint
|
||||
// Additional hook for consistency with tools pattern
|
||||
export const useTriggerPluginsByType = (triggerType: string, enabled = true) => {
|
||||
return useQuery<ToolWithProvider[]>({
|
||||
return useQuery<TriggerWithProvider[]>({
|
||||
queryKey: [NAME_SPACE, 'byType', triggerType],
|
||||
queryFn: () => get<ToolWithProvider[]>(`/workspaces/current/triggers/plugins?type=${triggerType}`),
|
||||
queryFn: async () => {
|
||||
const response = await get<TriggerProviderApiEntity[]>(`/workspaces/current/triggers?type=${triggerType}`)
|
||||
return response.map(convertToTriggerWithProvider)
|
||||
},
|
||||
enabled: enabled && !!triggerType,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue