mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
block selector & data source node
This commit is contained in:
@ -109,7 +109,7 @@ const Blocks = ({
|
|||||||
}, [groups, nodesExtraData, onSelect, t])
|
}, [groups, nodesExtraData, onSelect, t])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='p-1'>
|
<div className='max-h-[480px] overflow-y-auto p-1'>
|
||||||
{
|
{
|
||||||
isEmpty && (
|
isEmpty && (
|
||||||
<div className='flex h-[22px] items-center px-3 text-xs font-medium text-text-tertiary'>{t('workflow.tabs.noResult')}</div>
|
<div className='flex h-[22px] items-center px-3 text-xs font-medium text-text-tertiary'>{t('workflow.tabs.noResult')}</div>
|
||||||
|
|||||||
@ -3,6 +3,12 @@ import { BlockEnum } from '../types'
|
|||||||
import { BlockClassificationEnum } from './types'
|
import { BlockClassificationEnum } from './types'
|
||||||
|
|
||||||
export const BLOCKS: Block[] = [
|
export const BLOCKS: Block[] = [
|
||||||
|
{
|
||||||
|
classification: BlockClassificationEnum.Default,
|
||||||
|
type: BlockEnum.DataSource,
|
||||||
|
title: 'File upload',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
classification: BlockClassificationEnum.Default,
|
classification: BlockClassificationEnum.Default,
|
||||||
type: BlockEnum.Start,
|
type: BlockEnum.Start,
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
import {
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { BLOCKS } from './constants'
|
import { BLOCKS } from './constants'
|
||||||
import {
|
import {
|
||||||
@ -16,19 +20,43 @@ export const useBlocks = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useTabs = () => {
|
export const useTabs = (noBlocks?: boolean) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const tabs = useMemo(() => {
|
||||||
|
return [
|
||||||
|
...(
|
||||||
|
noBlocks
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
key: TabsEnum.Blocks,
|
||||||
|
name: t('workflow.tabs.blocks'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
),
|
||||||
|
{
|
||||||
|
key: TabsEnum.Sources,
|
||||||
|
name: t('workflow.tabs.sources'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: TabsEnum.Tools,
|
||||||
|
name: t('workflow.tabs.tools'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}, [t, noBlocks])
|
||||||
|
const initialTab = useMemo(() => {
|
||||||
|
if (noBlocks)
|
||||||
|
return TabsEnum.Sources
|
||||||
|
|
||||||
return [
|
return TabsEnum.Blocks
|
||||||
{
|
}, [noBlocks])
|
||||||
key: TabsEnum.Blocks,
|
const [activeTab, setActiveTab] = useState(initialTab)
|
||||||
name: t('workflow.tabs.blocks'),
|
|
||||||
},
|
return {
|
||||||
{
|
tabs,
|
||||||
key: TabsEnum.Tools,
|
activeTab,
|
||||||
name: t('workflow.tabs.tools'),
|
setActiveTab,
|
||||||
},
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useToolTabs = () => {
|
export const useToolTabs = () => {
|
||||||
|
|||||||
@ -16,13 +16,15 @@ import type {
|
|||||||
import type { BlockEnum, OnSelectBlock } from '../types'
|
import type { BlockEnum, OnSelectBlock } from '../types'
|
||||||
import Tabs from './tabs'
|
import Tabs from './tabs'
|
||||||
import { TabsEnum } from './types'
|
import { TabsEnum } from './types'
|
||||||
|
import { useTabs } from './hooks'
|
||||||
import {
|
import {
|
||||||
PortalToFollowElem,
|
PortalToFollowElem,
|
||||||
PortalToFollowElemContent,
|
PortalToFollowElemContent,
|
||||||
PortalToFollowElemTrigger,
|
PortalToFollowElemTrigger,
|
||||||
} from '@/app/components/base/portal-to-follow-elem'
|
} from '@/app/components/base/portal-to-follow-elem'
|
||||||
import Input from '@/app/components/base/input'
|
import Input from '@/app/components/base/input'
|
||||||
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
// import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Plus02,
|
Plus02,
|
||||||
@ -85,10 +87,12 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
onSelect(type, toolDefaultValue)
|
onSelect(type, toolDefaultValue)
|
||||||
}, [handleOpenChange, onSelect])
|
}, [handleOpenChange, onSelect])
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState(noBlocks ? TabsEnum.Tools : TabsEnum.Blocks)
|
const {
|
||||||
const handleActiveTabChange = useCallback((newActiveTab: TabsEnum) => {
|
activeTab,
|
||||||
setActiveTab(newActiveTab)
|
setActiveTab,
|
||||||
}, [])
|
tabs,
|
||||||
|
} = useTabs()
|
||||||
|
|
||||||
const searchPlaceholder = useMemo(() => {
|
const searchPlaceholder = useMemo(() => {
|
||||||
if (activeTab === TabsEnum.Blocks)
|
if (activeTab === TabsEnum.Blocks)
|
||||||
return t('workflow.tabs.searchBlock')
|
return t('workflow.tabs.searchBlock')
|
||||||
@ -128,9 +132,31 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
}
|
}
|
||||||
</PortalToFollowElemTrigger>
|
</PortalToFollowElemTrigger>
|
||||||
<PortalToFollowElemContent className='z-[1000]'>
|
<PortalToFollowElemContent className='z-[1000]'>
|
||||||
<div className={`rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg ${popupClassName}`}>
|
<div className={cn(
|
||||||
<div className='px-2 pt-2' onClick={e => e.stopPropagation()}>
|
'overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg backdrop-blur-[5px]',
|
||||||
{activeTab === TabsEnum.Blocks && (
|
popupClassName,
|
||||||
|
)}>
|
||||||
|
<div className='border-b border-divider-subtle bg-background-section-burn'>
|
||||||
|
<div className='flex h-9 items-center px-1 pt-1'>
|
||||||
|
{
|
||||||
|
tabs.map(tab => (
|
||||||
|
<div
|
||||||
|
key={tab.key}
|
||||||
|
className={cn(
|
||||||
|
'system-sm-medium mr-0.5 cursor-pointer rounded-t-lg px-3 py-2 text-text-tertiary hover:bg-state-base-hover',
|
||||||
|
activeTab === tab.key && 'bg-components-panel-bg text-text-accent shadow-sm',
|
||||||
|
)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setActiveTab(tab.key)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tab.name}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className='relative z-[1] bg-components-panel-bg p-2'>
|
||||||
<Input
|
<Input
|
||||||
showLeftIcon
|
showLeftIcon
|
||||||
showClearIcon
|
showClearIcon
|
||||||
@ -140,6 +166,10 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
onChange={e => setSearchText(e.target.value)}
|
onChange={e => setSearchText(e.target.value)}
|
||||||
onClear={() => setSearchText('')}
|
onClear={() => setSearchText('')}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <div className='p-2' onClick={e => e.stopPropagation()}>
|
||||||
|
{activeTab === TabsEnum.Blocks && (
|
||||||
)}
|
)}
|
||||||
{activeTab === TabsEnum.Tools && (
|
{activeTab === TabsEnum.Tools && (
|
||||||
<SearchBox
|
<SearchBox
|
||||||
@ -151,11 +181,9 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
placeholder={t('plugin.searchTools')!}
|
placeholder={t('plugin.searchTools')!}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
</div> */}
|
||||||
</div>
|
|
||||||
<Tabs
|
<Tabs
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
onActiveTabChange={handleActiveTabChange}
|
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
searchText={searchText}
|
searchText={searchText}
|
||||||
tags={tags}
|
tags={tags}
|
||||||
|
|||||||
@ -2,16 +2,13 @@ import type { FC } from 'react'
|
|||||||
import { memo } from 'react'
|
import { memo } from 'react'
|
||||||
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools'
|
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools'
|
||||||
import type { BlockEnum } from '../types'
|
import type { BlockEnum } from '../types'
|
||||||
import { useTabs } from './hooks'
|
|
||||||
import type { ToolDefaultValue } from './types'
|
import type { ToolDefaultValue } from './types'
|
||||||
import { TabsEnum } from './types'
|
import { TabsEnum } from './types'
|
||||||
import Blocks from './blocks'
|
import Blocks from './blocks'
|
||||||
import AllTools from './all-tools'
|
import AllTools from './all-tools'
|
||||||
import cn from '@/utils/classnames'
|
|
||||||
|
|
||||||
export type TabsProps = {
|
export type TabsProps = {
|
||||||
activeTab: TabsEnum
|
activeTab: TabsEnum
|
||||||
onActiveTabChange: (activeTab: TabsEnum) => void
|
|
||||||
searchText: string
|
searchText: string
|
||||||
tags: string[]
|
tags: string[]
|
||||||
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
||||||
@ -20,42 +17,18 @@ export type TabsProps = {
|
|||||||
}
|
}
|
||||||
const Tabs: FC<TabsProps> = ({
|
const Tabs: FC<TabsProps> = ({
|
||||||
activeTab,
|
activeTab,
|
||||||
onActiveTabChange,
|
|
||||||
tags,
|
tags,
|
||||||
searchText,
|
searchText,
|
||||||
onSelect,
|
onSelect,
|
||||||
availableBlocksTypes,
|
availableBlocksTypes,
|
||||||
noBlocks,
|
noBlocks,
|
||||||
}) => {
|
}) => {
|
||||||
const tabs = useTabs()
|
|
||||||
const { data: buildInTools } = useAllBuiltInTools()
|
const { data: buildInTools } = useAllBuiltInTools()
|
||||||
const { data: customTools } = useAllCustomTools()
|
const { data: customTools } = useAllCustomTools()
|
||||||
const { data: workflowTools } = useAllWorkflowTools()
|
const { data: workflowTools } = useAllWorkflowTools()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={e => e.stopPropagation()}>
|
<div onClick={e => e.stopPropagation()}>
|
||||||
{
|
|
||||||
!noBlocks && (
|
|
||||||
<div className='flex items-center border-b-[0.5px] border-divider-subtle px-3'>
|
|
||||||
{
|
|
||||||
tabs.map(tab => (
|
|
||||||
<div
|
|
||||||
key={tab.key}
|
|
||||||
className={cn(
|
|
||||||
'system-sm-medium relative mr-4 cursor-pointer pb-2 pt-1',
|
|
||||||
activeTab === tab.key
|
|
||||||
? 'text-text-primary after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:bg-util-colors-blue-brand-blue-brand-600'
|
|
||||||
: 'text-text-tertiary',
|
|
||||||
)}
|
|
||||||
onClick={() => onActiveTabChange(tab.key)}
|
|
||||||
>
|
|
||||||
{tab.name}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
activeTab === TabsEnum.Blocks && !noBlocks && (
|
activeTab === TabsEnum.Blocks && !noBlocks && (
|
||||||
<Blocks
|
<Blocks
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export enum TabsEnum {
|
export enum TabsEnum {
|
||||||
Blocks = 'blocks',
|
Blocks = 'blocks',
|
||||||
Tools = 'tools',
|
Tools = 'tools',
|
||||||
|
Sources = 'sources',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ToolTypeEnum {
|
export enum ToolTypeEnum {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import IterationStartDefault from './nodes/iteration-start/default'
|
|||||||
import AgentDefault from './nodes/agent/default'
|
import AgentDefault from './nodes/agent/default'
|
||||||
import LoopStartDefault from './nodes/loop-start/default'
|
import LoopStartDefault from './nodes/loop-start/default'
|
||||||
import LoopEndDefault from './nodes/loop-end/default'
|
import LoopEndDefault from './nodes/loop-end/default'
|
||||||
|
import DataSourceDefault from './nodes/data-source/default'
|
||||||
|
|
||||||
type NodesExtraData = {
|
type NodesExtraData = {
|
||||||
author: string
|
author: string
|
||||||
@ -33,6 +34,15 @@ type NodesExtraData = {
|
|||||||
checkValid: any
|
checkValid: any
|
||||||
}
|
}
|
||||||
export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
||||||
|
[BlockEnum.DataSource]: {
|
||||||
|
author: 'Dify',
|
||||||
|
about: '',
|
||||||
|
availablePrevNodes: [],
|
||||||
|
availableNextNodes: [],
|
||||||
|
getAvailablePrevNodes: DataSourceDefault.getAvailablePrevNodes,
|
||||||
|
getAvailableNextNodes: DataSourceDefault.getAvailableNextNodes,
|
||||||
|
checkValid: DataSourceDefault.checkValid,
|
||||||
|
},
|
||||||
[BlockEnum.Start]: {
|
[BlockEnum.Start]: {
|
||||||
author: 'Dify',
|
author: 'Dify',
|
||||||
about: '',
|
about: '',
|
||||||
@ -243,6 +253,12 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const NODES_INITIAL_DATA = {
|
export const NODES_INITIAL_DATA = {
|
||||||
|
[BlockEnum.DataSource]: {
|
||||||
|
type: BlockEnum.DataSource,
|
||||||
|
title: '',
|
||||||
|
desc: '',
|
||||||
|
...DataSourceDefault.defaultValue,
|
||||||
|
},
|
||||||
[BlockEnum.Start]: {
|
[BlockEnum.Start]: {
|
||||||
type: BlockEnum.Start,
|
type: BlockEnum.Start,
|
||||||
title: '',
|
title: '',
|
||||||
|
|||||||
@ -25,11 +25,8 @@ import {
|
|||||||
useStore,
|
useStore,
|
||||||
useWorkflowStore,
|
useWorkflowStore,
|
||||||
} from '../store'
|
} from '../store'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getParallelInfo,
|
|
||||||
} from '../utils'
|
|
||||||
import {
|
|
||||||
PARALLEL_DEPTH_LIMIT,
|
|
||||||
PARALLEL_LIMIT,
|
PARALLEL_LIMIT,
|
||||||
SUPPORT_OUTPUT_VARS_NODE,
|
SUPPORT_OUTPUT_VARS_NODE,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
@ -323,24 +320,24 @@ export const useWorkflow = () => {
|
|||||||
}, [store, workflowStore, t])
|
}, [store, workflowStore, t])
|
||||||
|
|
||||||
const checkNestedParallelLimit = useCallback((nodes: Node[], edges: Edge[], parentNodeId?: string) => {
|
const checkNestedParallelLimit = useCallback((nodes: Node[], edges: Edge[], parentNodeId?: string) => {
|
||||||
const {
|
// const {
|
||||||
parallelList,
|
// parallelList,
|
||||||
hasAbnormalEdges,
|
// hasAbnormalEdges,
|
||||||
} = getParallelInfo(nodes, edges, parentNodeId)
|
// } = getParallelInfo(nodes, edges, parentNodeId)
|
||||||
const { workflowConfig } = workflowStore.getState()
|
// const { workflowConfig } = workflowStore.getState()
|
||||||
|
|
||||||
if (hasAbnormalEdges)
|
// if (hasAbnormalEdges)
|
||||||
return false
|
// return false
|
||||||
|
|
||||||
for (let i = 0; i < parallelList.length; i++) {
|
// for (let i = 0; i < parallelList.length; i++) {
|
||||||
const parallel = parallelList[i]
|
// const parallel = parallelList[i]
|
||||||
|
|
||||||
if (parallel.depth > (workflowConfig?.parallel_depth_limit || PARALLEL_DEPTH_LIMIT)) {
|
// if (parallel.depth > (workflowConfig?.parallel_depth_limit || PARALLEL_DEPTH_LIMIT)) {
|
||||||
const { setShowTips } = workflowStore.getState()
|
// const { setShowTips } = workflowStore.getState()
|
||||||
setShowTips(t('workflow.common.parallelTip.depthLimit', { num: (workflowConfig?.parallel_depth_limit || PARALLEL_DEPTH_LIMIT) }))
|
// setShowTips(t('workflow.common.parallelTip.depthLimit', { num: (workflowConfig?.parallel_depth_limit || PARALLEL_DEPTH_LIMIT) }))
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}, [t, workflowStore])
|
}, [t, workflowStore])
|
||||||
|
|||||||
@ -131,7 +131,7 @@ const BaseNode: FC<BaseNodeProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex rounded-2xl border-[2px]',
|
'relative flex rounded-2xl border',
|
||||||
showSelectedBorder ? 'border-components-option-card-option-selected-border' : 'border-transparent',
|
showSelectedBorder ? 'border-components-option-card-option-selected-border' : 'border-transparent',
|
||||||
!showSelectedBorder && data._inParallelHovering && 'border-workflow-block-border-highlight',
|
!showSelectedBorder && data._inParallelHovering && 'border-workflow-block-border-highlight',
|
||||||
data._waitingRun && 'opacity-70',
|
data._waitingRun && 'opacity-70',
|
||||||
@ -142,6 +142,15 @@ const BaseNode: FC<BaseNodeProps> = ({
|
|||||||
height: (data.type === BlockEnum.Iteration || data.type === BlockEnum.Loop) ? data.height : 'auto',
|
height: (data.type === BlockEnum.Iteration || data.type === BlockEnum.Loop) ? data.height : 'auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{
|
||||||
|
data.type === BlockEnum.DataSource && (
|
||||||
|
<div className='absolute inset-[-2px] top-[-22px] z-[-1] rounded-[18px] bg-node-data-source-bg p-0.5 backdrop-blur-[6px]'>
|
||||||
|
<div className='system-2xs-semibold-uppercase flex h-5 items-center px-2.5 text-text-tertiary'>
|
||||||
|
data source
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'group relative pb-1 shadow-xs',
|
'group relative pb-1 shadow-xs',
|
||||||
|
|||||||
@ -38,6 +38,8 @@ import ListFilterNode from './list-operator/node'
|
|||||||
import ListFilterPanel from './list-operator/panel'
|
import ListFilterPanel from './list-operator/panel'
|
||||||
import AgentNode from './agent/node'
|
import AgentNode from './agent/node'
|
||||||
import AgentPanel from './agent/panel'
|
import AgentPanel from './agent/panel'
|
||||||
|
import DataSourceNode from './data-source/node'
|
||||||
|
import DataSourcePanel from './data-source/panel'
|
||||||
import { TransferMethod } from '@/types/app'
|
import { TransferMethod } from '@/types/app'
|
||||||
|
|
||||||
export const NodeComponentMap: Record<string, ComponentType<any>> = {
|
export const NodeComponentMap: Record<string, ComponentType<any>> = {
|
||||||
@ -61,6 +63,7 @@ export const NodeComponentMap: Record<string, ComponentType<any>> = {
|
|||||||
[BlockEnum.DocExtractor]: DocExtractorNode,
|
[BlockEnum.DocExtractor]: DocExtractorNode,
|
||||||
[BlockEnum.ListFilter]: ListFilterNode,
|
[BlockEnum.ListFilter]: ListFilterNode,
|
||||||
[BlockEnum.Agent]: AgentNode,
|
[BlockEnum.Agent]: AgentNode,
|
||||||
|
[BlockEnum.DataSource]: DataSourceNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PanelComponentMap: Record<string, ComponentType<any>> = {
|
export const PanelComponentMap: Record<string, ComponentType<any>> = {
|
||||||
@ -84,6 +87,7 @@ export const PanelComponentMap: Record<string, ComponentType<any>> = {
|
|||||||
[BlockEnum.DocExtractor]: DocExtractorPanel,
|
[BlockEnum.DocExtractor]: DocExtractorPanel,
|
||||||
[BlockEnum.ListFilter]: ListFilterPanel,
|
[BlockEnum.ListFilter]: ListFilterPanel,
|
||||||
[BlockEnum.Agent]: AgentPanel,
|
[BlockEnum.Agent]: AgentPanel,
|
||||||
|
[BlockEnum.DataSource]: DataSourcePanel,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CUSTOM_NODE_TYPE = 'custom'
|
export const CUSTOM_NODE_TYPE = 'custom'
|
||||||
|
|||||||
27
web/app/components/workflow/nodes/data-source/default.ts
Normal file
27
web/app/components/workflow/nodes/data-source/default.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { BlockEnum } from '../../types'
|
||||||
|
import type { NodeDefault } from '../../types'
|
||||||
|
import type { DataSourceNodeType } from './types'
|
||||||
|
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
||||||
|
|
||||||
|
const nodeDefault: NodeDefault<DataSourceNodeType> = {
|
||||||
|
defaultValue: {
|
||||||
|
},
|
||||||
|
getAvailablePrevNodes(isChatMode: boolean) {
|
||||||
|
const nodes = isChatMode
|
||||||
|
? ALL_CHAT_AVAILABLE_BLOCKS
|
||||||
|
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
||||||
|
return nodes
|
||||||
|
},
|
||||||
|
getAvailableNextNodes(isChatMode: boolean) {
|
||||||
|
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
||||||
|
return nodes
|
||||||
|
},
|
||||||
|
checkValid() {
|
||||||
|
return {
|
||||||
|
isValid: true,
|
||||||
|
errorMessage: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default nodeDefault
|
||||||
13
web/app/components/workflow/nodes/data-source/node.tsx
Normal file
13
web/app/components/workflow/nodes/data-source/node.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type { FC } from 'react'
|
||||||
|
import { memo } from 'react'
|
||||||
|
import type { DataSourceNodeType } from './types'
|
||||||
|
import type { NodeProps } from '@/app/components/workflow/types'
|
||||||
|
const Node: FC<NodeProps<DataSourceNodeType>> = () => {
|
||||||
|
return (
|
||||||
|
<div className='mb-1 px-3 py-1'>
|
||||||
|
DataSource
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Node)
|
||||||
14
web/app/components/workflow/nodes/data-source/panel.tsx
Normal file
14
web/app/components/workflow/nodes/data-source/panel.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import type { FC } from 'react'
|
||||||
|
import { memo } from 'react'
|
||||||
|
import type { DataSourceNodeType } from './types'
|
||||||
|
import type { NodePanelProps } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
|
const Panel: FC<NodePanelProps<DataSourceNodeType>> = () => {
|
||||||
|
return (
|
||||||
|
<div className='mb-2 mt-2 space-y-4 px-4'>
|
||||||
|
datasource
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Panel)
|
||||||
3
web/app/components/workflow/nodes/data-source/types.ts
Normal file
3
web/app/components/workflow/nodes/data-source/types.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import type { CommonNodeType } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
|
export type DataSourceNodeType = CommonNodeType
|
||||||
@ -40,6 +40,7 @@ export enum BlockEnum {
|
|||||||
Loop = 'loop',
|
Loop = 'loop',
|
||||||
LoopStart = 'loop-start',
|
LoopStart = 'loop-start',
|
||||||
LoopEnd = 'loop-end',
|
LoopEnd = 'loop-end',
|
||||||
|
DataSource = 'data-source',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ControlMode {
|
export enum ControlMode {
|
||||||
|
|||||||
@ -229,6 +229,7 @@ const translation = {
|
|||||||
'utilities': 'Utilities',
|
'utilities': 'Utilities',
|
||||||
'noResult': 'No match found',
|
'noResult': 'No match found',
|
||||||
'agent': 'Agent Strategy',
|
'agent': 'Agent Strategy',
|
||||||
|
'sources': 'Sources',
|
||||||
},
|
},
|
||||||
blocks: {
|
blocks: {
|
||||||
'start': 'Start',
|
'start': 'Start',
|
||||||
|
|||||||
@ -230,6 +230,7 @@ const translation = {
|
|||||||
'utilities': '工具',
|
'utilities': '工具',
|
||||||
'noResult': '未找到匹配项',
|
'noResult': '未找到匹配项',
|
||||||
'agent': 'Agent 策略',
|
'agent': 'Agent 策略',
|
||||||
|
'sources': '数据源',
|
||||||
},
|
},
|
||||||
blocks: {
|
blocks: {
|
||||||
'start': '开始',
|
'start': '开始',
|
||||||
|
|||||||
@ -120,6 +120,7 @@ const config = {
|
|||||||
'price-premium-text-background': 'var(--color-premium-text-background)',
|
'price-premium-text-background': 'var(--color-premium-text-background)',
|
||||||
'price-enterprise-background': 'var(--color-price-enterprise-background)',
|
'price-enterprise-background': 'var(--color-price-enterprise-background)',
|
||||||
'grid-mask-background': 'var(--color-grid-mask-background)',
|
'grid-mask-background': 'var(--color-grid-mask-background)',
|
||||||
|
'node-data-source-bg': 'var(--color-node-data-source-bg)',
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
'spin-slow': 'spin 2s linear infinite',
|
'spin-slow': 'spin 2s linear infinite',
|
||||||
|
|||||||
@ -61,4 +61,9 @@ html[data-theme="dark"] {
|
|||||||
rgba(24, 24, 27, 0.08) 0%,
|
rgba(24, 24, 27, 0.08) 0%,
|
||||||
rgba(0, 0, 0, 0) 100%);
|
rgba(0, 0, 0, 0) 100%);
|
||||||
--color-line-divider-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.14) 0%, rgba(0, 0, 0, 0) 100%, );
|
--color-line-divider-bg: linear-gradient(90deg, rgba(200, 206, 218, 0.14) 0%, rgba(0, 0, 0, 0) 100%, );
|
||||||
|
--workflow-block-wrapper-bg-1: rgba(39, 39, 43, 1);
|
||||||
|
--workflow-block-wrapper-bg-2: rgba(39, 39, 43, 0.2);
|
||||||
|
--color-node-data-source-bg: linear-gradient(100deg, var(--workflow-block-wrapper-bg-1, #E9EBF0) 0%, var(--workflow-block-wrapper-bg-2, rgba(233, 235, 240, 0.20)) 100%);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -61,4 +61,7 @@ html[data-theme="light"] {
|
|||||||
rgba(200, 206, 218, 0.2) 0%,
|
rgba(200, 206, 218, 0.2) 0%,
|
||||||
rgba(255, 255, 255, 0) 100%);
|
rgba(255, 255, 255, 0) 100%);
|
||||||
--color-line-divider-bg: linear-gradient(90deg, rgba(16, 24, 40, 0.08) 0%, rgba(255, 255, 255, 0) 100%);
|
--color-line-divider-bg: linear-gradient(90deg, rgba(16, 24, 40, 0.08) 0%, rgba(255, 255, 255, 0) 100%);
|
||||||
|
--workflow-block-wrapper-bg-1: rgba(233, 235, 240, 1);
|
||||||
|
--workflow-block-wrapper-bg-2: rgba(233, 235, 240, 0.2);
|
||||||
|
--color-node-data-source-bg: linear-gradient(100deg, var(--workflow-block-wrapper-bg-1, #E9EBF0) 0%, var(--workflow-block-wrapper-bg-2, rgba(233, 235, 240, 0.20)) 100%);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user