mirror of
https://github.com/langgenius/dify.git
synced 2026-06-21 01:41:08 +08:00
168 lines
5.3 KiB
TypeScript
168 lines
5.3 KiB
TypeScript
import type { FC } from 'react'
|
|
import type { StartPlaceholderNodeType } from './types'
|
|
import type {
|
|
PluginDefaultValue,
|
|
TriggerDefaultValue,
|
|
} from '@/app/components/workflow/block-selector/types'
|
|
import type { NodePanelProps } from '@/app/components/workflow/types'
|
|
import * as React from 'react'
|
|
import {
|
|
useCallback,
|
|
useState,
|
|
} from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { useStoreApi } from 'reactflow'
|
|
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
|
import AllStartBlocks from '@/app/components/workflow/block-selector/all-start-blocks'
|
|
import { useAutoGenerateWebhookUrl } from '@/app/components/workflow/hooks'
|
|
import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
|
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
|
|
import { useStore as useWorkflowStore } from '@/app/components/workflow/store'
|
|
import { BlockEnum } from '@/app/components/workflow/types'
|
|
|
|
const getTriggerPluginNodeData = (
|
|
triggerConfig: TriggerDefaultValue,
|
|
fallbackTitle?: string,
|
|
fallbackDesc?: string,
|
|
) => {
|
|
return {
|
|
plugin_id: triggerConfig.plugin_id,
|
|
provider_id: triggerConfig.provider_name,
|
|
provider_type: triggerConfig.provider_type,
|
|
provider_name: triggerConfig.provider_name,
|
|
event_name: triggerConfig.event_name,
|
|
event_label: triggerConfig.event_label,
|
|
event_description: triggerConfig.event_description,
|
|
title: triggerConfig.event_label || triggerConfig.title || fallbackTitle,
|
|
desc: triggerConfig.event_description || fallbackDesc,
|
|
output_schema: { ...triggerConfig.output_schema },
|
|
parameters_schema: triggerConfig.paramSchemas ? [...triggerConfig.paramSchemas] : [],
|
|
config: { ...triggerConfig.params },
|
|
subscription_id: triggerConfig.subscription_id,
|
|
plugin_unique_identifier: triggerConfig.plugin_unique_identifier,
|
|
is_team_authorization: triggerConfig.is_team_authorization,
|
|
meta: triggerConfig.meta ? { ...triggerConfig.meta } : undefined,
|
|
}
|
|
}
|
|
|
|
const Panel: FC<NodePanelProps<StartPlaceholderNodeType>> = ({
|
|
id,
|
|
}) => {
|
|
const { t } = useTranslation()
|
|
const [searchText, setSearchText] = useState('')
|
|
const [tags, setTags] = useState<string[]>([])
|
|
const availableNodesMetaData = useHooksStore(s => s.availableNodesMetaData)
|
|
const setHasSelectedStartNode = useWorkflowStore(s => s.setHasSelectedStartNode)
|
|
const setShouldAutoOpenStartNodeSelector = useWorkflowStore(s => s.setShouldAutoOpenStartNodeSelector)
|
|
const reactFlowStore = useStoreApi()
|
|
const autoGenerateWebhookUrl = useAutoGenerateWebhookUrl()
|
|
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
|
|
|
const handleSelectStartNode = useCallback((nodeType: BlockEnum, toolConfig?: PluginDefaultValue) => {
|
|
const nodeDefault = availableNodesMetaData?.nodesMap?.[nodeType]
|
|
if (!nodeDefault?.defaultValue)
|
|
return
|
|
|
|
const baseNodeData = { ...nodeDefault.defaultValue }
|
|
const mergedNodeData = (() => {
|
|
if (nodeType !== BlockEnum.TriggerPlugin || !toolConfig) {
|
|
return {
|
|
...baseNodeData,
|
|
...toolConfig,
|
|
}
|
|
}
|
|
|
|
const triggerNodeData = getTriggerPluginNodeData(
|
|
toolConfig as TriggerDefaultValue,
|
|
baseNodeData.title,
|
|
baseNodeData.desc,
|
|
)
|
|
|
|
return {
|
|
...baseNodeData,
|
|
...triggerNodeData,
|
|
config: {
|
|
...(baseNodeData as { config?: Record<string, unknown> }).config,
|
|
...triggerNodeData.config,
|
|
},
|
|
}
|
|
})()
|
|
|
|
const { getNodes, setNodes } = reactFlowStore.getState()
|
|
const nextNodes = getNodes().map((node) => {
|
|
if (node.id !== id) {
|
|
return {
|
|
...node,
|
|
data: {
|
|
...node.data,
|
|
selected: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
return {
|
|
...node,
|
|
data: {
|
|
...mergedNodeData,
|
|
type: nodeType,
|
|
selected: true,
|
|
},
|
|
}
|
|
})
|
|
|
|
setNodes(nextNodes)
|
|
setHasSelectedStartNode?.(true)
|
|
setShouldAutoOpenStartNodeSelector?.(true)
|
|
|
|
handleSyncWorkflowDraft(true, false, {
|
|
onSuccess: () => {
|
|
autoGenerateWebhookUrl(id)
|
|
},
|
|
onError: () => {
|
|
console.error('Failed to save start node selection to draft')
|
|
},
|
|
})
|
|
}, [
|
|
autoGenerateWebhookUrl,
|
|
availableNodesMetaData?.nodesMap,
|
|
handleSyncWorkflowDraft,
|
|
id,
|
|
reactFlowStore,
|
|
setHasSelectedStartNode,
|
|
setShouldAutoOpenStartNodeSelector,
|
|
])
|
|
|
|
return (
|
|
<div className="flex h-full min-h-0 flex-col">
|
|
<div className="px-3 py-2">
|
|
<SearchBox
|
|
search={searchText}
|
|
onSearchChange={setSearchText}
|
|
tags={tags}
|
|
onTagsChange={setTags}
|
|
placeholder={t('tabs.searchTrigger', { ns: 'workflow' })}
|
|
inputClassName="grow"
|
|
/>
|
|
</div>
|
|
<div className="min-h-0 flex-1 overflow-hidden">
|
|
<AllStartBlocks
|
|
className="max-w-none min-w-0"
|
|
searchText={searchText}
|
|
onSelect={handleSelectStartNode}
|
|
availableBlocksTypes={[
|
|
BlockEnum.Start,
|
|
BlockEnum.TriggerSchedule,
|
|
BlockEnum.TriggerWebhook,
|
|
BlockEnum.TriggerPlugin,
|
|
]}
|
|
tags={tags}
|
|
allowUserInputSelection
|
|
variant="panel"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default React.memo(Panel)
|