@ -1,65 +1,69 @@
import {
import {
memo ,
memo ,
useCallback ,
useCallback ,
use State ,
use Memo ,
} from 'react'
} from 'react'
import { useStore } from '@/app/components/workflow/store'
import { useStore } from '@/app/components/workflow/store'
import { RiCloseLine } from '@remixicon/react'
import { RiCloseLine } from '@remixicon/react'
import { Jina } from '@/app/components/base/icons/src/public/llm'
import { BlockEnum , type InputVar } from '@/app/components/workflow/types'
import type { InputVar } from '@/app/components/workflow/types'
import { InputVarType } from '@/app/components/workflow/types'
import Tooltip from '@/app/components/base/tooltip'
import DialogWrapper from './dialog-wrapper'
import DialogWrapper from './dialog-wrapper'
import FieldList from './field-list'
import FieldList from './field-list'
import FooterTip from './footer-tip'
import FooterTip from './footer-tip'
import SharedInputs from './label-right-content/shared-inputs'
import Datasource from './label-right-content/datasource'
import { useNodes } from 'reactflow'
import type { DataSourceNodeType } from '@/app/components/workflow/nodes/data-source/types'
import { useTranslation } from 'react-i18next'
import produce from 'immer'
type InputFieldDialogProps = {
type InputFieldDialogProps = {
readonly ? : boolean
readonly ? : boolean
initialInputFieldsMap? : Record < string , InputVar [ ] >
}
}
const InputFieldDialog = ( {
const InputFieldDialog = ( {
readonly = false ,
readonly = false ,
initialInputFieldsMap ,
} : InputFieldDialogProps ) = > {
} : InputFieldDialogProps ) = > {
const { t } = useTranslation ( )
const nodes = useNodes < DataSourceNodeType > ( )
const showInputFieldDialog = useStore ( state = > state . showInputFieldDialog )
const showInputFieldDialog = useStore ( state = > state . showInputFieldDialog )
const setShowInputFieldDialog = useStore ( state = > state . setShowInputFieldDialog )
const setShowInputFieldDialog = useStore ( state = > state . setShowInputFieldDialog )
// TODO: delete mock data
const ragPipelineVariables = useStore ( state = > state . ragPipelineVariables )
const [ inputFieldsMap , setInputFieldsMap ] = useState ( initialInputFieldsMap || {
const setRagPipelineVariables = useStore ( state = > state . setRagPipelineVariables )
jina : [ {
variable : 'name' ,
const datasourceTitleMap = useMemo ( ( ) = > {
label : 'name' ,
const datasourceNameMap : Record < string , string > = { }
type : InputVarType . textInput ,
const datasourceNodes = nodes . filter ( node = > node . data . type === BlockEnum . DataSource )
required : true ,
datasourceNodes . forEach ( ( node ) = > {
max_length : 12 ,
const { id , data } = node
} , {
if ( data ? . title )
variable : 'num' ,
datasourceNameMap [ id ] = data . title
label : 'num' ,
} )
type : InputVarType . number ,
return datasourceNameMap
required : true ,
} , [ nodes ] )
} ] ,
firecrawl : [ {
const inputFieldsMap = useMemo ( ( ) = > {
variable : 'name' ,
const inputFieldsMap : Record < string , InputVar [ ] > = { }
label : 'name' ,
ragPipelineVariables ? . forEach ( ( variable ) = > {
type: InputVarType . textInput ,
const { nodeId , variables } = variable
required : true ,
if ( nodeId )
max_length : 12 ,
inputFieldsMap [ nodeId ] = variables
} ] ,
else
shared : [ {
inputFieldsMap . shared = variables
variable : 'name' ,
} )
label : 'name' ,
return inputFieldsMap
type : InputVarType . textInput ,
} , [ ragPipelineVariables ] )
required : true ,
max_length : 12 ,
const datasourceKeys = useMemo ( ( ) = > {
} ] ,
return Object . keys ( inputFieldsMap ) . filter ( key = > key !== 'shared' )
} )
} , [ inputFieldsMap ] )
const updateInputFields = useCallback ( ( key : string , value : InputVar [ ] ) = > {
const updateInputFields = useCallback ( ( key : string , value : InputVar [ ] ) = > {
setInputFieldsMap ( prev = > ( {
const newRagPipelineVariables = produce ( ragPipelineVariables ! , ( draft ) = > {
. . . prev ,
const index = draft . findIndex ( variable = > variable . nodeId === key )
[ key ] : value ,
draft [ index ] . variables = value
} ) )
} )
} , [ ] )
setRagPipelineVariables ? . ( newRagPipelineVariables )
} , [ ragPipelineVariables , setRagPipelineVariables ] )
const closePanel = useCallback ( ( ) = > {
const closePanel = useCallback ( ( ) = > {
setShowInputFieldDialog ? . ( false )
setShowInputFieldDialog ? . ( false )
@ -72,9 +76,8 @@ const InputFieldDialog = ({
>
>
< div className = 'flex grow flex-col' >
< div className = 'flex grow flex-col' >
< div className = 'flex items-center p-4 pb-0' >
< div className = 'flex items-center p-4 pb-0' >
{ /* // TODO: i18n */ }
< div className = 'system-xl-semibold grow' >
< div className = 'system-xl-semibold grow' >
User input fields
{ t ( 'datasetPipeline.inputFieldPanel.title' ) }
< / div >
< / div >
< button
< button
type = 'button'
type = 'button'
@ -85,54 +88,31 @@ const InputFieldDialog = ({
< / button >
< / button >
< / div >
< / div >
< div className = 'system-sm-regular px-4 py-1 text-text-tertiary' >
< div className = 'system-sm-regular px-4 py-1 text-text-tertiary' >
User input fields are used to define and collect variables required during the pipeline execution process . Users can customize the field type and flexibly configure the input value to meet the needs of different data sources or document processing steps .
{ t ( 'datasetPipeline.inputFieldPanel.description' ) }
< / div >
< / div >
< div className = 'flex grow flex-col overflow-y-auto' >
< div className = 'flex grow flex-col overflow-y-auto' >
{ /* Jina Reader Field List */ }
{ /* Datasources Inputs */ }
< FieldList
{
LabelRightContent = { (
datasourceKeys . map ( ( key ) = > {
< div className = 'flex items-center gap-x-1.5' >
const inputFields = inputFieldsMap [ key ] || [ ]
< div className = 'flex size-5 items-center justify-center rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default' >
return (
< Jina className = 'size-3.5' / >
< FieldList
< / div >
LabelRightContent = { < Datasource title = { datasourceTitleMap [ key ] } / > }
< span className = 'system-sm-medium text-text-secondary' > Jina Reader < / span >
inputFields = { inputFields }
< / div >
readonly = { readonly }
) }
labelClassName = 'pt-2 pb-1'
inputFields = { inputFieldsMap . jina }
handleInputFieldsChange = { updateInputFields . bind ( null , key ) }
readonly = { readonly }
/ >
labelClassName = 'pt-2 pb-1'
)
handleInputFieldsChange = { updateInputFields . bind ( null , 'jina' ) }
} )
/ >
}
{ /* Firecrawl Field List */ }
< FieldList
LabelRightContent = { (
< div className = 'flex items-center gap-x-1.5' >
< div className = 'flex size-5 items-center justify-center rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default' >
< span className = 'text-[14px] leading-[14px]' > 🔥 < / span >
< / div >
< span className = 'system-sm-medium text-text-secondary' > Firecrawl < / span >
< / div >
) }
inputFields = { inputFieldsMap . firecrawl }
readonly = { readonly }
labelClassName = 'pt-2 pb-1'
handleInputFieldsChange = { updateInputFields . bind ( null , 'firecrawl' ) }
/ >
{ /* Shared Inputs */ }
{ /* Shared Inputs */ }
< FieldList
< FieldList
LabelRightContent = { (
LabelRightContent = { < SharedInputs / > }
< div className = 'flex items-center gap-x-1' >
inputFields = { inputFieldsMap . shared || [ ] }
< span className = 'system-sm-medium text-text-secondary' > SHARED INPUTS < / span >
< Tooltip
popupContent = 'Shared Inputs are available to all downstream nodes across data sources. For example, variables like delimiter and maximum chunk length can be uniformly applied when processing documents from multiple sources.'
popupClassName = '!w-[300px]'
/ >
< / div >
) }
inputFields = { inputFieldsMap . shared }
readonly = { readonly }
readonly = { readonly }
labelClassName = 'pt-1 pb-2'
labelClassName = 'pt-1 pb-2'
handleInputFieldsChange = { updateInputFields . bind ( null , ' shared ') }
handleInputFieldsChange = { updateInputFields . bind ( null , '' ) }
/ >
/ >
< / div >
< / div >
< FooterTip / >
< FooterTip / >