Feat: Render MessageForm with shadcn-ui. #3221 (#5596)

### What problem does this PR solve?

Feat: Render MessageForm with shadcn-ui. #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu 2025-03-04 15:47:05 +08:00 committed by GitHub
parent 9816b868f9
commit f256e1a59a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 120 additions and 101 deletions

View File

@ -9,7 +9,7 @@ import { useTheme } from '@/components/theme-provider';
import { LanguageList, LanguageMap } from '@/constants/common'; import { LanguageList, LanguageMap } from '@/constants/common';
import { useChangeLanguage } from '@/hooks/logic-hooks'; import { useChangeLanguage } from '@/hooks/logic-hooks';
import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
import { MoonIcon, SunIcon } from 'lucide-react'; import { CircleHelp, MoonIcon, SunIcon } from 'lucide-react';
import styled from './index.less'; import styled from './index.less';
const Circle = ({ children, ...restProps }: React.PropsWithChildren) => { const Circle = ({ children, ...restProps }: React.PropsWithChildren) => {
@ -24,6 +24,10 @@ const handleGithubCLick = () => {
window.open('https://github.com/infiniflow/ragflow', 'target'); window.open('https://github.com/infiniflow/ragflow', 'target');
}; };
const handleDocHelpCLick = () => {
window.open('https://ragflow.io/docs/dev/category/guides', 'target');
};
const RightToolBar = () => { const RightToolBar = () => {
const { t } = useTranslate('common'); const { t } = useTranslate('common');
const changeLanguage = useChangeLanguage(); const changeLanguage = useChangeLanguage();
@ -63,6 +67,9 @@ const RightToolBar = () => {
<Circle> <Circle>
<GithubOutlined onClick={handleGithubCLick} /> <GithubOutlined onClick={handleGithubCLick} />
</Circle> </Circle>
<Circle>
<CircleHelp className="size-4" onClick={handleDocHelpCLick} />
</Circle>
<Circle> <Circle>
{theme === 'dark' ? ( {theme === 'dark' ? (
<MoonIcon onClick={onMoonClick} size={20} /> <MoonIcon onClick={onMoonClick} size={20} />

View File

@ -158,8 +158,11 @@ export function useFormConfigMap() {
}, },
[Operator.PubMed]: { [Operator.PubMed]: {
component: PubMedForm, component: PubMedForm,
defaultValues: {}, defaultValues: { top_n: 10 },
schema: z.object({}), schema: z.object({
top_n: z.number(),
email: z.string(),
}),
}, },
[Operator.ArXiv]: { [Operator.ArXiv]: {
component: ArXivForm, component: ArXivForm,

View File

@ -1,85 +1,80 @@
import { useTranslate } from '@/hooks/common-hooks'; import { Button } from '@/components/ui/button';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import {
import { Button, Form, Input } from 'antd'; Form,
import { IOperatorForm } from '../../interface'; FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Textarea } from '@/components/ui/textarea';
import { PlusCircle, Trash2 } from 'lucide-react';
import { useFieldArray } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { INextOperatorForm } from '../../interface';
import styles from './index.less'; const MessageForm = ({ form }: INextOperatorForm) => {
const { t } = useTranslation();
const formItemLayout = { const { fields, append, remove } = useFieldArray({
labelCol: { name: 'messages',
sm: { span: 6 }, control: form.control,
}, });
wrapperCol: {
sm: { span: 18 },
},
};
const formItemLayoutWithOutLabel = {
wrapperCol: {
sm: { span: 18, offset: 6 },
},
};
const MessageForm = ({ onValuesChange, form }: IOperatorForm) => {
const { t } = useTranslate('flow');
return ( return (
<Form <Form {...form}>
name="basic" <form
{...formItemLayoutWithOutLabel} className="space-y-6"
onValuesChange={onValuesChange} onSubmit={(e) => {
autoComplete="off" e.preventDefault();
form={form} }}
> >
<Form.List name="messages"> <FormItem>
{(fields, { add, remove }, {}) => ( <FormLabel>{t('flow.msg')}</FormLabel>
<> <div className="space-y-4">
{fields.map((field, index) => ( {fields.map((field, index) => (
<Form.Item <div key={field.id} className="flex items-start gap-2">
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)} <FormField
label={index === 0 ? t('msg') : ''} control={form.control}
required={false} name={`messages.${index}`}
key={field.key} render={({ field }) => (
> <FormItem className="flex-1">
<Form.Item <FormControl>
{...field} <Textarea
validateTrigger={['onChange', 'onBlur']} {...field}
rules={[ placeholder={t('flow.messagePlaceholder')}
{ rows={5}
required: true, />
whitespace: true, </FormControl>
message: t('messageMsg'), </FormItem>
}, )}
]} />
noStyle {fields.length > 1 && (
> <Button
<Input.TextArea variant="ghost"
rows={4} size="icon"
placeholder={t('messagePlaceholder')} type="button"
style={{ width: '80%' }} onClick={() => remove(index)}
/> className="cursor-pointer text-colors-text-functional-danger"
</Form.Item> >
{fields.length > 1 ? ( <Trash2 className="h-4 w-4" />
<MinusCircleOutlined </Button>
className={styles.dynamicDeleteButton} )}
onClick={() => remove(field.name)} </div>
/>
) : null}
</Form.Item>
))} ))}
<Form.Item>
<Button <Button
type="dashed" type="button"
onClick={() => add()} variant="outline"
style={{ width: '80%' }} onClick={() => append(' ')} // "" will cause the inability to add, refer to: https://github.com/orgs/react-hook-form/discussions/8485#discussioncomment-2961861
icon={<PlusOutlined />} className="w-full mt-4"
> >
{t('addMessage')} <PlusCircle className="mr-2 h-4 w-4" />
</Button> {t('flow.addMessage')}
</Form.Item> </Button>
</> </div>
)} <FormMessage />
</Form.List> </FormItem>
</form>
</Form> </Form>
); );
}; };

View File

@ -1,30 +1,44 @@
import TopNItem from '@/components/top-n-item'; import { TopNFormField } from '@/components/top-n-item';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Input } from 'antd'; import { INextOperatorForm } from '../../interface';
import { IOperatorForm } from '../../interface'; import { DynamicInputVariable } from '../components/next-dynamic-input-variable';
import DynamicInputVariable from '../components/dynamic-input-variable';
const PubMedForm = ({ onValuesChange, form, node }: IOperatorForm) => { const PubMedForm = ({ form, node }: INextOperatorForm) => {
const { t } = useTranslate('flow'); const { t } = useTranslate('flow');
return ( return (
<Form <Form {...form}>
name="basic" <form
autoComplete="off" className="space-y-6"
form={form} onSubmit={(e) => {
onValuesChange={onValuesChange} e.preventDefault();
layout={'vertical'} }}
>
<DynamicInputVariable node={node}></DynamicInputVariable>
<TopNItem initialValue={10}></TopNItem>
<Form.Item
label={t('email')}
name={'email'}
tooltip={t('emailTip')}
rules={[{ type: 'email' }]}
> >
<Input></Input> <DynamicInputVariable node={node}></DynamicInputVariable>
</Form.Item> <TopNFormField></TopNFormField>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel tooltip={t('emailTip')}>{t('email')}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form> </Form>
); );
}; };