### What problem does this PR solve? Feat: Switching the programming language of the code operator will switch the corresponding language template #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.x
| @@ -8,10 +8,8 @@ import { useTheme } from '@/components/theme-provider'; | |||
| import { INoteNode } from '@/interfaces/database/flow'; | |||
| import { memo, useEffect } from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { | |||
| useHandleFormValuesChange, | |||
| useHandleNodeNameChange, | |||
| } from '../../hooks'; | |||
| import { useHandleNodeNameChange } from '../../hooks'; | |||
| import { useHandleFormValuesChange } from '../../hooks/use-watch-form-change'; | |||
| import styles from './index.less'; | |||
| const { TextArea } = Input; | |||
| @@ -17,7 +17,8 @@ import { useForm } from 'react-hook-form'; | |||
| import { BeginId, Operator, operatorMap } from '../constant'; | |||
| import { FlowFormContext } from '../context'; | |||
| import { RunTooltip } from '../flow-tooltip'; | |||
| import { useHandleFormValuesChange, useHandleNodeNameChange } from '../hooks'; | |||
| import { useHandleNodeNameChange } from '../hooks'; | |||
| import { useHandleFormValuesChange } from '../hooks/use-watch-form-change'; | |||
| import OperatorIcon from '../operator-icon'; | |||
| import { | |||
| buildCategorizeListFromObject, | |||
| @@ -133,14 +133,12 @@ export function useFormConfigMap() { | |||
| }, | |||
| [Operator.Code]: { | |||
| component: CodeForm, | |||
| defaultValues: { | |||
| message_history_window_size: 6, | |||
| }, | |||
| defaultValues: { arguments: [] }, | |||
| schema: z.object({ | |||
| script: z.string(), | |||
| arguments: z | |||
| .array(z.object({ name: z.string(), component_id: z.string() })) | |||
| .optional(), | |||
| arguments: z.array( | |||
| z.object({ name: z.string(), component_id: z.string() }), | |||
| ), | |||
| lang: z.string(), | |||
| }), | |||
| }, | |||
| @@ -10,8 +10,9 @@ import { | |||
| FormMessage, | |||
| } from '@/components/ui/form'; | |||
| import { RAGFlowSelect } from '@/components/ui/select'; | |||
| import { ProgrammingLanguage } from '@/constants/agent'; | |||
| import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | |||
| import { ICodeForm } from '@/interfaces/database/flow'; | |||
| import { useEffect } from 'react'; | |||
| import { DynamicInputVariable } from './next-variable'; | |||
| loader.config({ paths: { vs: '/vs' } }); | |||
| @@ -24,15 +25,13 @@ const options = [ | |||
| const CodeForm = ({ form, node }: INextOperatorForm) => { | |||
| const formData = node?.data.form as ICodeForm; | |||
| // useEffect(() => { | |||
| // setTimeout(() => { | |||
| // // TODO: Direct operation zustand is more elegant | |||
| // form?.setFieldValue( | |||
| // 'script', | |||
| // CodeTemplateStrMap[formData.lang as ProgrammingLanguage], | |||
| // ); | |||
| // }, 0); | |||
| // }, [form, formData.lang]); | |||
| useEffect(() => { | |||
| // TODO: Direct operation zustand is more elegant | |||
| form?.setValue( | |||
| 'script', | |||
| CodeTemplateStrMap[formData.lang as ProgrammingLanguage], | |||
| ); | |||
| }, [form, formData.lang]); | |||
| return ( | |||
| <Form {...form}> | |||
| @@ -54,7 +54,10 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) { | |||
| <FormItem className="w-2/5"> | |||
| <FormDescription /> | |||
| <FormControl> | |||
| <Input placeholder={t('common.pleaseInput')} {...field} /> | |||
| <Input | |||
| {...field} | |||
| placeholder={t('common.pleaseInput')} | |||
| ></Input> | |||
| </FormControl> | |||
| <FormMessage /> | |||
| </FormItem> | |||
| @@ -84,7 +87,12 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) { | |||
| </div> | |||
| ); | |||
| })} | |||
| <Button onClick={append} className="mt-4" variant={'outline'} size={'sm'}> | |||
| <Button | |||
| onClick={() => append({ name: '', component_id: undefined })} | |||
| className="mt-4" | |||
| variant={'outline'} | |||
| size={'sm'} | |||
| > | |||
| <Plus /> | |||
| {t('flow.addVariable')} | |||
| </Button> | |||
| @@ -294,7 +294,13 @@ export const useHandleFormValuesChange = ( | |||
| useEffect(() => { | |||
| const subscription = form?.watch((value, { name, type, values }) => { | |||
| if (id && name) { | |||
| console.log('🚀 ~ useEffect ~ value:', type, values); | |||
| console.log( | |||
| '🚀 ~ useEffect ~ value:', | |||
| name, | |||
| type, | |||
| values, | |||
| operatorName, | |||
| ); | |||
| let nextValues: any = value; | |||
| // Fixed the issue that the related form value does not change after selecting the freedom field of the model | |||
| @@ -320,8 +326,8 @@ export const useHandleFormValuesChange = ( | |||
| category_description: buildCategorizeObjectFromList(value.items), | |||
| }; | |||
| } | |||
| // Manually triggered form updates are synchronized to the canvas | |||
| if (type) { | |||
| // Manually triggered form updates are synchronized to the canvas | |||
| updateNodeForm(id, nextValues); | |||
| } | |||
| } | |||
| @@ -0,0 +1,98 @@ | |||
| import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | |||
| import { settledModelVariableMap } from '@/constants/knowledge'; | |||
| import { omit } from 'lodash'; | |||
| import { useCallback, useEffect } from 'react'; | |||
| import { UseFormReturn } from 'react-hook-form'; | |||
| import { Operator } from '../constant'; | |||
| import useGraphStore from '../store'; | |||
| import { buildCategorizeObjectFromList } from '../utils'; | |||
| export const useHandleFormValuesChange = ( | |||
| operatorName: Operator, | |||
| id?: string, | |||
| form?: UseFormReturn, | |||
| ) => { | |||
| const updateNodeForm = useGraphStore((state) => state.updateNodeForm); | |||
| const handleValuesChange = useCallback( | |||
| (changedValues: any, values: any) => { | |||
| let nextValues: any = values; | |||
| // Fixed the issue that the related form value does not change after selecting the freedom field of the model | |||
| if ( | |||
| Object.keys(changedValues).length === 1 && | |||
| 'parameter' in changedValues && | |||
| changedValues['parameter'] in settledModelVariableMap | |||
| ) { | |||
| nextValues = { | |||
| ...values, | |||
| ...settledModelVariableMap[ | |||
| changedValues['parameter'] as keyof typeof settledModelVariableMap | |||
| ], | |||
| }; | |||
| } | |||
| if (id) { | |||
| updateNodeForm(id, nextValues); | |||
| } | |||
| }, | |||
| [updateNodeForm, id], | |||
| ); | |||
| useEffect(() => { | |||
| const subscription = form?.watch((value, { name, type, values }) => { | |||
| console.log('🚀 ~ subscription ~ value:', value); | |||
| if (id && name) { | |||
| console.log( | |||
| '🚀 ~ useEffect ~ value:', | |||
| name, | |||
| type, | |||
| values, | |||
| operatorName, | |||
| ); | |||
| let nextValues: any = value; | |||
| // Fixed the issue that the related form value does not change after selecting the freedom field of the model | |||
| if ( | |||
| name === 'parameter' && | |||
| value['parameter'] in settledModelVariableMap | |||
| ) { | |||
| nextValues = { | |||
| ...value, | |||
| ...settledModelVariableMap[ | |||
| value['parameter'] as keyof typeof settledModelVariableMap | |||
| ], | |||
| }; | |||
| } | |||
| const categoryDescriptionRegex = /items\.\d+\.name/g; | |||
| if ( | |||
| operatorName === Operator.Categorize && | |||
| categoryDescriptionRegex.test(name) | |||
| ) { | |||
| nextValues = { | |||
| ...omit(value, 'items'), | |||
| category_description: buildCategorizeObjectFromList(value.items), | |||
| }; | |||
| } | |||
| if ( | |||
| operatorName === Operator.Code && | |||
| type === 'change' && | |||
| name === 'lang' | |||
| ) { | |||
| nextValues = { | |||
| ...value, | |||
| script: CodeTemplateStrMap[value.lang as ProgrammingLanguage], | |||
| }; | |||
| } | |||
| // Manually triggered form updates are synchronized to the canvas | |||
| if (type) { | |||
| // run(id, nextValues); | |||
| updateNodeForm(id, nextValues); | |||
| } | |||
| } | |||
| }); | |||
| return () => subscription?.unsubscribe(); | |||
| }, [form, form?.watch, id, operatorName, updateNodeForm]); | |||
| return { handleValuesChange }; | |||
| }; | |||