mirror of https://github.com/langgenius/dify.git
feat: enhance input field dialog with preview functionality and global inputs
This commit is contained in:
parent
cab491795a
commit
3afd5e73c9
|
|
@ -36,7 +36,7 @@ const DialogWrapper = ({
|
|||
<TransitionChild>
|
||||
<DialogPanel className={cn(
|
||||
'relative flex w-[400px] flex-col overflow-hidden rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg p-0 shadow-xl shadow-shadow-shadow-9 transition-all',
|
||||
'data-[closed]:scale-95 data-[closed]:opacity-0',
|
||||
'data-[closed]:scale-95 data-[closed]:opacity-0',
|
||||
'data-[enter]:scale-100 data-[enter]:opacity-100 data-[enter]:duration-300 data-[enter]:ease-out',
|
||||
'data-[leave]:scale-95 data-[leave]:opacity-0 data-[leave]:duration-200 data-[leave]:ease-in',
|
||||
className,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const FieldListContainer = ({
|
|||
return inputFields.map((content) => {
|
||||
return ({
|
||||
id: content.variable,
|
||||
name: content.variable,
|
||||
...content,
|
||||
})
|
||||
})
|
||||
}, [inputFields])
|
||||
|
|
@ -40,6 +40,7 @@ const FieldListContainer = ({
|
|||
setList={onListSortChange}
|
||||
handle='.handle'
|
||||
ghostClass='opacity-50'
|
||||
group='rag-pipeline-input-field'
|
||||
animation={150}
|
||||
disabled={readonly}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -36,9 +36,10 @@ export const useFieldList = (
|
|||
|
||||
const handleListSortChange = useCallback((list: SortableItem[]) => {
|
||||
const newInputFields = list.map((item) => {
|
||||
return inputFieldsRef.current.find(field => field.variable === item.name)
|
||||
const { id, ...filed } = item
|
||||
return filed
|
||||
})
|
||||
handleInputFieldsChange(newInputFields as InputVar[])
|
||||
handleInputFieldsChange(newInputFields)
|
||||
}, [handleInputFieldsChange])
|
||||
|
||||
const [editingField, setEditingField] = useState<InputVar | undefined>()
|
||||
|
|
@ -62,12 +63,12 @@ export const useFieldList = (
|
|||
setRemoveIndex(index as number)
|
||||
return
|
||||
}
|
||||
const newInputFields = inputFieldsRef.current.splice(index, 1)
|
||||
const newInputFields = inputFieldsRef.current.filter((_, i) => i !== index)
|
||||
handleInputFieldsChange(newInputFields)
|
||||
}, [handleInputFieldsChange, isVarUsedInNodes, nodeId, showRemoveVarConfirm])
|
||||
|
||||
const onRemoveVarConfirm = useCallback(() => {
|
||||
const newInputFields = inputFieldsRef.current.splice(removedIndex, 1)
|
||||
const newInputFields = inputFieldsRef.current.filter((_, i) => i !== removedIndex)
|
||||
handleInputFieldsChange(newInputFields)
|
||||
removeUsedVarInNodes(removedVar)
|
||||
hideRemoveVarConfirm()
|
||||
|
|
|
|||
|
|
@ -56,16 +56,14 @@ const FieldList = ({
|
|||
<RiAddLine className='h-4 w-4 text-text-tertiary' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
{inputFields.length > 0 && (
|
||||
<FieldListContainer
|
||||
className='flex flex-col gap-y-1 px-4 pb-2'
|
||||
inputFields={inputFields}
|
||||
onEditField={handleOpenInputFieldEditor}
|
||||
onRemoveField={handleRemoveField}
|
||||
onListSortChange={handleListSortChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
)}
|
||||
<FieldListContainer
|
||||
className='flex flex-col gap-y-1 px-4 pb-1'
|
||||
inputFields={inputFields}
|
||||
onEditField={handleOpenInputFieldEditor}
|
||||
onRemoveField={handleRemoveField}
|
||||
onListSortChange={handleListSortChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
{showInputFieldEditor && (
|
||||
<InputFieldEditor
|
||||
show={showInputFieldEditor}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { InputVar } from '@/models/pipeline'
|
||||
|
||||
export type SortableItem = {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
} & InputVar
|
||||
|
|
|
|||
|
|
@ -2,22 +2,30 @@ import {
|
|||
memo,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { RiCloseLine } from '@remixicon/react'
|
||||
import { RiCloseLine, RiEyeLine } from '@remixicon/react'
|
||||
import type { Node } from '@/app/components/workflow/types'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import DialogWrapper from './dialog-wrapper'
|
||||
import FieldList from './field-list'
|
||||
import FooterTip from './footer-tip'
|
||||
import SharedInputs from './label-right-content/shared-inputs'
|
||||
import GlobalInputs from './label-right-content/global-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'
|
||||
// import produce from 'immer'
|
||||
import { useNodesSyncDraft } from '@/app/components/workflow/hooks'
|
||||
import type { InputVar, RAGPipelineVariables } from '@/models/pipeline'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import cn from '@/utils/classnames'
|
||||
import PreviewPanel from './preview'
|
||||
import { useDebounceFn, useUnmount } from 'ahooks'
|
||||
|
||||
type InputFieldDialogProps = {
|
||||
readonly?: boolean
|
||||
|
|
@ -32,8 +40,33 @@ const InputFieldDialog = ({
|
|||
const setShowInputFieldDialog = useStore(state => state.setShowInputFieldDialog)
|
||||
const ragPipelineVariables = useStore(state => state.ragPipelineVariables)
|
||||
const setRagPipelineVariables = useStore(state => state.setRagPipelineVariables)
|
||||
const [previewPanelOpen, setPreviewPanelOpen] = useState(false)
|
||||
|
||||
const getInputFieldsMap = () => {
|
||||
const inputFieldsMap: Record<string, InputVar[]> = {}
|
||||
ragPipelineVariables?.forEach((variable) => {
|
||||
const { belong_to_node_id: nodeId, ...varConfig } = variable
|
||||
if (inputFieldsMap[nodeId])
|
||||
inputFieldsMap[nodeId].push(varConfig)
|
||||
else
|
||||
inputFieldsMap[nodeId] = [varConfig]
|
||||
})
|
||||
return inputFieldsMap
|
||||
}
|
||||
const inputFieldsMap = useRef(getInputFieldsMap())
|
||||
|
||||
const { doSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
|
||||
useUnmount(async () => {
|
||||
await doSyncWorkflowDraft()
|
||||
})
|
||||
|
||||
const { run: syncWorkflowDraft } = useDebounceFn(() => {
|
||||
doSyncWorkflowDraft()
|
||||
}, {
|
||||
wait: 500,
|
||||
})
|
||||
|
||||
const datasourceNodeDataMap = useMemo(() => {
|
||||
const datasourceNodeDataMap: Record<string, DataSourceNodeType> = {}
|
||||
const datasourceNodes: Node<DataSourceNodeType>[] = nodes.filter(node => node.data.type === BlockEnum.DataSource)
|
||||
|
|
@ -44,25 +77,11 @@ const InputFieldDialog = ({
|
|||
return datasourceNodeDataMap
|
||||
}, [nodes])
|
||||
|
||||
const inputFieldsMap = useMemo(() => {
|
||||
const inputFieldsMap: Record<string, InputVar[]> = {}
|
||||
ragPipelineVariables?.forEach((variable) => {
|
||||
const { belong_to_node_id: nodeId, ...varConfig } = variable
|
||||
if (inputFieldsMap[nodeId])
|
||||
inputFieldsMap[nodeId].push(varConfig)
|
||||
else
|
||||
inputFieldsMap[nodeId] = [varConfig]
|
||||
})
|
||||
return inputFieldsMap
|
||||
}, [ragPipelineVariables])
|
||||
|
||||
const updateInputFields = useCallback(async (key: string, value: InputVar[]) => {
|
||||
const NewInputFieldsMap = produce(inputFieldsMap, (draft) => {
|
||||
draft[key] = value
|
||||
})
|
||||
const updateInputFields = useCallback((key: string, value: InputVar[]) => {
|
||||
inputFieldsMap.current[key] = value
|
||||
const newRagPipelineVariables: RAGPipelineVariables = []
|
||||
Object.keys(NewInputFieldsMap).forEach((key) => {
|
||||
const inputFields = NewInputFieldsMap[key]
|
||||
Object.keys(inputFieldsMap.current).forEach((key) => {
|
||||
const inputFields = inputFieldsMap.current[key]
|
||||
inputFields.forEach((inputField) => {
|
||||
newRagPipelineVariables.push({
|
||||
...inputField,
|
||||
|
|
@ -71,65 +90,101 @@ const InputFieldDialog = ({
|
|||
})
|
||||
})
|
||||
setRagPipelineVariables?.(newRagPipelineVariables)
|
||||
await doSyncWorkflowDraft()
|
||||
}, [doSyncWorkflowDraft, inputFieldsMap, setRagPipelineVariables])
|
||||
syncWorkflowDraft()
|
||||
}, [setRagPipelineVariables, syncWorkflowDraft])
|
||||
|
||||
const closePanel = useCallback(() => {
|
||||
setShowInputFieldDialog?.(false)
|
||||
}, [setShowInputFieldDialog])
|
||||
|
||||
const togglePreviewPanel = useCallback(() => {
|
||||
setPreviewPanelOpen(prev => !prev)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<DialogWrapper
|
||||
show={!!showInputFieldDialog}
|
||||
onClose={closePanel}
|
||||
>
|
||||
<div className='flex grow flex-col'>
|
||||
<div className='flex items-center p-4 pb-0'>
|
||||
<div className='system-xl-semibold grow'>
|
||||
{t('datasetPipeline.inputFieldPanel.title')}
|
||||
<>
|
||||
<DialogWrapper
|
||||
show={!!showInputFieldDialog}
|
||||
onClose={closePanel}
|
||||
>
|
||||
<div className='flex grow flex-col'>
|
||||
<div className='flex items-center p-4 pb-0'>
|
||||
<div className='system-xl-semibold grow'>
|
||||
{t('datasetPipeline.inputFieldPanel.title')}
|
||||
</div>
|
||||
<Button
|
||||
variant={'ghost'}
|
||||
size='small'
|
||||
className={cn(
|
||||
'shrink-0 gap-x-px px-1.5',
|
||||
previewPanelOpen && 'bg-state-accent-active text-text-accent',
|
||||
)}
|
||||
onClick={togglePreviewPanel}
|
||||
>
|
||||
<RiEyeLine className='size-3.5' />
|
||||
<span className='px-[3px]'>{t('datasetPipeline.operations.preview')}</span>
|
||||
</Button>
|
||||
<Divider type='vertical' className='mx-1 h-3' />
|
||||
<button
|
||||
type='button'
|
||||
className='flex size-6 shrink-0 items-center justify-center p-0.5'
|
||||
onClick={closePanel}
|
||||
>
|
||||
<RiCloseLine className='size-4 text-text-tertiary' />
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type='button'
|
||||
className='flex size-6 shrink-0 items-center justify-center p-0.5'
|
||||
onClick={closePanel}
|
||||
>
|
||||
<RiCloseLine className='size-4 text-text-tertiary' />
|
||||
</button>
|
||||
<div className='system-sm-regular px-4 pb-2 pt-1 text-text-tertiary'>
|
||||
{t('datasetPipeline.inputFieldPanel.description')}
|
||||
</div>
|
||||
<div className='flex grow flex-col overflow-y-auto'>
|
||||
{/* Unique Inputs for Each Entrance */}
|
||||
<div className='flex h-6 items-center gap-x-0.5 px-4 pt-2'>
|
||||
<span className='system-sm-semibold-uppercase text-text-secondary'>
|
||||
{t('datasetPipeline.inputFieldPanel.uniqueInputs.title')}
|
||||
</span>
|
||||
<Tooltip
|
||||
popupContent={t('datasetPipeline.inputFieldPanel.uniqueInputs.tooltip')}
|
||||
popupClassName='max-w-[240px]'
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col gap-y-1 py-1'>
|
||||
{
|
||||
Object.keys(datasourceNodeDataMap).map((key) => {
|
||||
const inputFields = inputFieldsMap.current[key] || []
|
||||
return (
|
||||
<FieldList
|
||||
key={key}
|
||||
nodeId={key}
|
||||
LabelRightContent={<Datasource nodeData={datasourceNodeDataMap[key]} />}
|
||||
inputFields={inputFields}
|
||||
readonly={readonly}
|
||||
labelClassName='pt-1 pb-1'
|
||||
handleInputFieldsChange={updateInputFields}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
{/* Global Inputs */}
|
||||
<FieldList
|
||||
nodeId='shared'
|
||||
LabelRightContent={<GlobalInputs />}
|
||||
inputFields={inputFieldsMap.current.shared || []}
|
||||
readonly={readonly}
|
||||
labelClassName='pt-2 pb-1'
|
||||
handleInputFieldsChange={updateInputFields}
|
||||
/>
|
||||
</div>
|
||||
<FooterTip />
|
||||
</div>
|
||||
<div className='system-sm-regular px-4 py-1 text-text-tertiary'>
|
||||
{t('datasetPipeline.inputFieldPanel.description')}
|
||||
</div>
|
||||
<div className='flex grow flex-col overflow-y-auto'>
|
||||
{/* Datasources Inputs */}
|
||||
{
|
||||
Object.keys(datasourceNodeDataMap).map((key) => {
|
||||
const inputFields = inputFieldsMap[key] || []
|
||||
return (
|
||||
<FieldList
|
||||
key={key}
|
||||
nodeId={key}
|
||||
LabelRightContent={<Datasource nodeData={datasourceNodeDataMap[key]} />}
|
||||
inputFields={inputFields}
|
||||
readonly={readonly}
|
||||
labelClassName='pt-2 pb-1'
|
||||
handleInputFieldsChange={updateInputFields}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
{/* Shared Inputs */}
|
||||
<FieldList
|
||||
nodeId='shared'
|
||||
LabelRightContent={<SharedInputs />}
|
||||
inputFields={inputFieldsMap.shared || []}
|
||||
readonly={readonly}
|
||||
labelClassName='pt-1 pb-2'
|
||||
handleInputFieldsChange={updateInputFields}
|
||||
/>
|
||||
</div>
|
||||
<FooterTip />
|
||||
</div>
|
||||
</DialogWrapper>
|
||||
</DialogWrapper>
|
||||
{previewPanelOpen && (
|
||||
<PreviewPanel
|
||||
show={previewPanelOpen}
|
||||
onClose={togglePreviewPanel}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@ import Tooltip from '@/app/components/base/tooltip'
|
|||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const SharedInputs = () => {
|
||||
const GlobalInputs = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex items-center gap-x-1'>
|
||||
<span className='system-sm-semibold-uppercase text-text-secondary'>
|
||||
{t('datasetPipeline.inputFieldPanel.sharedInputs.title')}
|
||||
{t('datasetPipeline.inputFieldPanel.globalInputs.title')}
|
||||
</span>
|
||||
<Tooltip
|
||||
popupContent={t('datasetPipeline.inputFieldPanel.sharedInputs.tooltip')}
|
||||
popupClassName='!w-[300px]'
|
||||
popupContent={t('datasetPipeline.inputFieldPanel.globalInputs.tooltip')}
|
||||
popupClassName='w-[240px]'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(SharedInputs)
|
||||
export default React.memo(GlobalInputs)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const DataSource = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex flex-col'>
|
||||
<div className='system-sm-semibold-uppercase px-4 pt-2 text-text-secondary'>
|
||||
{t('datasetPipeline.inputFieldPanel.preview.stepOneTitle')}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(DataSource)
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import { Fragment, useCallback } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { Dialog, DialogPanel, Transition, TransitionChild } from '@headlessui/react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type DialogWrapperProps = {
|
||||
className?: string
|
||||
panelWrapperClassName?: string
|
||||
children: ReactNode
|
||||
show: boolean
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
const DialogWrapper = ({
|
||||
className,
|
||||
panelWrapperClassName,
|
||||
children,
|
||||
show,
|
||||
onClose,
|
||||
}: DialogWrapperProps) => {
|
||||
const close = useCallback(() => onClose?.(), [onClose])
|
||||
return (
|
||||
<Transition appear show={show} as={Fragment}>
|
||||
<Dialog as='div' className='relative z-40' onClose={close}>
|
||||
<TransitionChild>
|
||||
<div className={cn(
|
||||
'fixed inset-0 bg-black/25',
|
||||
'data-[closed]:opacity-0',
|
||||
'data-[enter]:opacity-100 data-[enter]:duration-300 data-[enter]:ease-out',
|
||||
'data-[leave]:opacity-0 data-[leave]:duration-200 data-[leave]:ease-in',
|
||||
)} />
|
||||
</TransitionChild>
|
||||
|
||||
<div className='fixed inset-0'>
|
||||
<div className={cn('flex min-h-full flex-col items-end justify-start pb-1 pt-[116px]', panelWrapperClassName)}>
|
||||
<TransitionChild>
|
||||
<DialogPanel className={cn(
|
||||
'relative flex w-[480px] grow flex-col overflow-hidden rounded-2xl border-y-[0.5px] border-l-[0.5px] border-components-panel-border bg-components-panel-bg p-0 shadow-xl shadow-shadow-shadow-5 transition-all',
|
||||
'data-[closed]:scale-95 data-[closed]:opacity-0',
|
||||
'data-[enter]:scale-100 data-[enter]:opacity-100 data-[enter]:duration-300 data-[enter]:ease-out',
|
||||
'data-[leave]:scale-95 data-[leave]:opacity-0 data-[leave]:duration-200 data-[leave]:ease-in',
|
||||
className,
|
||||
)}>
|
||||
{children}
|
||||
</DialogPanel>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition >
|
||||
)
|
||||
}
|
||||
|
||||
export default DialogWrapper
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { RiCloseLine } from '@remixicon/react'
|
||||
import DialogWrapper from './dialog-wrapper'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
|
||||
type PreviewPanelProps = {
|
||||
show: boolean
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const PreviewPanel = ({
|
||||
show,
|
||||
onClose,
|
||||
}: PreviewPanelProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<DialogWrapper
|
||||
show={show}
|
||||
onClose={onClose}
|
||||
panelWrapperClassName='pr-[424px]'
|
||||
>
|
||||
<div className='flex items-center gap-x-2 px-4 pt-1'>
|
||||
<div className='grow py-1'>
|
||||
<Badge className='border-text-accent-secondary bg-components-badge-bg-dimm text-text-accent-secondary'>
|
||||
{t('datasetPipeline.operations.preview')}
|
||||
</Badge>
|
||||
</div>
|
||||
<button
|
||||
type='button'
|
||||
className='flex size-6 shrink-0 items-center justify-center'
|
||||
onClick={onClose}
|
||||
>
|
||||
<RiCloseLine className='size-4 text-text-tertiary' />
|
||||
</button>
|
||||
</div>
|
||||
</DialogWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default PreviewPanel
|
||||
|
|
@ -27,6 +27,8 @@ import type { PublishWorkflowParams } from '@/types/workflow'
|
|||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import { useParams, useRouter } from 'next/navigation'
|
||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||
import { useInvalid } from '@/service/use-base'
|
||||
import { publishedPipelineInfoQueryKeyPrefix } from '@/service/use-pipeline'
|
||||
|
||||
const PUBLISH_SHORTCUT = ['⌘', '⇧', 'P']
|
||||
|
||||
|
|
@ -45,6 +47,8 @@ const Popup = () => {
|
|||
const { notify } = useToastContext()
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
||||
const invalidPublishedPipelineInfo = useInvalid([...publishedPipelineInfoQueryKeyPrefix, pipelineId])
|
||||
|
||||
const handlePublish = useCallback(async (params?: PublishWorkflowParams) => {
|
||||
if (await handleCheckBeforePublish()) {
|
||||
const res = await publishWorkflow({
|
||||
|
|
@ -58,12 +62,13 @@ const Popup = () => {
|
|||
notify({ type: 'success', message: t('common.api.actionSuccess') })
|
||||
workflowStore.getState().setPublishedAt(res.created_at)
|
||||
mutateDatasetRes?.()
|
||||
invalidPublishedPipelineInfo()
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error('Checklist failed')
|
||||
}
|
||||
}, [handleCheckBeforePublish, publishWorkflow, pipelineId, notify, t, workflowStore, mutateDatasetRes])
|
||||
}, [handleCheckBeforePublish, publishWorkflow, pipelineId, notify, t, workflowStore, mutateDatasetRes, invalidPublishedPipelineInfo])
|
||||
|
||||
useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.shift.p`, (e) => {
|
||||
e.preventDefault()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ const translation = {
|
|||
process: 'Process',
|
||||
dataSource: 'Data Source',
|
||||
saveAndProcess: 'Save & Process',
|
||||
preview: 'Preview',
|
||||
},
|
||||
knowledgeNameAndIcon: 'Knowledge name & icon',
|
||||
knowledgeNameAndIconPlaceholder: 'Please enter the name of the Knowledge Base',
|
||||
|
|
@ -66,12 +67,20 @@ const translation = {
|
|||
inputFieldPanel: {
|
||||
title: 'User Input Fields',
|
||||
description: '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.',
|
||||
sharedInputs: {
|
||||
title: 'Shared Inputs',
|
||||
tooltip: '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.',
|
||||
uniqueInputs: {
|
||||
title: 'Unique Inputs for Each Entrance',
|
||||
tooltip: 'Unique Inputs are only accessible to the selected data source and its downstream nodes. Users won\'t need to fill it in when choosing other data sources. Only input fields referenced by data source variables will appear in the first step(Data Source). All other fields will be shown in the second step(Process Documents).',
|
||||
},
|
||||
globalInputs: {
|
||||
title: 'Global Inputs for All Entrances',
|
||||
tooltip: 'Global Inputs are shared across all nodes. Users will need to fill them in when selecting any data source. For example, fields like delimiter and maximum chunk length can be uniformly applied across multiple data sources. Only input fields referenced by Data Source variables appear in the first step (Data Source). All other fields show up in the second step (Process Documents).',
|
||||
},
|
||||
addInputField: 'Add Input Field',
|
||||
editInputField: 'Edit Input Field',
|
||||
preview: {
|
||||
stepOneTitle: 'Data Source',
|
||||
stepTwoTitle: 'Process Documents',
|
||||
},
|
||||
},
|
||||
addDocuments: {
|
||||
title: 'Add Documents',
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ const translation = {
|
|||
process: '处理',
|
||||
dataSource: '数据源',
|
||||
saveAndProcess: '保存并处理',
|
||||
preview: '预览',
|
||||
},
|
||||
knowledgeNameAndIcon: '知识库名称和图标',
|
||||
knowledgeNameAndIconPlaceholder: '请输入知识库名称',
|
||||
|
|
@ -66,12 +67,20 @@ const translation = {
|
|||
inputFieldPanel: {
|
||||
title: '用户输入字段',
|
||||
description: '用户输入字段用于定义和收集流水线执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。',
|
||||
sharedInputs: {
|
||||
title: '共享输入',
|
||||
tooltip: '共享输入可被数据源中的所有下游节点使用。例如,在处理来自多个来源的文档时,delimiter(分隔符)和 maximum chunk length(最大分块长度)等变量可以统一应用。',
|
||||
uniqueInputs: {
|
||||
title: '非共享输入',
|
||||
tooltip: '非共享输入只能被选定的数据源及其下游节点访问。用户在选择其他数据源时不需要填写它。只有数据源变量引用的输入字段才会出现在第一步(数据源)中。所有其他字段将在第二步(Process Documents)中显示。',
|
||||
},
|
||||
globalInputs: {
|
||||
title: '全局共享输入',
|
||||
tooltip: '全局共享输入在所有节点之间共享。用户在选择任何数据源时都需要填写它们。例如,像分隔符(delimiter)和最大块长度(Maximum Chunk Length)这样的字段可以跨多个数据源统一应用。只有数据源变量引用的输入字段才会出现在第一步(数据源)中。所有其他字段都显示在第二步(Process Documents)中。',
|
||||
},
|
||||
addInputField: '添加输入字段',
|
||||
editInputField: '编辑输入字段',
|
||||
preview: {
|
||||
stepOneTitle: '数据源',
|
||||
stepTwoTitle: '处理文档',
|
||||
},
|
||||
},
|
||||
addDocuments: {
|
||||
title: '添加文档',
|
||||
|
|
|
|||
|
|
@ -179,9 +179,11 @@ export const useDataSourceList = (enabled: boolean, onSuccess?: (v: DataSourceIt
|
|||
})
|
||||
}
|
||||
|
||||
export const publishedPipelineInfoQueryKeyPrefix = [NAME_SPACE, 'published-pipeline']
|
||||
|
||||
export const usePublishedPipelineInfo = (pipelineId: string) => {
|
||||
return useQuery<PublishedPipelineInfoResponse>({
|
||||
queryKey: [NAME_SPACE, 'published-pipeline', pipelineId],
|
||||
queryKey: [...publishedPipelineInfoQueryKeyPrefix, pipelineId],
|
||||
queryFn: () => {
|
||||
return get<PublishedPipelineInfoResponse>(`/rag/pipelines/${pipelineId}/workflows/publish`)
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue