### What problem does this PR solve? Feat: Add DynamicVariableForm with shadcn-ui. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.17.0
| } from '@xyflow/react'; | } from '@xyflow/react'; | ||||
| import '@xyflow/react/dist/style.css'; | import '@xyflow/react/dist/style.css'; | ||||
| // import ChatDrawer from '../chat/drawer'; | // import ChatDrawer from '../chat/drawer'; | ||||
| import FormDrawer from '../form-drawer'; | |||||
| import FormDrawer from '../form-drawer/next'; | |||||
| import { | import { | ||||
| useHandleDrop, | useHandleDrop, | ||||
| useSelectCanvasData, | useSelectCanvasData, |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { IModalProps } from '@/interfaces/common'; | import { IModalProps } from '@/interfaces/common'; | ||||
| import { CloseOutlined } from '@ant-design/icons'; | |||||
| import { Drawer, Flex, Form, Input } from 'antd'; | |||||
| import { Flex, Form, Input } from 'antd'; | |||||
| import { get, isPlainObject, lowerFirst } from 'lodash'; | import { get, isPlainObject, lowerFirst } from 'lodash'; | ||||
| import { Play } from 'lucide-react'; | import { Play } from 'lucide-react'; | ||||
| import { useEffect, useRef } from 'react'; | import { useEffect, useRef } from 'react'; | ||||
| import PubMedForm from '../form/pubmed-form'; | import PubMedForm from '../form/pubmed-form'; | ||||
| import QWeatherForm from '../form/qweather-form'; | import QWeatherForm from '../form/qweather-form'; | ||||
| import RelevantForm from '../form/relevant-form'; | import RelevantForm from '../form/relevant-form'; | ||||
| import RetrievalForm from '../form/retrieval-form'; | |||||
| import RetrievalForm from '../form/retrieval-form/next'; | |||||
| import RewriteQuestionForm from '../form/rewrite-question-form'; | import RewriteQuestionForm from '../form/rewrite-question-form'; | ||||
| import SwitchForm from '../form/switch-form'; | import SwitchForm from '../form/switch-form'; | ||||
| import TemplateForm from '../form/template-form'; | import TemplateForm from '../form/template-form'; | ||||
| import OperatorIcon from '../operator-icon'; | import OperatorIcon from '../operator-icon'; | ||||
| import { | import { | ||||
| buildCategorizeListFromObject, | buildCategorizeListFromObject, | ||||
| getDrawerWidth, | |||||
| needsSingleStepDebugging, | needsSingleStepDebugging, | ||||
| } from '../utils'; | } from '../utils'; | ||||
| import SingleDebugDrawer from './single-debug-drawer'; | |||||
| import { Sheet, SheetContent, SheetHeader } from '@/components/ui/sheet'; | |||||
| import { RAGFlowNodeType } from '@/interfaces/database/flow'; | import { RAGFlowNodeType } from '@/interfaces/database/flow'; | ||||
| import { FlowFormContext } from '../context'; | import { FlowFormContext } from '../context'; | ||||
| import { RunTooltip } from '../flow-tooltip'; | import { RunTooltip } from '../flow-tooltip'; | ||||
| import IterationForm from '../form/iteration-from'; | import IterationForm from '../form/iteration-from'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| interface IProps { | interface IProps { | ||||
| }, [visible, form, node?.data?.form, node?.id, node, operatorName]); | }, [visible, form, node?.data?.form, node?.id, node, operatorName]); | ||||
| return ( | return ( | ||||
| <Drawer | |||||
| title={ | |||||
| <Flex vertical> | |||||
| <Flex gap={'middle'} align="center"> | |||||
| <OperatorIcon | |||||
| name={operatorName} | |||||
| color={operatorMap[operatorName]?.color} | |||||
| ></OperatorIcon> | |||||
| <Flex align="center" gap={'small'} flex={1}> | |||||
| <label htmlFor="" className={styles.title}> | |||||
| {t('title')} | |||||
| </label> | |||||
| {node?.id === BeginId ? ( | |||||
| <span>{t(BeginId)}</span> | |||||
| ) : ( | |||||
| <Input | |||||
| value={name} | |||||
| onBlur={handleNameBlur} | |||||
| onChange={handleNameChange} | |||||
| ></Input> | |||||
| <Sheet onOpenChange={hideModal} open={visible}> | |||||
| <SheetContent> | |||||
| <SheetHeader> | |||||
| <Flex vertical> | |||||
| <Flex gap={'middle'} align="center"> | |||||
| <OperatorIcon | |||||
| name={operatorName} | |||||
| color={operatorMap[operatorName]?.color} | |||||
| ></OperatorIcon> | |||||
| <Flex align="center" gap={'small'} flex={1}> | |||||
| <label htmlFor="" className={styles.title}> | |||||
| {t('title')} | |||||
| </label> | |||||
| {node?.id === BeginId ? ( | |||||
| <span>{t(BeginId)}</span> | |||||
| ) : ( | |||||
| <Input | |||||
| value={name} | |||||
| onBlur={handleNameBlur} | |||||
| onChange={handleNameChange} | |||||
| ></Input> | |||||
| )} | |||||
| </Flex> | |||||
| {needsSingleStepDebugging(operatorName) && ( | |||||
| <RunTooltip> | |||||
| <Play | |||||
| className="size-5 cursor-pointer" | |||||
| onClick={showSingleDebugDrawer} | |||||
| /> | |||||
| </RunTooltip> | |||||
| )} | )} | ||||
| {/* <CloseOutlined onClick={hideModal} /> */} | |||||
| </Flex> | </Flex> | ||||
| {needsSingleStepDebugging(operatorName) && ( | |||||
| <RunTooltip> | |||||
| <Play | |||||
| className="size-5 cursor-pointer" | |||||
| onClick={showSingleDebugDrawer} | |||||
| /> | |||||
| </RunTooltip> | |||||
| )} | |||||
| <CloseOutlined onClick={hideModal} /> | |||||
| <span className={styles.operatorDescription}> | |||||
| {t(`${lowerFirst(operatorName)}Description`)} | |||||
| </span> | |||||
| </Flex> | </Flex> | ||||
| <span className={styles.operatorDescription}> | |||||
| {t(`${lowerFirst(operatorName)}Description`)} | |||||
| </span> | |||||
| </Flex> | |||||
| } | |||||
| placement="right" | |||||
| onClose={hideModal} | |||||
| open={visible} | |||||
| getContainer={false} | |||||
| mask={false} | |||||
| width={getDrawerWidth()} | |||||
| closeIcon={null} | |||||
| rootClassName={styles.formDrawer} | |||||
| > | |||||
| <section className={styles.formWrapper}> | |||||
| {visible && ( | |||||
| <FlowFormContext.Provider value={node}> | |||||
| <OperatorForm | |||||
| onValuesChange={handleValuesChange} | |||||
| form={form} | |||||
| node={node} | |||||
| ></OperatorForm> | |||||
| </FlowFormContext.Provider> | |||||
| )} | |||||
| </section> | |||||
| {singleDebugDrawerVisible && ( | |||||
| </SheetHeader> | |||||
| <section className={styles.formWrapper}> | |||||
| {visible && ( | |||||
| <FlowFormContext.Provider value={node}> | |||||
| <OperatorForm | |||||
| onValuesChange={handleValuesChange} | |||||
| form={form} | |||||
| node={node} | |||||
| ></OperatorForm> | |||||
| </FlowFormContext.Provider> | |||||
| )} | |||||
| </section> | |||||
| </SheetContent> | |||||
| {/* {singleDebugDrawerVisible && ( | |||||
| <SingleDebugDrawer | <SingleDebugDrawer | ||||
| visible={singleDebugDrawerVisible} | visible={singleDebugDrawerVisible} | ||||
| hideModal={hideSingleDebugDrawer} | hideModal={hideSingleDebugDrawer} | ||||
| componentId={node?.id} | componentId={node?.id} | ||||
| ></SingleDebugDrawer> | ></SingleDebugDrawer> | ||||
| )} | |||||
| </Drawer> | |||||
| )} */} | |||||
| </Sheet> | |||||
| ); | ); | ||||
| }; | }; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | |||||
| import { IModalProps } from '@/interfaces/common'; | |||||
| import { CloseOutlined } from '@ant-design/icons'; | |||||
| import { Flex, Input } from 'antd'; | |||||
| import { get, isPlainObject, lowerFirst } from 'lodash'; | |||||
| import { Play } from 'lucide-react'; | |||||
| import { useEffect, useRef } from 'react'; | |||||
| import { BeginId, Operator, operatorMap } from '../constant'; | |||||
| import { useHandleFormValuesChange, useHandleNodeNameChange } from '../hooks'; | |||||
| import OperatorIcon from '../operator-icon'; | |||||
| import { | |||||
| buildCategorizeListFromObject, | |||||
| needsSingleStepDebugging, | |||||
| } from '../utils'; | |||||
| import SingleDebugDrawer from './single-debug-drawer'; | |||||
| import { Sheet, SheetContent, SheetHeader } from '@/components/ui/sheet'; | |||||
| import { RAGFlowNodeType } from '@/interfaces/database/flow'; | |||||
| import { FlowFormContext } from '../context'; | |||||
| import { RunTooltip } from '../flow-tooltip'; | |||||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||||
| import { useForm } from 'react-hook-form'; | |||||
| import { useFormConfigMap } from './use-form-config-map'; | |||||
| interface IProps { | |||||
| node?: RAGFlowNodeType; | |||||
| singleDebugDrawerVisible: IModalProps<any>['visible']; | |||||
| hideSingleDebugDrawer: IModalProps<any>['hideModal']; | |||||
| showSingleDebugDrawer: IModalProps<any>['showModal']; | |||||
| } | |||||
| const EmptyContent = () => <div></div>; | |||||
| const FormDrawer = ({ | |||||
| visible, | |||||
| hideModal, | |||||
| node, | |||||
| singleDebugDrawerVisible, | |||||
| hideSingleDebugDrawer, | |||||
| showSingleDebugDrawer, | |||||
| }: IModalProps<any> & IProps) => { | |||||
| const operatorName: Operator = node?.data.label as Operator; | |||||
| const FormConfigMap = useFormConfigMap(); | |||||
| const currentFormMap = FormConfigMap[operatorName]; | |||||
| const OperatorForm = currentFormMap.component ?? EmptyContent; | |||||
| const form = useForm({ | |||||
| defaultValues: currentFormMap.defaultValues, | |||||
| resolver: zodResolver(currentFormMap.schema), | |||||
| }); | |||||
| const { name, handleNameBlur, handleNameChange } = useHandleNodeNameChange({ | |||||
| id: node?.id, | |||||
| data: node?.data, | |||||
| }); | |||||
| const previousId = useRef<string | undefined>(node?.id); | |||||
| const { t } = useTranslate('flow'); | |||||
| const { handleValuesChange } = useHandleFormValuesChange(node?.id); | |||||
| useEffect(() => { | |||||
| if (visible) { | |||||
| if (node?.id !== previousId.current) { | |||||
| // form.resetFields(); | |||||
| form.reset(); | |||||
| form.clearErrors(); | |||||
| } | |||||
| if (operatorName === Operator.Categorize) { | |||||
| const items = buildCategorizeListFromObject( | |||||
| get(node, 'data.form.category_description', {}), | |||||
| ); | |||||
| const formData = node?.data?.form; | |||||
| if (isPlainObject(formData)) { | |||||
| // form.setFieldsValue({ ...formData, items }); | |||||
| form.reset({ ...formData, items }); | |||||
| } | |||||
| } else { | |||||
| // form.setFieldsValue(node?.data?.form); | |||||
| form.reset(node?.data?.form); | |||||
| } | |||||
| previousId.current = node?.id; | |||||
| } | |||||
| }, [visible, form, node?.data?.form, node?.id, node, operatorName]); | |||||
| return ( | |||||
| <Sheet onOpenChange={hideModal} open={visible}> | |||||
| <SheetContent className="bg-white"> | |||||
| <SheetHeader> | |||||
| <Flex vertical> | |||||
| <Flex gap={'middle'} align="center"> | |||||
| <OperatorIcon | |||||
| name={operatorName} | |||||
| color={operatorMap[operatorName]?.color} | |||||
| ></OperatorIcon> | |||||
| <Flex align="center" gap={'small'} flex={1}> | |||||
| <label htmlFor="">{t('title')}</label> | |||||
| {node?.id === BeginId ? ( | |||||
| <span>{t(BeginId)}</span> | |||||
| ) : ( | |||||
| <Input | |||||
| value={name} | |||||
| onBlur={handleNameBlur} | |||||
| onChange={handleNameChange} | |||||
| ></Input> | |||||
| )} | |||||
| </Flex> | |||||
| {needsSingleStepDebugging(operatorName) && ( | |||||
| <RunTooltip> | |||||
| <Play | |||||
| className="size-5 cursor-pointer" | |||||
| onClick={showSingleDebugDrawer} | |||||
| /> | |||||
| </RunTooltip> | |||||
| )} | |||||
| <CloseOutlined onClick={hideModal} /> | |||||
| </Flex> | |||||
| <span>{t(`${lowerFirst(operatorName)}Description`)}</span> | |||||
| </Flex> | |||||
| </SheetHeader> | |||||
| <section> | |||||
| {visible && ( | |||||
| <FlowFormContext.Provider value={node}> | |||||
| <OperatorForm | |||||
| onValuesChange={handleValuesChange} | |||||
| form={form} | |||||
| node={node} | |||||
| ></OperatorForm> | |||||
| </FlowFormContext.Provider> | |||||
| )} | |||||
| </section> | |||||
| </SheetContent> | |||||
| {singleDebugDrawerVisible && ( | |||||
| <SingleDebugDrawer | |||||
| visible={singleDebugDrawerVisible} | |||||
| hideModal={hideSingleDebugDrawer} | |||||
| componentId={node?.id} | |||||
| ></SingleDebugDrawer> | |||||
| )} | |||||
| </Sheet> | |||||
| ); | |||||
| }; | |||||
| export default FormDrawer; |
| import { useTranslation } from 'react-i18next'; | |||||
| import { z } from 'zod'; | |||||
| import { Operator } from '../constant'; | |||||
| import AkShareForm from '../form/akshare-form'; | |||||
| import AnswerForm from '../form/answer-form'; | |||||
| import ArXivForm from '../form/arxiv-form'; | |||||
| import BaiduFanyiForm from '../form/baidu-fanyi-form'; | |||||
| import BaiduForm from '../form/baidu-form'; | |||||
| import BeginForm from '../form/begin-form'; | |||||
| import BingForm from '../form/bing-form'; | |||||
| import CategorizeForm from '../form/categorize-form'; | |||||
| import CrawlerForm from '../form/crawler-form'; | |||||
| import DeepLForm from '../form/deepl-form'; | |||||
| import DuckDuckGoForm from '../form/duckduckgo-form'; | |||||
| import EmailForm from '../form/email-form'; | |||||
| import ExeSQLForm from '../form/exesql-form'; | |||||
| import GenerateForm from '../form/generate-form'; | |||||
| import GithubForm from '../form/github-form'; | |||||
| import GoogleForm from '../form/google-form'; | |||||
| import GoogleScholarForm from '../form/google-scholar-form'; | |||||
| import InvokeForm from '../form/invoke-form'; | |||||
| import IterationForm from '../form/iteration-from'; | |||||
| import Jin10Form from '../form/jin10-form'; | |||||
| import KeywordExtractForm from '../form/keyword-extract-form'; | |||||
| import MessageForm from '../form/message-form'; | |||||
| import PubMedForm from '../form/pubmed-form'; | |||||
| import QWeatherForm from '../form/qweather-form'; | |||||
| import RelevantForm from '../form/relevant-form'; | |||||
| import RetrievalForm from '../form/retrieval-form/next'; | |||||
| import RewriteQuestionForm from '../form/rewrite-question-form'; | |||||
| import SwitchForm from '../form/switch-form'; | |||||
| import TemplateForm from '../form/template-form'; | |||||
| import TuShareForm from '../form/tushare-form'; | |||||
| import WenCaiForm from '../form/wencai-form'; | |||||
| import WikipediaForm from '../form/wikipedia-form'; | |||||
| import YahooFinanceForm from '../form/yahoo-finance-form'; | |||||
| export function useFormConfigMap() { | |||||
| const { t } = useTranslation(); | |||||
| const FormConfigMap = { | |||||
| [Operator.Begin]: { | |||||
| component: BeginForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({ | |||||
| name: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim(), | |||||
| age: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim(), | |||||
| }), | |||||
| }, | |||||
| [Operator.Retrieval]: { | |||||
| component: RetrievalForm, | |||||
| defaultValues: { query: [] }, | |||||
| schema: z.object({ | |||||
| name: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim(), | |||||
| age: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim(), | |||||
| query: z.array( | |||||
| z.object({ | |||||
| type: z.string(), | |||||
| }), | |||||
| ), | |||||
| }), | |||||
| }, | |||||
| [Operator.Generate]: { | |||||
| component: GenerateForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Answer]: { | |||||
| component: AnswerForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Categorize]: { | |||||
| component: CategorizeForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Message]: { | |||||
| component: MessageForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Relevant]: { | |||||
| component: RelevantForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.RewriteQuestion]: { | |||||
| component: RewriteQuestionForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Baidu]: { | |||||
| component: BaiduForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.DuckDuckGo]: { | |||||
| component: DuckDuckGoForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.KeywordExtract]: { | |||||
| component: KeywordExtractForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Wikipedia]: { | |||||
| component: WikipediaForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.PubMed]: { | |||||
| component: PubMedForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.ArXiv]: { | |||||
| component: ArXivForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Google]: { | |||||
| component: GoogleForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Bing]: { | |||||
| component: BingForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.GoogleScholar]: { | |||||
| component: GoogleScholarForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.DeepL]: { | |||||
| component: DeepLForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.GitHub]: { | |||||
| component: GithubForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.BaiduFanyi]: { | |||||
| component: BaiduFanyiForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.QWeather]: { | |||||
| component: QWeatherForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.ExeSQL]: { | |||||
| component: ExeSQLForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Switch]: { | |||||
| component: SwitchForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.WenCai]: { | |||||
| component: WenCaiForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.AkShare]: { | |||||
| component: AkShareForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.YahooFinance]: { | |||||
| component: YahooFinanceForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Jin10]: { | |||||
| component: Jin10Form, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.TuShare]: { | |||||
| component: TuShareForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Crawler]: { | |||||
| component: CrawlerForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Invoke]: { | |||||
| component: InvokeForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Concentrator]: { | |||||
| component: () => <></>, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Note]: { | |||||
| component: () => <></>, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Template]: { | |||||
| component: TemplateForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Email]: { | |||||
| component: EmailForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Iteration]: { | |||||
| component: IterationForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.IterationStart]: { | |||||
| component: () => <></>, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| }; | |||||
| return FormConfigMap; | |||||
| } |
| 'use client'; | |||||
| import { Button } from '@/components/ui/button'; | |||||
| import { | |||||
| FormControl, | |||||
| FormDescription, | |||||
| FormField, | |||||
| FormItem, | |||||
| FormMessage, | |||||
| } from '@/components/ui/form'; | |||||
| import { Input } from '@/components/ui/input'; | |||||
| import { RAGFlowSelect } from '@/components/ui/select'; | |||||
| import { RAGFlowNodeType } from '@/interfaces/database/flow'; | |||||
| import { CircleMinus, Plus } from 'lucide-react'; | |||||
| import { useFieldArray, useFormContext } from 'react-hook-form'; | |||||
| import { useTranslation } from 'react-i18next'; | |||||
| import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query'; | |||||
| interface IProps { | |||||
| node?: RAGFlowNodeType; | |||||
| } | |||||
| enum VariableType { | |||||
| Reference = 'reference', | |||||
| Input = 'input', | |||||
| } | |||||
| const getVariableName = (type: string) => | |||||
| type === VariableType.Reference ? 'component_id' : 'value'; | |||||
| export function DynamicVariableForm({ node }: IProps) { | |||||
| const { t } = useTranslation(); | |||||
| const form = useFormContext(); | |||||
| const { fields, remove, append } = useFieldArray({ | |||||
| name: 'query', | |||||
| control: form.control, | |||||
| }); | |||||
| const valueOptions = useBuildComponentIdSelectOptions( | |||||
| node?.id, | |||||
| node?.parentId, | |||||
| ); | |||||
| const options = [ | |||||
| { value: VariableType.Reference, label: t('flow.reference') }, | |||||
| { value: VariableType.Input, label: t('flow.text') }, | |||||
| ]; | |||||
| return ( | |||||
| <div> | |||||
| {fields.map((field, index) => { | |||||
| const typeField = `query.${index}.type`; | |||||
| const typeValue = form.watch(typeField); | |||||
| return ( | |||||
| <div key={field.id} className="flex items-center gap-1"> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name={typeField} | |||||
| render={({ field }) => ( | |||||
| <FormItem className="w-2/5"> | |||||
| {/* <FormLabel>City</FormLabel> */} | |||||
| <FormDescription /> | |||||
| <FormControl> | |||||
| <RAGFlowSelect | |||||
| // placeholder={t('common.pleaseSelect')} | |||||
| {...field} | |||||
| options={options} | |||||
| ></RAGFlowSelect> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name={`query.${index}.${getVariableName(typeValue)}`} | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| {/* <FormLabel>State</FormLabel> */} | |||||
| <FormDescription /> | |||||
| <FormControl> | |||||
| {typeValue === VariableType.Reference ? ( | |||||
| <RAGFlowSelect | |||||
| // placeholder={t('common.pleaseSelect')} | |||||
| {...field} | |||||
| options={valueOptions} | |||||
| ></RAGFlowSelect> | |||||
| ) : ( | |||||
| <Input placeholder={t('common.pleaseInput')} {...field} /> | |||||
| )} | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <CircleMinus | |||||
| className="cursor-pointer" | |||||
| onClick={() => remove(index)} | |||||
| /> | |||||
| </div> | |||||
| ); | |||||
| })} | |||||
| <Button onClick={append} className="w-full mt-4"> | |||||
| <Plus /> | |||||
| {t('flow.addVariable')} | |||||
| </Button> | |||||
| </div> | |||||
| ); | |||||
| } |
| import { KnowledgeBaseFormField } from '@/components/knowledge-base-item'; | |||||
| import { RerankFormFields } from '@/components/rerank'; | |||||
| import { SimilaritySliderFormField } from '@/components/similarity-slider'; | |||||
| import { TopNFormField } from '@/components/top-n-item'; | |||||
| import { | |||||
| Form, | |||||
| FormControl, | |||||
| FormField, | |||||
| FormItem, | |||||
| FormLabel, | |||||
| FormMessage, | |||||
| } from '@/components/ui/form'; | |||||
| import { Textarea } from '@/components/ui/textarea'; | |||||
| import { useTranslate } from '@/hooks/common-hooks'; | |||||
| import { INextOperatorForm } from '../../interface'; | |||||
| import { DynamicVariableForm } from '../components/next-dynamic-input-variable'; | |||||
| const RetrievalForm = ({ form, node }: INextOperatorForm) => { | |||||
| const { t } = useTranslate('flow'); | |||||
| return ( | |||||
| <Form {...form}> | |||||
| <DynamicVariableForm></DynamicVariableForm> | |||||
| <SimilaritySliderFormField name="keywords_similarity_weight"></SimilaritySliderFormField> | |||||
| <TopNFormField></TopNFormField> | |||||
| <RerankFormFields></RerankFormFields> | |||||
| <KnowledgeBaseFormField></KnowledgeBaseFormField> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="empty_response" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>{t('chat.emptyResponse')}</FormLabel> | |||||
| <FormControl> | |||||
| <Textarea | |||||
| placeholder={t('common.namePlaceholder')} | |||||
| {...field} | |||||
| autoComplete="off" | |||||
| rows={4} | |||||
| /> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| </Form> | |||||
| ); | |||||
| }; | |||||
| export default RetrievalForm; |
| import { RAGFlowNodeType } from '@/interfaces/database/flow'; | import { RAGFlowNodeType } from '@/interfaces/database/flow'; | ||||
| import { FormInstance } from 'antd'; | import { FormInstance } from 'antd'; | ||||
| import { UseFormReturn } from 'react-hook-form'; | |||||
| export interface IOperatorForm { | export interface IOperatorForm { | ||||
| onValuesChange?(changedValues: any, values: any): void; | onValuesChange?(changedValues: any, values: any): void; | ||||
| nodeId?: string; | nodeId?: string; | ||||
| } | } | ||||
| export interface INextOperatorForm { | |||||
| form: UseFormReturn; | |||||
| node?: RAGFlowNodeType; | |||||
| nodeId?: string; | |||||
| } | |||||
| export interface IGenerateParameter { | export interface IGenerateParameter { | ||||
| id?: string; | id?: string; | ||||
| key: string; | key: string; |