dify
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import React from 'react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiArrowLeftLine } from '@remixicon/react'
|
||||
|
||||
type ActionsProps = {
|
||||
onBack: () => void
|
||||
runDisabled?: boolean
|
||||
onProcess: () => void
|
||||
}
|
||||
|
||||
const Actions = ({
|
||||
onBack,
|
||||
runDisabled,
|
||||
onProcess,
|
||||
}: ActionsProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex items-center justify-between'>
|
||||
<Button
|
||||
variant='secondary'
|
||||
onClick={onBack}
|
||||
className='gap-x-0.5'
|
||||
>
|
||||
<RiArrowLeftLine className='size-4' />
|
||||
<span className='px-0.5'>{t('datasetPipeline.operations.dataSource')}</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant='primary'
|
||||
disabled={runDisabled}
|
||||
onClick={onProcess}
|
||||
>
|
||||
{t('datasetPipeline.operations.saveAndProcess')}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Actions)
|
||||
@@ -0,0 +1,96 @@
|
||||
import { useAppForm } from '@/app/components/base/form'
|
||||
import BaseField from '@/app/components/base/form/form-scenarios/base/field'
|
||||
import type { BaseConfiguration } from '@/app/components/base/form/form-scenarios/base/types'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useCallback, useImperativeHandle } from 'react'
|
||||
import type { ZodSchema } from 'zod'
|
||||
import Header from './header'
|
||||
|
||||
type OptionsProps = {
|
||||
initialData: Record<string, any>
|
||||
configurations: BaseConfiguration[]
|
||||
schema: ZodSchema
|
||||
onSubmit: (data: Record<string, any>) => void
|
||||
onPreview: () => void
|
||||
ref: React.RefObject<any>
|
||||
isRunning: boolean
|
||||
}
|
||||
|
||||
const Form = ({
|
||||
initialData,
|
||||
configurations,
|
||||
schema,
|
||||
onSubmit,
|
||||
onPreview,
|
||||
ref,
|
||||
isRunning,
|
||||
}: OptionsProps) => {
|
||||
const form = useAppForm({
|
||||
defaultValues: initialData,
|
||||
validators: {
|
||||
onSubmit: ({ value }) => {
|
||||
const result = schema.safeParse(value)
|
||||
if (!result.success) {
|
||||
const issues = result.error.issues
|
||||
const firstIssue = issues[0]
|
||||
const errorMessage = `"${firstIssue.path.join('.')}" ${firstIssue.message}`
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: errorMessage,
|
||||
})
|
||||
return errorMessage
|
||||
}
|
||||
return undefined
|
||||
},
|
||||
},
|
||||
onSubmit: ({ value }) => {
|
||||
onSubmit(value)
|
||||
},
|
||||
})
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
submit: () => {
|
||||
form.handleSubmit()
|
||||
},
|
||||
}
|
||||
}, [form])
|
||||
|
||||
const handleReset = useCallback(() => {
|
||||
form.reset()
|
||||
}, [form])
|
||||
|
||||
return (
|
||||
<form
|
||||
className='flex w-full flex-col rounded-lg border border-components-panel-border bg-components-panel-bg'
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
form.handleSubmit()
|
||||
}}
|
||||
>
|
||||
<form.Subscribe
|
||||
selector={state => state.isDirty}
|
||||
children={isDirty => (
|
||||
<Header
|
||||
onReset={handleReset}
|
||||
resetDisabled={!isDirty}
|
||||
onPreview={onPreview}
|
||||
previewDisabled={isRunning}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className='flex flex-col gap-3 border-t border-divider-subtle px-4 py-3'>
|
||||
{configurations.map((config, index) => {
|
||||
const FieldComponent = BaseField({
|
||||
initialData,
|
||||
config,
|
||||
})
|
||||
return <FieldComponent key={index} form={form} />
|
||||
})}
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default Form
|
||||
@@ -0,0 +1,42 @@
|
||||
import React from 'react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiSearchEyeLine } from '@remixicon/react'
|
||||
|
||||
type HeaderProps = {
|
||||
onReset: () => void
|
||||
resetDisabled: boolean
|
||||
previewDisabled: boolean
|
||||
onPreview?: () => void
|
||||
}
|
||||
|
||||
const Header = ({
|
||||
onReset,
|
||||
resetDisabled,
|
||||
previewDisabled,
|
||||
onPreview,
|
||||
}: HeaderProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='flex items-center gap-x-1 px-4 py-2'>
|
||||
<div className='system-sm-semibold-uppercase grow text-text-secondary'>
|
||||
{t('datasetPipeline.addDocuments.stepTwo.chunkSettings')}
|
||||
</div>
|
||||
<Button variant='ghost' disabled={resetDisabled} onClick={onReset}>
|
||||
{t('common.operation.reset')}
|
||||
</Button>
|
||||
<Button
|
||||
variant='secondary-accent'
|
||||
onClick={onPreview}
|
||||
className='gap-x-0.5'
|
||||
disabled={previewDisabled}
|
||||
>
|
||||
<RiSearchEyeLine className='size-4' />
|
||||
<span className='px-0.5'>{t('datasetPipeline.addDocuments.stepTwo.previewChunks')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Header)
|
||||
@@ -0,0 +1,15 @@
|
||||
import { usePublishedPipelineProcessingParams } from '@/service/use-pipeline'
|
||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||
|
||||
export const useInputVariables = (datasourceNodeId: string) => {
|
||||
const pipelineId = useDatasetDetailContextWithSelector(state => state.dataset?.pipeline_id)
|
||||
const { data: paramsConfig, isFetching: isFetchingParams } = usePublishedPipelineProcessingParams({
|
||||
pipeline_id: pipelineId!,
|
||||
node_id: datasourceNodeId,
|
||||
})
|
||||
|
||||
return {
|
||||
paramsConfig,
|
||||
isFetchingParams,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from 'react'
|
||||
import { generateZodSchema } from '@/app/components/base/form/form-scenarios/base/utils'
|
||||
import { useInputVariables } from './hooks'
|
||||
import Form from './form'
|
||||
import Actions from './actions'
|
||||
import { useConfigurations, useInitialData } from '@/app/components/rag-pipeline/hooks/use-input-fields'
|
||||
|
||||
type ProcessDocumentsProps = {
|
||||
dataSourceNodeId: string
|
||||
ref: React.RefObject<any>
|
||||
isRunning: boolean
|
||||
onProcess: () => void
|
||||
onPreview: () => void
|
||||
onSubmit: (data: Record<string, any>) => void
|
||||
onBack: () => void
|
||||
}
|
||||
|
||||
const ProcessDocuments = ({
|
||||
dataSourceNodeId,
|
||||
isRunning,
|
||||
onProcess,
|
||||
onPreview,
|
||||
onSubmit,
|
||||
onBack,
|
||||
ref,
|
||||
}: ProcessDocumentsProps) => {
|
||||
const { isFetchingParams, paramsConfig } = useInputVariables(dataSourceNodeId)
|
||||
const initialData = useInitialData(paramsConfig?.variables || [])
|
||||
const configurations = useConfigurations(paramsConfig?.variables || [])
|
||||
const schema = generateZodSchema(configurations)
|
||||
|
||||
return (
|
||||
<div className='flex flex-col gap-y-4 pt-4'>
|
||||
<Form
|
||||
ref={ref}
|
||||
initialData={initialData}
|
||||
configurations={configurations}
|
||||
schema={schema}
|
||||
onSubmit={onSubmit}
|
||||
onPreview={onPreview}
|
||||
isRunning={isRunning}
|
||||
/>
|
||||
<Actions runDisabled={isFetchingParams || isRunning} onBack={onBack} onProcess={onProcess} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(ProcessDocuments)
|
||||
Reference in New Issue
Block a user