mirror of
https://github.com/langgenius/dify.git
synced 2025-11-17 03:44:13 +00:00
fix: pipeline init
This commit is contained in:
parent
4d68aadc1c
commit
f6978ce6b1
@ -0,0 +1,39 @@
|
|||||||
|
import {
|
||||||
|
memo,
|
||||||
|
} from 'react'
|
||||||
|
import PromptEditor from '@/app/components/base/prompt-editor'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
import Placeholder from './placeholder'
|
||||||
|
|
||||||
|
type MixedVariableTextInputProps = {
|
||||||
|
editable?: boolean
|
||||||
|
value?: string
|
||||||
|
onChange?: (text: string) => void
|
||||||
|
}
|
||||||
|
const MixedVariableTextInput = ({
|
||||||
|
editable = true,
|
||||||
|
value = '',
|
||||||
|
onChange,
|
||||||
|
}: MixedVariableTextInputProps) => {
|
||||||
|
return (
|
||||||
|
<PromptEditor
|
||||||
|
wrapperClassName={cn(
|
||||||
|
'rounded-lg border border-transparent bg-components-input-bg-normal px-2 py-1',
|
||||||
|
'hover:border-components-input-border-hover hover:bg-components-input-bg-hover',
|
||||||
|
'focus-within:border-components-input-border-active focus-within:bg-components-input-bg-active focus-within:shadow-xs',
|
||||||
|
)}
|
||||||
|
className='caret:text-text-accent'
|
||||||
|
editable={editable}
|
||||||
|
value={value}
|
||||||
|
workflowVariableBlock={{
|
||||||
|
show: true,
|
||||||
|
variables: [],
|
||||||
|
workflowNodesMap: {},
|
||||||
|
}}
|
||||||
|
placeholder={<Placeholder />}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(MixedVariableTextInput)
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
import { useCallback } from 'react'
|
||||||
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||||
|
import { FOCUS_COMMAND } from 'lexical'
|
||||||
|
import { $insertNodes } from 'lexical'
|
||||||
|
import { CustomTextNode } from '@/app/components/base/prompt-editor/plugins/custom-text/node'
|
||||||
|
import Badge from '@/app/components/base/badge'
|
||||||
|
|
||||||
|
const Placeholder = () => {
|
||||||
|
const [editor] = useLexicalComposerContext()
|
||||||
|
|
||||||
|
const handleInsert = useCallback((text: string) => {
|
||||||
|
editor.update(() => {
|
||||||
|
const textNode = new CustomTextNode(text)
|
||||||
|
$insertNodes([textNode])
|
||||||
|
})
|
||||||
|
editor.dispatchCommand(FOCUS_COMMAND, undefined as any)
|
||||||
|
}, [editor])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className='pointer-events-auto flex h-full w-full cursor-text items-center px-2'
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
handleInsert('')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex grow items-center'>
|
||||||
|
Type or press
|
||||||
|
<div className='system-kbd mx-0.5 flex h-4 w-4 items-center justify-center rounded bg-components-kbd-bg-gray text-text-placeholder'>/</div>
|
||||||
|
<div
|
||||||
|
className='system-sm-regular cursor-pointer text-components-input-text-placeholder underline decoration-dotted decoration-auto underline-offset-auto hover:text-text-tertiary'
|
||||||
|
onClick={((e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
handleInsert('/')
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
insert variable
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Badge
|
||||||
|
className='shrink-0'
|
||||||
|
text='String'
|
||||||
|
uppercase={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Placeholder
|
||||||
@ -64,8 +64,9 @@ import cn from '@/utils/classnames'
|
|||||||
export type PromptEditorProps = {
|
export type PromptEditorProps = {
|
||||||
instanceId?: string
|
instanceId?: string
|
||||||
compact?: boolean
|
compact?: boolean
|
||||||
|
wrapperClassName?: string
|
||||||
className?: string
|
className?: string
|
||||||
placeholder?: string
|
placeholder?: string | JSX.Element
|
||||||
placeholderClassName?: string
|
placeholderClassName?: string
|
||||||
style?: React.CSSProperties
|
style?: React.CSSProperties
|
||||||
value?: string
|
value?: string
|
||||||
@ -85,6 +86,7 @@ export type PromptEditorProps = {
|
|||||||
const PromptEditor: FC<PromptEditorProps> = ({
|
const PromptEditor: FC<PromptEditorProps> = ({
|
||||||
instanceId,
|
instanceId,
|
||||||
compact,
|
compact,
|
||||||
|
wrapperClassName,
|
||||||
className,
|
className,
|
||||||
placeholder,
|
placeholder,
|
||||||
placeholderClassName,
|
placeholderClassName,
|
||||||
@ -147,10 +149,25 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<LexicalComposer initialConfig={{ ...initialConfig, editable }}>
|
<LexicalComposer initialConfig={{ ...initialConfig, editable }}>
|
||||||
<div className='relative min-h-5'>
|
<div className={cn('relative', wrapperClassName)}>
|
||||||
<RichTextPlugin
|
<RichTextPlugin
|
||||||
contentEditable={<ContentEditable className={`${className} outline-none ${compact ? 'text-[13px] leading-5' : 'text-sm leading-6'} text-text-secondary`} style={style || {}} />}
|
contentEditable={
|
||||||
placeholder={<Placeholder value={placeholder} className={cn('truncate', placeholderClassName)} compact={compact} />}
|
<ContentEditable
|
||||||
|
className={cn(
|
||||||
|
'text-text-secondary outline-none',
|
||||||
|
compact ? 'text-[13px] leading-5' : 'text-sm leading-6',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
style={style || {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
placeholder={
|
||||||
|
<Placeholder
|
||||||
|
value={placeholder}
|
||||||
|
className={cn('truncate', placeholderClassName)}
|
||||||
|
compact={compact}
|
||||||
|
/>
|
||||||
|
}
|
||||||
ErrorBoundary={LexicalErrorBoundary}
|
ErrorBoundary={LexicalErrorBoundary}
|
||||||
/>
|
/>
|
||||||
<ComponentPickerBlock
|
<ComponentPickerBlock
|
||||||
|
|||||||
@ -16,7 +16,6 @@ export class CustomTextNode extends TextNode {
|
|||||||
|
|
||||||
createDOM(config: EditorConfig) {
|
createDOM(config: EditorConfig) {
|
||||||
const dom = super.createDOM(config)
|
const dom = super.createDOM(config)
|
||||||
dom.classList.add('align-middle')
|
|
||||||
return dom
|
return dom
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,16 +8,16 @@ const Placeholder = ({
|
|||||||
className,
|
className,
|
||||||
}: {
|
}: {
|
||||||
compact?: boolean
|
compact?: boolean
|
||||||
value?: string
|
value?: string | JSX.Element
|
||||||
className?: string
|
className?: string
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
className,
|
|
||||||
'pointer-events-none absolute left-0 top-0 h-full w-full select-none text-sm text-components-input-text-placeholder',
|
'pointer-events-none absolute left-0 top-0 h-full w-full select-none text-sm text-components-input-text-placeholder',
|
||||||
compact ? 'text-[13px] leading-5' : 'text-sm leading-6',
|
compact ? 'text-[13px] leading-5' : 'text-sm leading-6',
|
||||||
|
className,
|
||||||
)}>
|
)}>
|
||||||
{value || t('common.promptEditor.placeholder')}
|
{value || t('common.promptEditor.placeholder')}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
53
web/app/components/rag-pipeline/hooks/use-pipeline-config.ts
Normal file
53
web/app/components/rag-pipeline/hooks/use-pipeline-config.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { useCallback } from 'react'
|
||||||
|
import {
|
||||||
|
useStore,
|
||||||
|
useWorkflowStore,
|
||||||
|
} from '@/app/components/workflow/store'
|
||||||
|
import { useWorkflowConfig } from '@/service/use-workflow'
|
||||||
|
import type { ToolWithProvider } from '@/app/components/workflow/types'
|
||||||
|
import type { FetchWorkflowDraftResponse } from '@/types/workflow'
|
||||||
|
|
||||||
|
export const usePipelineConfig = () => {
|
||||||
|
const pipelineId = useStore(s => s.pipelineId)
|
||||||
|
const workflowStore = useWorkflowStore()
|
||||||
|
|
||||||
|
const handleUpdateWorkflowConfig = useCallback((config: Record<string, any>) => {
|
||||||
|
const { setWorkflowConfig } = workflowStore.getState()
|
||||||
|
|
||||||
|
setWorkflowConfig(config)
|
||||||
|
}, [workflowStore])
|
||||||
|
useWorkflowConfig(
|
||||||
|
pipelineId ? `/rag/pipeline/${pipelineId}/workflows/draft/config` : '',
|
||||||
|
handleUpdateWorkflowConfig,
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleUpdateDataSourceList = useCallback((dataSourceList: ToolWithProvider[]) => {
|
||||||
|
const { setDataSourceList } = workflowStore.getState()
|
||||||
|
|
||||||
|
setDataSourceList!(dataSourceList)
|
||||||
|
}, [workflowStore])
|
||||||
|
useWorkflowConfig<ToolWithProvider[]>(
|
||||||
|
'/rag/pipelines/datasource-plugins',
|
||||||
|
handleUpdateDataSourceList,
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleUpdateNodesDefaultConfigs = useCallback((nodesDefaultConfigs: Record<string, any>) => {
|
||||||
|
const { setNodesDefaultConfigs } = workflowStore.getState()
|
||||||
|
|
||||||
|
setNodesDefaultConfigs!(nodesDefaultConfigs)
|
||||||
|
}, [workflowStore])
|
||||||
|
useWorkflowConfig(
|
||||||
|
pipelineId ? `/rag/pipeline/${pipelineId}/workflows/default-workflow-block-configs` : '',
|
||||||
|
handleUpdateNodesDefaultConfigs,
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleUpdatePublishedAt = useCallback((publishedWorkflow: FetchWorkflowDraftResponse) => {
|
||||||
|
const { setPublishedAt } = workflowStore.getState()
|
||||||
|
|
||||||
|
setPublishedAt(publishedWorkflow?.created_at)
|
||||||
|
}, [workflowStore])
|
||||||
|
useWorkflowConfig(
|
||||||
|
pipelineId ? `/rag/pipeline/${pipelineId}/workflows/publish` : '',
|
||||||
|
handleUpdatePublishedAt,
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -5,18 +5,15 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { useParams } from 'next/navigation'
|
import { useParams } from 'next/navigation'
|
||||||
import {
|
import {
|
||||||
useStore,
|
|
||||||
useWorkflowStore,
|
useWorkflowStore,
|
||||||
} from '@/app/components/workflow/store'
|
} from '@/app/components/workflow/store'
|
||||||
import { usePipelineTemplate } from './use-pipeline-template'
|
import { usePipelineTemplate } from './use-pipeline-template'
|
||||||
import {
|
import {
|
||||||
fetchNodesDefaultConfigs,
|
|
||||||
fetchPublishedWorkflow,
|
|
||||||
fetchWorkflowDraft,
|
fetchWorkflowDraft,
|
||||||
syncWorkflowDraft,
|
syncWorkflowDraft,
|
||||||
} from '@/service/workflow'
|
} from '@/service/workflow'
|
||||||
import type { FetchWorkflowDraftResponse } from '@/types/workflow'
|
import type { FetchWorkflowDraftResponse } from '@/types/workflow'
|
||||||
// import { useWorkflowConfig } from '@/service/use-workflow'
|
import { usePipelineConfig } from './use-pipeline-config'
|
||||||
|
|
||||||
export const usePipelineInit = () => {
|
export const usePipelineInit = () => {
|
||||||
const { datasetId } = useParams()
|
const { datasetId } = useParams()
|
||||||
@ -25,31 +22,33 @@ export const usePipelineInit = () => {
|
|||||||
nodes: nodesTemplate,
|
nodes: nodesTemplate,
|
||||||
edges: edgesTemplate,
|
edges: edgesTemplate,
|
||||||
} = usePipelineTemplate()
|
} = usePipelineTemplate()
|
||||||
const setSyncWorkflowDraftHash = useStore(s => s.setSyncWorkflowDraftHash)
|
|
||||||
const [data, setData] = useState<FetchWorkflowDraftResponse>()
|
const [data, setData] = useState<FetchWorkflowDraftResponse>()
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// workflowStore.setState({ pipelineId: datasetId as string })
|
workflowStore.setState({ pipelineId: datasetId as string })
|
||||||
}, [datasetId, workflowStore])
|
}, [datasetId, workflowStore])
|
||||||
|
|
||||||
const handleUpdateWorkflowConfig = useCallback((config: Record<string, any>) => {
|
usePipelineConfig()
|
||||||
const { setWorkflowConfig } = workflowStore.getState()
|
|
||||||
|
|
||||||
setWorkflowConfig(config)
|
|
||||||
}, [workflowStore])
|
|
||||||
// useWorkflowConfig(`/rag/pipeline/${datasetId}/workflows/draft/config`, handleUpdateWorkflowConfig)
|
|
||||||
|
|
||||||
const handleGetInitialWorkflowData = useCallback(async () => {
|
const handleGetInitialWorkflowData = useCallback(async () => {
|
||||||
|
const {
|
||||||
|
setEnvSecrets,
|
||||||
|
setEnvironmentVariables,
|
||||||
|
setSyncWorkflowDraftHash,
|
||||||
|
setDraftUpdatedAt,
|
||||||
|
setToolPublished,
|
||||||
|
} = workflowStore.getState()
|
||||||
try {
|
try {
|
||||||
const res = await fetchWorkflowDraft(`/rag/pipeline/${datasetId}/workflows/draft`)
|
const res = await fetchWorkflowDraft(`/rag/pipeline/${datasetId}/workflows/draft`)
|
||||||
setData(res)
|
setData(res)
|
||||||
workflowStore.setState({
|
setDraftUpdatedAt(res.updated_at)
|
||||||
envSecrets: (res.environment_variables || []).filter(env => env.value_type === 'secret').reduce((acc, env) => {
|
setToolPublished(res.tool_published)
|
||||||
|
setEnvSecrets((res.environment_variables || []).filter(env => env.value_type === 'secret').reduce((acc, env) => {
|
||||||
acc[env.id] = env.value
|
acc[env.id] = env.value
|
||||||
return acc
|
return acc
|
||||||
}, {} as Record<string, string>),
|
}, {} as Record<string, string>))
|
||||||
environmentVariables: res.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [],
|
setEnvironmentVariables(res.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [])
|
||||||
})
|
|
||||||
setSyncWorkflowDraftHash(res.hash)
|
setSyncWorkflowDraftHash(res.hash)
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
@ -68,49 +67,21 @@ export const usePipelineInit = () => {
|
|||||||
environment_variables: [],
|
environment_variables: [],
|
||||||
},
|
},
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
workflowStore.getState().setDraftUpdatedAt(res.updated_at)
|
const { setDraftUpdatedAt } = workflowStore.getState()
|
||||||
|
setDraftUpdatedAt(res.updated_at)
|
||||||
handleGetInitialWorkflowData()
|
handleGetInitialWorkflowData()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [nodesTemplate, edgesTemplate, workflowStore, setSyncWorkflowDraftHash, datasetId])
|
}, [nodesTemplate, edgesTemplate, workflowStore, datasetId])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// handleGetInitialWorkflowData()
|
handleGetInitialWorkflowData()
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleFetchPreloadData = useCallback(async () => {
|
|
||||||
try {
|
|
||||||
const nodesDefaultConfigsData = await fetchNodesDefaultConfigs(`/rag/pipeline/${datasetId}/workflows/default-workflow-block-configs`)
|
|
||||||
const publishedWorkflow = await fetchPublishedWorkflow(`/rag/pipeline/${datasetId}/workflows/publish`)
|
|
||||||
workflowStore.setState({
|
|
||||||
nodesDefaultConfigs: nodesDefaultConfigsData.reduce((acc, block) => {
|
|
||||||
if (!acc[block.type])
|
|
||||||
acc[block.type] = { ...block.config }
|
|
||||||
return acc
|
|
||||||
}, {} as Record<string, any>),
|
|
||||||
})
|
|
||||||
workflowStore.getState().setPublishedAt(publishedWorkflow?.created_at)
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
}, [workflowStore, datasetId])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// handleFetchPreloadData()
|
|
||||||
}, [handleFetchPreloadData])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data) {
|
|
||||||
workflowStore.getState().setDraftUpdatedAt(data.updated_at)
|
|
||||||
workflowStore.getState().setToolPublished(data.tool_published)
|
|
||||||
}
|
|
||||||
}, [data, workflowStore])
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { RAGPipelineVariables } from '@/models/pipeline'
|
import type { RAGPipelineVariables } from '@/models/pipeline'
|
||||||
import type { StateCreator } from 'zustand'
|
import type { StateCreator } from 'zustand'
|
||||||
|
import type { ToolWithProvider } from '../../workflow/types'
|
||||||
import { InputVarType } from '../../workflow/types'
|
import { InputVarType } from '../../workflow/types'
|
||||||
|
|
||||||
export type RagPipelineSliceShape = {
|
export type RagPipelineSliceShape = {
|
||||||
@ -10,6 +11,8 @@ export type RagPipelineSliceShape = {
|
|||||||
setNodesDefaultConfigs: (nodesDefaultConfigs: Record<string, any>) => void
|
setNodesDefaultConfigs: (nodesDefaultConfigs: Record<string, any>) => void
|
||||||
ragPipelineVariables: RAGPipelineVariables
|
ragPipelineVariables: RAGPipelineVariables
|
||||||
setRagPipelineVariables: (ragPipelineVariables: RAGPipelineVariables) => void
|
setRagPipelineVariables: (ragPipelineVariables: RAGPipelineVariables) => void
|
||||||
|
dataSourceList: ToolWithProvider[]
|
||||||
|
setDataSourceList: (dataSourceList: ToolWithProvider[]) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateRagPipelineSliceSlice = StateCreator<RagPipelineSliceShape>
|
export type CreateRagPipelineSliceSlice = StateCreator<RagPipelineSliceShape>
|
||||||
@ -50,4 +53,6 @@ export const createRagPipelineSliceSlice: StateCreator<RagPipelineSliceShape> =
|
|||||||
}],
|
}],
|
||||||
}],
|
}],
|
||||||
setRagPipelineVariables: (ragPipelineVariables: RAGPipelineVariables) => set(() => ({ ragPipelineVariables })),
|
setRagPipelineVariables: (ragPipelineVariables: RAGPipelineVariables) => set(() => ({ ragPipelineVariables })),
|
||||||
|
dataSourceList: [],
|
||||||
|
setDataSourceList: (dataSourceList: ToolWithProvider[]) => set(() => ({ dataSourceList })),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -29,6 +29,7 @@ export enum CollectionType {
|
|||||||
custom = 'api',
|
custom = 'api',
|
||||||
model = 'model',
|
model = 'model',
|
||||||
workflow = 'workflow',
|
workflow = 'workflow',
|
||||||
|
datasource = 'datasource',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Emoji = {
|
export type Emoji = {
|
||||||
|
|||||||
51
web/app/components/workflow/block-selector/data-sources.tsx
Normal file
51
web/app/components/workflow/block-selector/data-sources.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
useRef,
|
||||||
|
} from 'react'
|
||||||
|
import type {
|
||||||
|
OnSelectBlock,
|
||||||
|
ToolWithProvider,
|
||||||
|
} from '../types'
|
||||||
|
import Tools from './tools'
|
||||||
|
import { ViewType } from './view-type-select'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
import type { ListRef } from '@/app/components/workflow/block-selector/market-place-plugin/list'
|
||||||
|
|
||||||
|
type AllToolsProps = {
|
||||||
|
className?: string
|
||||||
|
toolContentClassName?: string
|
||||||
|
searchText: string
|
||||||
|
onSelect: OnSelectBlock
|
||||||
|
dataSources: ToolWithProvider[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataSources = ({
|
||||||
|
className,
|
||||||
|
toolContentClassName,
|
||||||
|
searchText,
|
||||||
|
onSelect,
|
||||||
|
dataSources,
|
||||||
|
}: AllToolsProps) => {
|
||||||
|
const pluginRef = useRef<ListRef>(null)
|
||||||
|
const wrapElemRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn(className)}>
|
||||||
|
<div
|
||||||
|
ref={wrapElemRef}
|
||||||
|
className='max-h-[464px] overflow-y-auto'
|
||||||
|
onScroll={pluginRef.current?.handleScroll}
|
||||||
|
>
|
||||||
|
<Tools
|
||||||
|
className={toolContentClassName}
|
||||||
|
showWorkflowEmpty={false}
|
||||||
|
tools={dataSources}
|
||||||
|
onSelect={onSelect}
|
||||||
|
viewType={ViewType.flat}
|
||||||
|
hasSearchText={!!searchText}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DataSources
|
||||||
@ -8,7 +8,7 @@ import {
|
|||||||
ToolTypeEnum,
|
ToolTypeEnum,
|
||||||
} from './types'
|
} from './types'
|
||||||
|
|
||||||
export const useTabs = (noBlocks?: boolean) => {
|
export const useTabs = (noBlocks?: boolean, noSources?: boolean) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const tabs = useMemo(() => {
|
const tabs = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@ -22,16 +22,22 @@ export const useTabs = (noBlocks?: boolean) => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
{
|
...(
|
||||||
key: TabsEnum.Sources,
|
noSources
|
||||||
name: t('workflow.tabs.sources'),
|
? []
|
||||||
},
|
: [
|
||||||
|
{
|
||||||
|
key: TabsEnum.Sources,
|
||||||
|
name: t('workflow.tabs.sources'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
),
|
||||||
{
|
{
|
||||||
key: TabsEnum.Tools,
|
key: TabsEnum.Tools,
|
||||||
name: t('workflow.tabs.tools'),
|
name: t('workflow.tabs.tools'),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}, [t, noBlocks])
|
}, [t, noBlocks, noSources])
|
||||||
const initialTab = useMemo(() => {
|
const initialTab = useMemo(() => {
|
||||||
if (noBlocks)
|
if (noBlocks)
|
||||||
return TabsEnum.Sources
|
return TabsEnum.Sources
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import type { NodeSelectorProps } from './main'
|
|||||||
import NodeSelector from './main'
|
import NodeSelector from './main'
|
||||||
import { useHooksStore } from '@/app/components/workflow/hooks-store/store'
|
import { useHooksStore } from '@/app/components/workflow/hooks-store/store'
|
||||||
import { BlockEnum } from '@/app/components/workflow/types'
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { useStore } from '@/app/components/workflow/store'
|
||||||
|
|
||||||
const NodeSelectorWrapper = (props: NodeSelectorProps) => {
|
const NodeSelectorWrapper = (props: NodeSelectorProps) => {
|
||||||
const availableNodesMetaData = useHooksStore(s => s.availableNodesMetaData)
|
const availableNodesMetaData = useHooksStore(s => s.availableNodesMetaData)
|
||||||
@ -27,10 +28,13 @@ const NodeSelectorWrapper = (props: NodeSelectorProps) => {
|
|||||||
})
|
})
|
||||||
}, [availableNodesMetaData?.nodes])
|
}, [availableNodesMetaData?.nodes])
|
||||||
|
|
||||||
|
const dataSourceList = useStore(s => s.dataSourceList)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeSelector
|
<NodeSelector
|
||||||
{...props}
|
{...props}
|
||||||
blocks={blocks}
|
blocks={blocks}
|
||||||
|
dataSources={dataSourceList || []}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import type {
|
|||||||
BlockEnum,
|
BlockEnum,
|
||||||
NodeDefault,
|
NodeDefault,
|
||||||
OnSelectBlock,
|
OnSelectBlock,
|
||||||
|
ToolWithProvider,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
import Tabs from './tabs'
|
import Tabs from './tabs'
|
||||||
import { TabsEnum } from './types'
|
import { TabsEnum } from './types'
|
||||||
@ -49,6 +50,7 @@ export type NodeSelectorProps = {
|
|||||||
availableBlocksTypes?: BlockEnum[]
|
availableBlocksTypes?: BlockEnum[]
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
blocks?: NodeDefault[]
|
blocks?: NodeDefault[]
|
||||||
|
dataSources?: ToolWithProvider[]
|
||||||
}
|
}
|
||||||
const NodeSelector: FC<NodeSelectorProps> = ({
|
const NodeSelector: FC<NodeSelectorProps> = ({
|
||||||
open: openFromProps,
|
open: openFromProps,
|
||||||
@ -65,6 +67,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
availableBlocksTypes,
|
availableBlocksTypes,
|
||||||
disabled,
|
disabled,
|
||||||
blocks = [],
|
blocks = [],
|
||||||
|
dataSources = [],
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [searchText, setSearchText] = useState('')
|
const [searchText, setSearchText] = useState('')
|
||||||
@ -95,7 +98,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
activeTab,
|
activeTab,
|
||||||
setActiveTab,
|
setActiveTab,
|
||||||
tabs,
|
tabs,
|
||||||
} = useTabs(!blocks.length)
|
} = useTabs(!blocks.length, !dataSources.length)
|
||||||
|
|
||||||
const searchPlaceholder = useMemo(() => {
|
const searchPlaceholder = useMemo(() => {
|
||||||
if (activeTab === TabsEnum.Blocks)
|
if (activeTab === TabsEnum.Blocks)
|
||||||
@ -193,6 +196,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
|
|||||||
tags={tags}
|
tags={tags}
|
||||||
availableBlocksTypes={availableBlocksTypes}
|
availableBlocksTypes={availableBlocksTypes}
|
||||||
blocks={blocks}
|
blocks={blocks}
|
||||||
|
dataSources={dataSources}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</PortalToFollowElemContent>
|
</PortalToFollowElemContent>
|
||||||
|
|||||||
@ -4,11 +4,13 @@ import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/se
|
|||||||
import type {
|
import type {
|
||||||
BlockEnum,
|
BlockEnum,
|
||||||
NodeDefault,
|
NodeDefault,
|
||||||
|
ToolWithProvider,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
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 DataSources from './data-sources'
|
||||||
|
|
||||||
export type TabsProps = {
|
export type TabsProps = {
|
||||||
activeTab: TabsEnum
|
activeTab: TabsEnum
|
||||||
@ -17,6 +19,7 @@ export type TabsProps = {
|
|||||||
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
||||||
availableBlocksTypes?: BlockEnum[]
|
availableBlocksTypes?: BlockEnum[]
|
||||||
blocks: NodeDefault[]
|
blocks: NodeDefault[]
|
||||||
|
dataSources?: ToolWithProvider[]
|
||||||
}
|
}
|
||||||
const Tabs: FC<TabsProps> = ({
|
const Tabs: FC<TabsProps> = ({
|
||||||
activeTab,
|
activeTab,
|
||||||
@ -25,6 +28,7 @@ const Tabs: FC<TabsProps> = ({
|
|||||||
onSelect,
|
onSelect,
|
||||||
availableBlocksTypes,
|
availableBlocksTypes,
|
||||||
blocks,
|
blocks,
|
||||||
|
dataSources = [],
|
||||||
}) => {
|
}) => {
|
||||||
const { data: buildInTools } = useAllBuiltInTools()
|
const { data: buildInTools } = useAllBuiltInTools()
|
||||||
const { data: customTools } = useAllCustomTools()
|
const { data: customTools } = useAllCustomTools()
|
||||||
@ -42,6 +46,15 @@ const Tabs: FC<TabsProps> = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
activeTab === TabsEnum.Sources && !!dataSources.length && (
|
||||||
|
<DataSources
|
||||||
|
searchText={searchText}
|
||||||
|
onSelect={onSelect}
|
||||||
|
dataSources={dataSources}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
activeTab === TabsEnum.Tools && (
|
activeTab === TabsEnum.Tools && (
|
||||||
<AllTools
|
<AllTools
|
||||||
|
|||||||
@ -21,11 +21,12 @@ export const useAppWorkflow = (appID: string) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWorkflowConfig = (url: string, onSuccess: (v: WorkflowConfigResponse) => void) => {
|
export const useWorkflowConfig = <T = WorkflowConfigResponse>(url: string, onSuccess: (v: T) => void) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
|
enabled: !!url,
|
||||||
queryKey: [NAME_SPACE, 'config', url],
|
queryKey: [NAME_SPACE, 'config', url],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const data = await get<WorkflowConfigResponse>(url)
|
const data = await get<T>(url)
|
||||||
onSuccess(data)
|
onSuccess(data)
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user