### What problem does this PR solve? Feat: Render DynamicCategorize with shadcn-ui. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
fb4b5b0a06
commit
850e218051
31
web/src/components/large-model-form-field.tsx
Normal file
31
web/src/components/large-model-form-field.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import {
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NextLLMSelect } from './llm-select';
|
||||
|
||||
export function LargeModelFormField() {
|
||||
const form = useFormContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="llm_id"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel tooltip={t('chat.modelTip')}>{t('chat.model')}</FormLabel>
|
||||
<FormControl>
|
||||
<NextLLMSelect {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,208 +0,0 @@
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { Flex, Form, 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 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 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';
|
||||
import { useHandleFormValuesChange, useHandleNodeNameChange } from '../hooks';
|
||||
import OperatorIcon from '../operator-icon';
|
||||
import {
|
||||
buildCategorizeListFromObject,
|
||||
needsSingleStepDebugging,
|
||||
} from '../utils';
|
||||
|
||||
import { Sheet, SheetContent, SheetHeader } from '@/components/ui/sheet';
|
||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||
import { FlowFormContext } from '../context';
|
||||
import { RunTooltip } from '../flow-tooltip';
|
||||
import IterationForm from '../form/iteration-from';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
interface IProps {
|
||||
node?: RAGFlowNodeType;
|
||||
singleDebugDrawerVisible: IModalProps<any>['visible'];
|
||||
hideSingleDebugDrawer: IModalProps<any>['hideModal'];
|
||||
showSingleDebugDrawer: IModalProps<any>['showModal'];
|
||||
}
|
||||
|
||||
const FormMap = {
|
||||
[Operator.Begin]: BeginForm,
|
||||
[Operator.Retrieval]: RetrievalForm,
|
||||
[Operator.Generate]: GenerateForm,
|
||||
[Operator.Answer]: AnswerForm,
|
||||
[Operator.Categorize]: CategorizeForm,
|
||||
[Operator.Message]: MessageForm,
|
||||
[Operator.Relevant]: RelevantForm,
|
||||
[Operator.RewriteQuestion]: RewriteQuestionForm,
|
||||
[Operator.Baidu]: BaiduForm,
|
||||
[Operator.DuckDuckGo]: DuckDuckGoForm,
|
||||
[Operator.KeywordExtract]: KeywordExtractForm,
|
||||
[Operator.Wikipedia]: WikipediaForm,
|
||||
[Operator.PubMed]: PubMedForm,
|
||||
[Operator.ArXiv]: ArXivForm,
|
||||
[Operator.Google]: GoogleForm,
|
||||
[Operator.Bing]: BingForm,
|
||||
[Operator.GoogleScholar]: GoogleScholarForm,
|
||||
[Operator.DeepL]: DeepLForm,
|
||||
[Operator.GitHub]: GithubForm,
|
||||
[Operator.BaiduFanyi]: BaiduFanyiForm,
|
||||
[Operator.QWeather]: QWeatherForm,
|
||||
[Operator.ExeSQL]: ExeSQLForm,
|
||||
[Operator.Switch]: SwitchForm,
|
||||
[Operator.WenCai]: WenCaiForm,
|
||||
[Operator.AkShare]: AkShareForm,
|
||||
[Operator.YahooFinance]: YahooFinanceForm,
|
||||
[Operator.Jin10]: Jin10Form,
|
||||
[Operator.TuShare]: TuShareForm,
|
||||
[Operator.Crawler]: CrawlerForm,
|
||||
[Operator.Invoke]: InvokeForm,
|
||||
[Operator.Concentrator]: () => <></>,
|
||||
[Operator.Note]: () => <></>,
|
||||
[Operator.Template]: TemplateForm,
|
||||
[Operator.Email]: EmailForm,
|
||||
[Operator.Iteration]: IterationForm,
|
||||
[Operator.IterationStart]: () => <></>,
|
||||
};
|
||||
|
||||
const EmptyContent = () => <div></div>;
|
||||
|
||||
const FormDrawer = ({
|
||||
visible,
|
||||
hideModal,
|
||||
node,
|
||||
singleDebugDrawerVisible,
|
||||
hideSingleDebugDrawer,
|
||||
showSingleDebugDrawer,
|
||||
}: IModalProps<any> & IProps) => {
|
||||
const operatorName: Operator = node?.data.label as Operator;
|
||||
const OperatorForm = FormMap[operatorName] ?? EmptyContent;
|
||||
const [form] = Form.useForm();
|
||||
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();
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
} else {
|
||||
form.setFieldsValue(node?.data?.form);
|
||||
}
|
||||
previousId.current = node?.id;
|
||||
}
|
||||
}, [visible, form, node?.data?.form, node?.id, node, operatorName]);
|
||||
|
||||
return (
|
||||
<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>
|
||||
<span className={styles.operatorDescription}>
|
||||
{t(`${lowerFirst(operatorName)}Description`)}
|
||||
</span>
|
||||
</Flex>
|
||||
</SheetHeader>
|
||||
<section className={styles.formWrapper}>
|
||||
{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;
|
||||
@ -8,6 +8,7 @@ import {
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { get, isPlainObject, lowerFirst } from 'lodash';
|
||||
import { Play, X } from 'lucide-react';
|
||||
@ -94,9 +95,9 @@ const FormSheet = ({
|
||||
return (
|
||||
<Sheet open={visible} modal={false}>
|
||||
<SheetTitle className="hidden"></SheetTitle>
|
||||
<SheetContent className="bg-white top-20" closeIcon={false}>
|
||||
<SheetContent className={cn('bg-white top-20 p-0')} closeIcon={false}>
|
||||
<SheetHeader>
|
||||
<section className="flex-col border-b pb-2">
|
||||
<section className="flex-col border-b py-2 px-5">
|
||||
<div className="flex items-center gap-2 pb-3">
|
||||
<OperatorIcon
|
||||
name={operatorName}
|
||||
|
||||
@ -99,8 +99,15 @@ export function useFormConfigMap() {
|
||||
},
|
||||
[Operator.Categorize]: {
|
||||
component: CategorizeForm,
|
||||
defaultValues: {},
|
||||
schema: z.object({}),
|
||||
defaultValues: { message_history_window_size: 1 },
|
||||
schema: z.object({
|
||||
message_history_window_size: z.number(),
|
||||
items: z.array(
|
||||
z.object({
|
||||
name: z.string().min(1, t('flow.nameMessage')).trim(),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
},
|
||||
[Operator.Message]: {
|
||||
component: MessageForm,
|
||||
|
||||
@ -1,18 +1,25 @@
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { CloseOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { useUpdateNodeInternals } from '@xyflow/react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Button,
|
||||
Collapse,
|
||||
Flex,
|
||||
Form,
|
||||
FormListFieldData,
|
||||
Input,
|
||||
Select,
|
||||
} from 'antd';
|
||||
import { FormInstance } from 'antd/lib';
|
||||
import { humanId } from 'human-id';
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from '@/components/ui/collapsible';
|
||||
import {
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { RAGFlowSelect } from '@/components/ui/select';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { useUpdateNodeInternals } from '@xyflow/react';
|
||||
import humanId from 'human-id';
|
||||
import trim from 'lodash/trim';
|
||||
import { ChevronsUpDown, X } from 'lucide-react';
|
||||
import {
|
||||
ChangeEventHandler,
|
||||
FocusEventHandler,
|
||||
@ -20,11 +27,10 @@ import {
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { UseFormReturn, useFieldArray, useFormContext } from 'react-hook-form';
|
||||
import { Operator } from '../../constant';
|
||||
import { useBuildFormSelectOptions } from '../../form-hooks';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
interface IProps {
|
||||
nodeId?: string;
|
||||
}
|
||||
@ -33,20 +39,20 @@ interface INameInputProps {
|
||||
value?: string;
|
||||
onChange?: (value: string) => void;
|
||||
otherNames?: string[];
|
||||
validate(errors: string[]): void;
|
||||
validate(error?: string): void;
|
||||
}
|
||||
|
||||
const getOtherFieldValues = (
|
||||
form: FormInstance,
|
||||
form: UseFormReturn,
|
||||
formListName: string = 'items',
|
||||
field: FormListFieldData,
|
||||
index: number,
|
||||
latestField: string,
|
||||
) =>
|
||||
(form.getFieldValue([formListName]) ?? [])
|
||||
(form.getValues(formListName) ?? [])
|
||||
.map((x: any) => x[latestField])
|
||||
.filter(
|
||||
(x: string) =>
|
||||
x !== form.getFieldValue([formListName, field.name, latestField]),
|
||||
x !== form.getValues(`${formListName}.${index}.${latestField}`),
|
||||
);
|
||||
|
||||
const NameInput = ({
|
||||
@ -61,15 +67,16 @@ const NameInput = ({
|
||||
const handleNameChange: ChangeEventHandler<HTMLInputElement> = useCallback(
|
||||
(e) => {
|
||||
const val = e.target.value;
|
||||
// trigger validation
|
||||
if (otherNames?.some((x) => x === val)) {
|
||||
validate([t('nameRepeatedMsg')]);
|
||||
} else if (trim(val) === '') {
|
||||
validate([t('nameRequiredMsg')]);
|
||||
} else {
|
||||
validate([]);
|
||||
}
|
||||
setName(val);
|
||||
const trimmedVal = trim(val);
|
||||
// trigger validation
|
||||
if (otherNames?.some((x) => x === trimmedVal)) {
|
||||
validate(t('nameRepeatedMsg'));
|
||||
} else if (trimmedVal === '') {
|
||||
validate(t('nameRequiredMsg'));
|
||||
} else {
|
||||
validate('');
|
||||
}
|
||||
},
|
||||
[otherNames, validate, t],
|
||||
);
|
||||
@ -97,128 +104,161 @@ const NameInput = ({
|
||||
);
|
||||
};
|
||||
|
||||
const FormSet = ({ nodeId, field }: IProps & { field: FormListFieldData }) => {
|
||||
const form = Form.useFormInstance();
|
||||
const FormSet = ({ nodeId, index }: IProps & { index: number }) => {
|
||||
const form = useFormContext();
|
||||
const { t } = useTranslate('flow');
|
||||
const buildCategorizeToOptions = useBuildFormSelectOptions(
|
||||
Operator.Categorize,
|
||||
nodeId,
|
||||
);
|
||||
|
||||
const buildFieldName = useCallback(
|
||||
(name: string) => {
|
||||
return `items.${index}.${name}`;
|
||||
},
|
||||
[index],
|
||||
);
|
||||
|
||||
return (
|
||||
<section>
|
||||
<Form.Item
|
||||
label={t('categoryName')}
|
||||
name={[field.name, 'name']}
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
whitespace: true,
|
||||
message: t('nameMessage'),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<NameInput
|
||||
otherNames={getOtherFieldValues(form, 'items', field, 'name')}
|
||||
validate={(errors: string[]) =>
|
||||
form.setFields([
|
||||
{
|
||||
name: ['items', field.name, 'name'],
|
||||
errors,
|
||||
},
|
||||
])
|
||||
}
|
||||
></NameInput>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('description')} name={[field.name, 'description']}>
|
||||
<Input.TextArea rows={3} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('examples')} name={[field.name, 'examples']}>
|
||||
<Input.TextArea rows={3} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('nextStep')} name={[field.name, 'to']}>
|
||||
<Select
|
||||
allowClear
|
||||
options={buildCategorizeToOptions(
|
||||
getOtherFieldValues(form, 'items', field, 'to'),
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item hidden name={[field.name, 'index']}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<section className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={buildFieldName('name')}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('categoryName')}</FormLabel>
|
||||
<FormControl>
|
||||
<NameInput
|
||||
{...field}
|
||||
otherNames={getOtherFieldValues(form, 'items', index, 'name')}
|
||||
validate={(error?: string) => {
|
||||
const fieldName = buildFieldName('name');
|
||||
if (error) {
|
||||
form.setError(fieldName, { message: error });
|
||||
} else {
|
||||
form.clearErrors(fieldName);
|
||||
}
|
||||
}}
|
||||
></NameInput>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={buildFieldName('description')}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('description')}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea {...field} rows={3} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={buildFieldName('examples')}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('examples')}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea {...field} rows={3} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={buildFieldName('to')}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('nextStep')}</FormLabel>
|
||||
<FormControl>
|
||||
<RAGFlowSelect
|
||||
{...field}
|
||||
allowClear
|
||||
options={buildCategorizeToOptions(
|
||||
getOtherFieldValues(form, 'items', index, 'to'),
|
||||
)}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="index"
|
||||
render={({ field }) => (
|
||||
<FormItem className="hidden">
|
||||
<FormLabel>{t('examples')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
const DynamicCategorize = ({ nodeId }: IProps) => {
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const form = Form.useFormInstance();
|
||||
|
||||
const form = useFormContext();
|
||||
const { t } = useTranslate('flow');
|
||||
const { fields, remove, append } = useFieldArray({
|
||||
name: 'items',
|
||||
control: form.control,
|
||||
});
|
||||
|
||||
const handleAdd = () => {
|
||||
append({
|
||||
name: humanId(),
|
||||
});
|
||||
if (nodeId) updateNodeInternals(nodeId);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.List name="items">
|
||||
{(fields, { add, remove }) => {
|
||||
const handleAdd = () => {
|
||||
const idx = form.getFieldValue([
|
||||
'items',
|
||||
fields.at(-1)?.name,
|
||||
'index',
|
||||
]);
|
||||
add({
|
||||
name: humanId(),
|
||||
index: fields.length === 0 ? 0 : idx + 1,
|
||||
});
|
||||
if (nodeId) updateNodeInternals(nodeId);
|
||||
};
|
||||
<div className="flex flex-col gap-4 ">
|
||||
{fields.map((field, index) => (
|
||||
<Collapsible key={field.id}>
|
||||
<div className="flex items-center justify-between space-x-4">
|
||||
<h4 className="font-bold">
|
||||
{form.getValues(`items.${index}.name`)}
|
||||
</h4>
|
||||
<CollapsibleTrigger asChild>
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-9 p-0"
|
||||
onClick={() => remove(index)}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" className="w-9 p-0">
|
||||
<ChevronsUpDown className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle</span>
|
||||
</Button>
|
||||
</div>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
<CollapsibleContent>
|
||||
<FormSet nodeId={nodeId} index={index}></FormSet>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
))}
|
||||
|
||||
return (
|
||||
<Flex gap={18} vertical>
|
||||
{fields.map((field) => (
|
||||
<Collapse
|
||||
size="small"
|
||||
key={field.key}
|
||||
className={styles.caseCard}
|
||||
items={[
|
||||
{
|
||||
key: field.key,
|
||||
label: (
|
||||
<div className="flex justify-between">
|
||||
<span>
|
||||
{form.getFieldValue(['items', field.name, 'name'])}
|
||||
</span>
|
||||
<CloseOutlined
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
children: (
|
||||
<FormSet nodeId={nodeId} field={field}></FormSet>
|
||||
),
|
||||
},
|
||||
]}
|
||||
></Collapse>
|
||||
))}
|
||||
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={handleAdd}
|
||||
block
|
||||
className={styles.addButton}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
{t('addCategory')}
|
||||
</Button>
|
||||
</Flex>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
</>
|
||||
<Button type={'button'} onClick={handleAdd}>
|
||||
<PlusOutlined />
|
||||
{t('addCategory')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
@lightBackgroundColor: rgba(150, 150, 150, 0.07);
|
||||
@darkBackgroundColor: rgba(150, 150, 150, 0.12);
|
||||
|
||||
.caseCard {
|
||||
:global(.ant-collapse-content) {
|
||||
background-color: @darkBackgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
.addButton {
|
||||
color: rgb(22, 119, 255);
|
||||
font-weight: 600;
|
||||
}
|
||||
@ -1,41 +1,33 @@
|
||||
import LLMSelect from '@/components/llm-select';
|
||||
import MessageHistoryWindowSizeItem from '@/components/message-history-window-size-item';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { Form } from 'antd';
|
||||
import { IOperatorForm } from '../../interface';
|
||||
import DynamicInputVariable from '../components/dynamic-input-variable';
|
||||
import { LargeModelFormField } from '@/components/large-model-form-field';
|
||||
import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item';
|
||||
import { Form } from '@/components/ui/form';
|
||||
import { INextOperatorForm } from '../../interface';
|
||||
import { DynamicInputVariable } from '../components/next-dynamic-input-variable';
|
||||
import DynamicCategorize from './dynamic-categorize';
|
||||
import { useHandleFormValuesChange } from './hooks';
|
||||
|
||||
const CategorizeForm = ({ form, onValuesChange, node }: IOperatorForm) => {
|
||||
const { t } = useTranslate('flow');
|
||||
const { handleValuesChange } = useHandleFormValuesChange({
|
||||
form,
|
||||
nodeId: node?.id,
|
||||
onValuesChange,
|
||||
});
|
||||
const CategorizeForm = ({ form, node }: INextOperatorForm) => {
|
||||
// const { handleValuesChange } = useHandleFormValuesChange({
|
||||
// form,
|
||||
// nodeId: node?.id,
|
||||
// onValuesChange,
|
||||
// });
|
||||
|
||||
return (
|
||||
<Form
|
||||
name="basic"
|
||||
autoComplete="off"
|
||||
form={form}
|
||||
onValuesChange={handleValuesChange}
|
||||
initialValues={{ items: [{}] }}
|
||||
layout={'vertical'}
|
||||
// onValuesChange={handleValuesChange}
|
||||
{...form}
|
||||
>
|
||||
<DynamicInputVariable node={node}></DynamicInputVariable>
|
||||
<Form.Item
|
||||
name={'llm_id'}
|
||||
label={t('model', { keyPrefix: 'chat' })}
|
||||
tooltip={t('modelTip', { keyPrefix: 'chat' })}
|
||||
<form
|
||||
className="space-y-6 p-5 overflow-auto max-h-[76vh]"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<LLMSelect></LLMSelect>
|
||||
</Form.Item>
|
||||
<MessageHistoryWindowSizeItem
|
||||
initialValue={1}
|
||||
></MessageHistoryWindowSizeItem>
|
||||
<DynamicCategorize nodeId={node?.id}></DynamicCategorize>
|
||||
<DynamicInputVariable node={node}></DynamicInputVariable>
|
||||
<LargeModelFormField></LargeModelFormField>
|
||||
<MessageHistoryWindowSizeFormField></MessageHistoryWindowSizeFormField>
|
||||
<DynamicCategorize nodeId={node?.id}></DynamicCategorize>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
.dynamicDeleteButton {
|
||||
position: relative;
|
||||
top: 4px;
|
||||
margin: 0 8px;
|
||||
color: #999;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
&:hover {
|
||||
color: #777;
|
||||
}
|
||||
&[disabled] {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user