diff --git a/web/src/pages/agent/form-sheet/use-form-config-map.tsx b/web/src/pages/agent/form-sheet/use-form-config-map.tsx index de09956ba..8add23ab3 100644 --- a/web/src/pages/agent/form-sheet/use-form-config-map.tsx +++ b/web/src/pages/agent/form-sheet/use-form-config-map.tsx @@ -43,20 +43,26 @@ export function useFormConfigMap() { const FormConfigMap = { [Operator.Begin]: { component: BeginForm, - defaultValues: {}, + defaultValues: { + prologue: t('chat.setAnOpenerInitial'), + }, schema: z.object({ - name: z - .string() - .min(1, { - message: t('common.namePlaceholder'), - }) - .trim(), - age: z + prologue: z .string() .min(1, { message: t('common.namePlaceholder'), }) .trim(), + query: z.array( + z.object({ + key: z.string(), + type: z.string(), + value: z.string(), + optional: z.boolean(), + name: z.string(), + options: z.array(z.union([z.number(), z.string(), z.boolean()])), + }), + ), }), }, [Operator.Retrieval]: { diff --git a/web/src/pages/agent/form/begin-form/hooks.ts b/web/src/pages/agent/form/begin-form/hooks.ts index b045f5dc5..8f9bfe11e 100644 --- a/web/src/pages/agent/form/begin-form/hooks.ts +++ b/web/src/pages/agent/form/begin-form/hooks.ts @@ -1,32 +1,32 @@ import { useSetModalState } from '@/hooks/common-hooks'; import { useSetSelectedRecord } from '@/hooks/logic-hooks'; import { useCallback, useMemo, useState } from 'react'; -import { BeginQuery, IOperatorForm } from '../../interface'; +import { BeginQuery, INextOperatorForm } from '../../interface'; -export const useEditQueryRecord = ({ form, onValuesChange }: IOperatorForm) => { +export const useEditQueryRecord = ({ form }: INextOperatorForm) => { const { setRecord, currentRecord } = useSetSelectedRecord(); const { visible, hideModal, showModal } = useSetModalState(); const [index, setIndex] = useState(-1); const otherThanCurrentQuery = useMemo(() => { - const query: BeginQuery[] = form?.getFieldValue('query') || []; + const query: BeginQuery[] = form?.getValues('query') || []; return query.filter((item, idx) => idx !== index); }, [form, index]); const handleEditRecord = useCallback( (record: BeginQuery) => { - const query: BeginQuery[] = form?.getFieldValue('query') || []; + const query: BeginQuery[] = form?.getValues('query') || []; const nextQuery: BeginQuery[] = index > -1 ? query.toSpliced(index, 1, record) : [...query, record]; - onValuesChange?.( - { query: nextQuery }, - { query: nextQuery, prologue: form?.getFieldValue('prologue') }, - ); + // onValuesChange?.( + // { query: nextQuery }, + // { query: nextQuery, prologue: form?.getFieldValue('prologue') }, + // ); hideModal(); }, - [form, hideModal, index, onValuesChange], + [form, hideModal, index], ); const handleShowModal = useCallback( diff --git a/web/src/pages/agent/form/begin-form/index.less b/web/src/pages/agent/form/begin-form/index.less deleted file mode 100644 index 0a03d4743..000000000 --- a/web/src/pages/agent/form/begin-form/index.less +++ /dev/null @@ -1,24 +0,0 @@ -.dynamicInputVariable { - background-color: #ebe9e950; - :global(.ant-collapse-content) { - background-color: #f6f6f657; - } - :global(.ant-collapse-content-box) { - padding: 0 !important; - } - margin-bottom: 20px; - .title { - font-weight: 600; - font-size: 16px; - } - - .addButton { - color: rgb(22, 119, 255); - font-weight: 600; - } -} - -.addButton { - color: rgb(22, 119, 255); - font-weight: 600; -} diff --git a/web/src/pages/agent/form/begin-form/index.tsx b/web/src/pages/agent/form/begin-form/index.tsx index 8df1181f1..3e73e6e8e 100644 --- a/web/src/pages/agent/form/begin-form/index.tsx +++ b/web/src/pages/agent/form/begin-form/index.tsx @@ -1,20 +1,26 @@ -import { PlusOutlined } from '@ant-design/icons'; -import { Button, Form, Input } from 'antd'; +import { Button } from '@/components/ui/button'; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/form'; +import { Textarea } from '@/components/ui/textarea'; import { useCallback } from 'react'; +import { useWatch } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import { BeginQuery, IOperatorForm } from '../../interface'; +import { BeginQuery, INextOperatorForm } from '../../interface'; import { useEditQueryRecord } from './hooks'; -import { ModalForm } from './paramater-modal'; +import { ParameterDialog } from './next-paramater-modal'; import QueryTable from './query-table'; -import styles from './index.less'; - -type FieldType = { - prologue?: string; -}; - -const BeginForm = ({ onValuesChange, form }: IOperatorForm) => { +const BeginForm = ({ form }: INextOperatorForm) => { const { t } = useTranslation(); + + const query = useWatch({ control: form.control, name: 'query' }); + const { ok, currentRecord, @@ -24,87 +30,68 @@ const BeginForm = ({ onValuesChange, form }: IOperatorForm) => { otherThanCurrentQuery, } = useEditQueryRecord({ form, - onValuesChange, }); const handleDeleteRecord = useCallback( (idx: number) => { - const query = form?.getFieldValue('query') || []; + const query = form?.getValues('query') || []; const nextQuery = query.filter( (item: BeginQuery, index: number) => index !== idx, ); - onValuesChange?.( - { query: nextQuery }, - { query: nextQuery, prologue: form?.getFieldValue('prologue') }, - ); + // onValuesChange?.( + // { query: nextQuery }, + // { query: nextQuery, prologue: form?.getFieldValue('prologue') }, + // ); }, - [form, onValuesChange], + [form], ); return ( - { - if (name === 'queryForm') { - ok(values as BeginQuery); - } - }} - > -
- - name={'prologue'} - label={t('chat.setAnOpener')} - tooltip={t('chat.setAnOpenerTip')} - initialValue={t('chat.setAnOpenerInitial')} - > - - - {/* Create a hidden field to make Form instance record this */} - - - - prevValues.query !== curValues.query - } - > - {({ getFieldValue }) => { - const query: BeginQuery[] = getFieldValue('query') || []; - return ( - - ); - }} - - - - {visible && ( - + + ( + + + {t('chat.setAnOpener')} + + + + + + )} - -
+ /> + {/* Create a hidden field to make Form instance record this */} +
} + /> + + + + + + {visible && ( + + )} + ); }; diff --git a/web/src/pages/agent/form/begin-form/next-begin-dynamic-options.tsx b/web/src/pages/agent/form/begin-form/next-begin-dynamic-options.tsx new file mode 100644 index 000000000..1d0db395d --- /dev/null +++ b/web/src/pages/agent/form/begin-form/next-begin-dynamic-options.tsx @@ -0,0 +1,62 @@ +'use client'; + +import { Button } from '@/components/ui/button'; +import { + FormControl, + FormField, + FormItem, + FormMessage, +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { Plus, X } from 'lucide-react'; +import { useFieldArray, useFormContext } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; + +export function BeginDynamicOptions() { + const { t } = useTranslation(); + const form = useFormContext(); + const name = 'options'; + + const { fields, remove, append } = useFieldArray({ + name: name, + control: form.control, + }); + + return ( +
+ {fields.map((field, index) => { + const typeField = `${name}.${index}`; + return ( +
+ ( + + + + + + + )} + /> + +
+ ); + })} + +
+ ); +} diff --git a/web/src/pages/agent/form/begin-form/next-paramater-modal.tsx b/web/src/pages/agent/form/begin-form/next-paramater-modal.tsx new file mode 100644 index 000000000..8dcdd43ee --- /dev/null +++ b/web/src/pages/agent/form/begin-form/next-paramater-modal.tsx @@ -0,0 +1,186 @@ +import { toast } from '@/components/hooks/use-toast'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { RAGFlowSelect, RAGFlowSelectOptionType } from '@/components/ui/select'; +import { Switch } from '@/components/ui/switch'; +import { IModalProps } from '@/interfaces/common'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useEffect, useMemo } from 'react'; +import { useForm, useWatch } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { z } from 'zod'; +import { BeginQueryType, BeginQueryTypeIconMap } from '../../constant'; +import { BeginQuery } from '../../interface'; +import { BeginDynamicOptions } from './next-begin-dynamic-options'; + +type ModalFormProps = { + initialValue: BeginQuery; + otherThanCurrentQuery: BeginQuery[]; +}; + +const FormId = 'BeginParameterForm'; + +function ParameterForm({ + initialValue, + otherThanCurrentQuery, +}: ModalFormProps) { + const FormSchema = z.object({ + type: z.string(), + key: z + .string() + .trim() + .refine( + (value) => + !value || !otherThanCurrentQuery.some((x) => x.key === value), + { message: 'The key cannot be repeated!' }, + ), + optional: z.boolean(), + options: z.array(z.string().or(z.boolean()).or(z.number())), + }); + + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + type: BeginQueryType.Line, + optional: false, + }, + }); + + const options = useMemo(() => { + return Object.values(BeginQueryType).reduce( + (pre, cur) => { + const Icon = BeginQueryTypeIconMap[cur]; + + return [ + ...pre, + { + label: ( +
+ + {cur} +
+ ), + value: cur, + }, + ]; + }, + [], + ); + }, []); + + const type = useWatch({ + control: form.control, + name: 'type', + }); + + useEffect(() => { + form.reset(initialValue); + }, [form, initialValue]); + + function onSubmit(data: z.infer) { + toast({ + title: 'You submitted the following values:', + description: ( +
+          {JSON.stringify(data, null, 2)}
+        
+ ), + }); + } + + return ( +
+ + ( + + Type + + + + + + )} + /> + ( + + Key + + + + + + )} + /> + ( + + Optional + + + + + + )} + /> + {type === BeginQueryType.Options && ( + + )} + + + ); +} + +export function ParameterDialog({ + initialValue, + hideModal, + otherThanCurrentQuery, +}: ModalFormProps & IModalProps) { + const { t } = useTranslation(); + + return ( + + + + {t('flow.variableSettings')} + + + + + + + + ); +} diff --git a/web/src/pages/agent/form/begin-form/query-table.tsx b/web/src/pages/agent/form/begin-form/query-table.tsx index c7614e682..445cf201d 100644 --- a/web/src/pages/agent/form/begin-form/query-table.tsx +++ b/web/src/pages/agent/form/begin-form/query-table.tsx @@ -4,7 +4,6 @@ import { Collapse, Space, Table, Tooltip } from 'antd'; import { BeginQuery } from '../../interface'; import { useTranslation } from 'react-i18next'; -import styles from './index.less'; interface IProps { data: BeginQuery[]; @@ -71,11 +70,10 @@ const QueryTable = ({ data, deleteRecord, showModal }: IProps) => { return ( {t('flow.input')}, + label: {t('flow.input')}, children: ( columns={columns}