mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-06-26 22:19:57 +00:00
### What problem does this PR solve? Feat: Add SwitchForm component #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
60c1bf5a19
commit
713b574c9d
File diff suppressed because one or more lines are too long
@ -3,7 +3,7 @@ import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
|||||||
import { MinusCircleOutlined } from '@ant-design/icons';
|
import { MinusCircleOutlined } from '@ant-design/icons';
|
||||||
import { Form, Input, Select } from 'antd';
|
import { Form, Input, Select } from 'antd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
import { useBuildVariableOptions } from '../../hooks/use-get-begin-query';
|
||||||
import { FormCollapse } from '../components/dynamic-input-variable';
|
import { FormCollapse } from '../components/dynamic-input-variable';
|
||||||
|
|
||||||
type DynamicInputVariableProps = {
|
type DynamicInputVariableProps = {
|
||||||
@ -17,10 +17,7 @@ export const DynamicInputVariable = ({
|
|||||||
}: DynamicInputVariableProps) => {
|
}: DynamicInputVariableProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const valueOptions = useBuildComponentIdSelectOptions(
|
const valueOptions = useBuildVariableOptions(node?.id, node?.parentId);
|
||||||
node?.id,
|
|
||||||
node?.parentId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormCollapse title={t('flow.inputVariables')}>
|
<FormCollapse title={t('flow.inputVariables')}>
|
||||||
|
@ -16,7 +16,7 @@ import { X } from 'lucide-react';
|
|||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
import { useBuildVariableOptions } from '../../hooks/use-get-begin-query';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
node?: RAGFlowNodeType;
|
node?: RAGFlowNodeType;
|
||||||
@ -41,10 +41,7 @@ export function DynamicVariableForm({ node, name = 'arguments' }: IProps) {
|
|||||||
control: form.control,
|
control: form.control,
|
||||||
});
|
});
|
||||||
|
|
||||||
const valueOptions = useBuildComponentIdSelectOptions(
|
const valueOptions = useBuildVariableOptions(node?.id, node?.parentId);
|
||||||
node?.id,
|
|
||||||
node?.parentId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
|
@ -3,7 +3,7 @@ import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
|||||||
import { Button, Collapse, Flex, Form, Input, Select } from 'antd';
|
import { Button, Collapse, Flex, Form, Input, Select } from 'antd';
|
||||||
import { PropsWithChildren, useCallback } from 'react';
|
import { PropsWithChildren, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
import { useBuildVariableOptions } from '../../hooks/use-get-begin-query';
|
||||||
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
@ -21,10 +21,7 @@ const getVariableName = (type: string) =>
|
|||||||
|
|
||||||
const DynamicVariableForm = ({ node }: IProps) => {
|
const DynamicVariableForm = ({ node }: IProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const valueOptions = useBuildComponentIdSelectOptions(
|
const valueOptions = useBuildVariableOptions(node?.id, node?.parentId);
|
||||||
node?.id,
|
|
||||||
node?.parentId,
|
|
||||||
);
|
|
||||||
const form = Form.useFormInstance();
|
const form = Form.useFormInstance();
|
||||||
|
|
||||||
const options = [
|
const options = [
|
||||||
|
@ -20,7 +20,7 @@ import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
|||||||
import { Plus, Trash2 } from 'lucide-react';
|
import { Plus, Trash2 } from 'lucide-react';
|
||||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
import { useBuildVariableOptions } from '../../hooks/use-get-begin-query';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
node?: RAGFlowNodeType;
|
node?: RAGFlowNodeType;
|
||||||
@ -42,10 +42,7 @@ export function DynamicVariableForm({ node }: IProps) {
|
|||||||
control: form.control,
|
control: form.control,
|
||||||
});
|
});
|
||||||
|
|
||||||
const valueOptions = useBuildComponentIdSelectOptions(
|
const valueOptions = useBuildVariableOptions(node?.id, node?.parentId);
|
||||||
node?.id,
|
|
||||||
node?.parentId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const options = [
|
const options = [
|
||||||
{ value: VariableType.Reference, label: t('flow.reference') },
|
{ value: VariableType.Reference, label: t('flow.reference') },
|
||||||
|
@ -3,7 +3,7 @@ import { useTranslate } from '@/hooks/common-hooks';
|
|||||||
import { DeleteOutlined } from '@ant-design/icons';
|
import { DeleteOutlined } from '@ant-design/icons';
|
||||||
import { Button, Collapse, Flex, Input, Select, Table, TableProps } from 'antd';
|
import { Button, Collapse, Flex, Input, Select, Table, TableProps } from 'antd';
|
||||||
import { trim } from 'lodash';
|
import { trim } from 'lodash';
|
||||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
import { useBuildVariableOptions } from '../../hooks/use-get-begin-query';
|
||||||
import { IInvokeVariable } from '../../interface';
|
import { IInvokeVariable } from '../../interface';
|
||||||
import { useHandleOperateParameters } from './hooks';
|
import { useHandleOperateParameters } from './hooks';
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ const DynamicVariablesForm = ({ node }: IProps) => {
|
|||||||
const nodeId = node?.id;
|
const nodeId = node?.id;
|
||||||
const { t } = useTranslate('flow');
|
const { t } = useTranslate('flow');
|
||||||
|
|
||||||
const options = useBuildComponentIdSelectOptions(nodeId, node?.parentId);
|
const options = useBuildVariableOptions(nodeId, node?.parentId);
|
||||||
const {
|
const {
|
||||||
dataSource,
|
dataSource,
|
||||||
handleAdd,
|
handleAdd,
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
@lightBackgroundColor: rgba(150, 150, 150, 0.07);
|
|
||||||
@darkBackgroundColor: rgba(150, 150, 150, 0.12);
|
|
||||||
|
|
||||||
.caseCard {
|
|
||||||
background-color: @lightBackgroundColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conditionCard {
|
|
||||||
background-color: @darkBackgroundColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.elseCase {
|
|
||||||
background-color: @lightBackgroundColor;
|
|
||||||
padding: 12px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.addButton {
|
|
||||||
color: rgb(22, 119, 255);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
@ -1,31 +1,179 @@
|
|||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { FormContainer } from '@/components/form-container';
|
||||||
import { Button, Card, Divider, Form, Input, Select } from 'antd';
|
import { BlockButton, Button } from '@/components/ui/button';
|
||||||
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormMessage,
|
||||||
|
} from '@/components/ui/form';
|
||||||
|
import { RAGFlowSelect } from '@/components/ui/select';
|
||||||
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
import { ISwitchForm } from '@/interfaces/database/flow';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { X } from 'lucide-react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { useFieldArray, useForm, useFormContext } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { z } from 'zod';
|
||||||
import {
|
import {
|
||||||
Operator,
|
Operator,
|
||||||
SwitchElseTo,
|
|
||||||
SwitchLogicOperatorOptions,
|
SwitchLogicOperatorOptions,
|
||||||
SwitchOperatorOptions,
|
SwitchOperatorOptions,
|
||||||
} from '../../constant';
|
} from '../../constant';
|
||||||
import { useBuildFormSelectOptions } from '../../form-hooks';
|
import { useBuildFormSelectOptions } from '../../form-hooks';
|
||||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
import {
|
||||||
|
useBuildComponentIdAndBeginOptions,
|
||||||
|
useBuildVariableOptions,
|
||||||
|
} from '../../hooks/use-get-begin-query';
|
||||||
import { IOperatorForm } from '../../interface';
|
import { IOperatorForm } from '../../interface';
|
||||||
import { getOtherFieldValues } from '../../utils';
|
import { useValues } from './use-values';
|
||||||
|
|
||||||
import { ISwitchForm } from '@/interfaces/database/flow';
|
const ConditionKey = 'conditions';
|
||||||
import styles from './index.less';
|
const ItemKey = 'items';
|
||||||
|
|
||||||
const SwitchForm = ({ onValuesChange, node, form }: IOperatorForm) => {
|
type ConditionCardsProps = {
|
||||||
|
name: string;
|
||||||
|
} & IOperatorForm;
|
||||||
|
|
||||||
|
function ConditionCards({ name: parentName, node }: ConditionCardsProps) {
|
||||||
|
const form = useFormContext();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const componentIdOptions = useBuildComponentIdAndBeginOptions(
|
||||||
|
node?.id,
|
||||||
|
node?.parentId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const switchOperatorOptions = useMemo(() => {
|
||||||
|
return SwitchOperatorOptions.map((x) => ({
|
||||||
|
value: x.value,
|
||||||
|
label: t(`flow.switchOperatorOptions.${x.label}`),
|
||||||
|
}));
|
||||||
|
}, [t]);
|
||||||
|
|
||||||
|
const name = `${parentName}.${ItemKey}`;
|
||||||
|
|
||||||
|
const { fields, remove, append } = useFieldArray({
|
||||||
|
name: name,
|
||||||
|
control: form.control,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="flex-1 space-y-2.5">
|
||||||
|
{fields.map((field, index) => {
|
||||||
|
return (
|
||||||
|
<div key={field.id} className="flex">
|
||||||
|
<Card className="bg-transparent border-input-border border flex-1">
|
||||||
|
<section className="p-2 bg-background-card flex justify-between">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`${name}.${index}.cpn_id`}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<RAGFlowSelect
|
||||||
|
{...field}
|
||||||
|
options={componentIdOptions}
|
||||||
|
triggerClassName="w-30 text-background-checked"
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`${name}.${index}.operator`}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<RAGFlowSelect
|
||||||
|
{...field}
|
||||||
|
options={switchOperatorOptions}
|
||||||
|
triggerClassName="w-30"
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
<CardContent className="p-4 ">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={`${name}.${index}.value`}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea {...field} className="bg-transparent" />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<Button variant={'ghost'} onClick={() => remove(index)}>
|
||||||
|
<X />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div className="pr-9">
|
||||||
|
<BlockButton
|
||||||
|
className="mt-6"
|
||||||
|
onClick={() => append({ operator: switchOperatorOptions[0].value })}
|
||||||
|
>
|
||||||
|
add
|
||||||
|
</BlockButton>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SwitchForm = ({ node }: IOperatorForm) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const values = useValues();
|
||||||
|
|
||||||
|
const FormSchema = z.object({
|
||||||
|
conditions: z.array(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
logical_operator: z.string(),
|
||||||
|
items: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
cpn_id: z.string(),
|
||||||
|
operator: z.string(),
|
||||||
|
value: z.string().optional(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
|
to: z.array(z.string()).optional(),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: values,
|
||||||
|
resolver: zodResolver(FormSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { fields, remove, append } = useFieldArray({
|
||||||
|
name: ConditionKey,
|
||||||
|
control: form.control,
|
||||||
|
});
|
||||||
|
|
||||||
const buildCategorizeToOptions = useBuildFormSelectOptions(
|
const buildCategorizeToOptions = useBuildFormSelectOptions(
|
||||||
Operator.Switch,
|
Operator.Switch,
|
||||||
node?.id,
|
node?.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
const getSelectedConditionTos = () => {
|
const getSelectedConditionTos = () => {
|
||||||
const conditions: ISwitchForm['conditions'] =
|
const conditions: ISwitchForm['conditions'] = form?.getValues('conditions');
|
||||||
form?.getFieldValue('conditions');
|
|
||||||
|
|
||||||
return conditions?.filter((x) => !!x).map((x) => x?.to) ?? [];
|
return conditions?.filter((x) => !!x).map((x) => x?.to) ?? [];
|
||||||
};
|
};
|
||||||
@ -44,159 +192,52 @@ const SwitchForm = ({ onValuesChange, node, form }: IOperatorForm) => {
|
|||||||
}));
|
}));
|
||||||
}, [t]);
|
}, [t]);
|
||||||
|
|
||||||
const componentIdOptions = useBuildComponentIdSelectOptions(
|
const componentIdOptions = useBuildVariableOptions(node?.id, node?.parentId);
|
||||||
node?.id,
|
|
||||||
node?.parentId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form {...form}>
|
||||||
form={form}
|
<form
|
||||||
name="dynamic_form_complex"
|
className="space-y-6 p-5 "
|
||||||
autoComplete="off"
|
onSubmit={(e) => {
|
||||||
initialValues={{ conditions: [{}] }}
|
e.preventDefault();
|
||||||
onValuesChange={onValuesChange}
|
}}
|
||||||
layout={'vertical'}
|
|
||||||
>
|
>
|
||||||
<Form.List name="conditions">
|
{fields.map((field, index) => {
|
||||||
{(fields, { add, remove }) => (
|
|
||||||
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
|
|
||||||
{fields.map((field) => {
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<FormContainer key={field.id} className="">
|
||||||
size="small"
|
<div>IF</div>
|
||||||
title={`Case ${field.name + 1}`}
|
<section className="flex items-center gap-2 !mt-2">
|
||||||
key={field.key}
|
<FormField
|
||||||
className={styles.caseCard}
|
control={form.control}
|
||||||
extra={
|
name={`${ConditionKey}.${index}.logical_operator`}
|
||||||
<CloseOutlined
|
render={({ field }) => (
|
||||||
onClick={() => {
|
<FormItem>
|
||||||
remove(field.name);
|
<FormControl>
|
||||||
}}
|
<RAGFlowSelect
|
||||||
|
{...field}
|
||||||
|
options={switchLogicOperatorOptions}
|
||||||
|
triggerClassName="w-18"
|
||||||
/>
|
/>
|
||||||
}
|
</FormControl>
|
||||||
>
|
<FormMessage />
|
||||||
<Form.Item noStyle dependencies={[field.name, 'items']}>
|
</FormItem>
|
||||||
{({ getFieldValue }) =>
|
|
||||||
getFieldValue(['conditions', field.name, 'items'])
|
|
||||||
?.length > 1 && (
|
|
||||||
<Form.Item
|
|
||||||
label={t('flow.logicalOperator')}
|
|
||||||
name={[field.name, 'logical_operator']}
|
|
||||||
>
|
|
||||||
<Select options={switchLogicOperatorOptions} />
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t('flow.nextStep')}
|
|
||||||
name={[field.name, 'to']}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
allowClear
|
|
||||||
options={buildCategorizeToOptions([
|
|
||||||
form?.getFieldValue(SwitchElseTo),
|
|
||||||
...getOtherFieldValues(
|
|
||||||
form!,
|
|
||||||
'conditions',
|
|
||||||
field,
|
|
||||||
'to',
|
|
||||||
),
|
|
||||||
])}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="Condition">
|
|
||||||
<Form.List name={[field.name, 'items']}>
|
|
||||||
{(subFields, subOpt) => (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
rowGap: 16,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{subFields.map((subField) => (
|
|
||||||
<Card
|
|
||||||
key={subField.key}
|
|
||||||
title={null}
|
|
||||||
size="small"
|
|
||||||
className={styles.conditionCard}
|
|
||||||
bordered
|
|
||||||
extra={
|
|
||||||
<CloseOutlined
|
|
||||||
onClick={() => {
|
|
||||||
subOpt.remove(subField.name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Form.Item
|
|
||||||
label={t('flow.componentId')}
|
|
||||||
name={[subField.name, 'cpn_id']}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
placeholder={t('flow.componentId')}
|
|
||||||
options={componentIdOptions}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t('flow.operator')}
|
|
||||||
name={[subField.name, 'operator']}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
placeholder={t('flow.operator')}
|
|
||||||
options={switchOperatorOptions}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t('flow.value')}
|
|
||||||
name={[subField.name, 'value']}
|
|
||||||
>
|
|
||||||
<Input placeholder={t('flow.value')} />
|
|
||||||
</Form.Item>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
form?.setFieldValue(
|
|
||||||
['conditions', field.name, 'logical_operator'],
|
|
||||||
SwitchLogicOperatorOptions[0],
|
|
||||||
);
|
|
||||||
subOpt.add({
|
|
||||||
operator: SwitchOperatorOptions[0].value,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
block
|
|
||||||
className={styles.addButton}
|
|
||||||
>
|
|
||||||
+ Add Condition
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</Form.List>
|
/>
|
||||||
</Form.Item>
|
<ConditionCards
|
||||||
</Card>
|
name={`${ConditionKey}.${index}`}
|
||||||
|
></ConditionCards>
|
||||||
|
</section>
|
||||||
|
</FormContainer>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
<BlockButton
|
||||||
<Button onClick={() => add()} block className={styles.addButton}>
|
onClick={() =>
|
||||||
+ Add Case
|
append({ logical_operator: SwitchLogicOperatorOptions[0] })
|
||||||
</Button>
|
}
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Form.List>
|
|
||||||
<Divider />
|
|
||||||
<Form.Item
|
|
||||||
label={'ELSE'}
|
|
||||||
name={[SwitchElseTo]}
|
|
||||||
className={styles.elseCase}
|
|
||||||
>
|
>
|
||||||
<Select
|
add
|
||||||
allowClear
|
</BlockButton>
|
||||||
options={buildCategorizeToOptions(getSelectedConditionTos())}
|
</form>
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
20
web/src/pages/agent/form/switch-form/use-values.ts
Normal file
20
web/src/pages/agent/form/switch-form/use-values.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
const defaultValues = {
|
||||||
|
conditions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useValues(node?: RAGFlowNodeType) {
|
||||||
|
const values = useMemo(() => {
|
||||||
|
const formData = node?.data?.form;
|
||||||
|
if (isEmpty(formData)) {
|
||||||
|
return defaultValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
}, [node]);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
@ -104,14 +104,76 @@ const ExcludedNodes = [
|
|||||||
Operator.Note,
|
Operator.Note,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const useBuildComponentIdSelectOptions = (
|
export function useBuildBeginVariableOptions() {
|
||||||
nodeId?: string,
|
|
||||||
parentId?: string,
|
|
||||||
) => {
|
|
||||||
const nodes = useGraphStore((state) => state.nodes);
|
|
||||||
const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
|
const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
|
||||||
|
|
||||||
|
const options = useMemo(() => {
|
||||||
|
const query: BeginQuery[] = getBeginNodeDataQuery();
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: <span>Begin Input</span>,
|
||||||
|
title: 'Begin Input',
|
||||||
|
options: query.map((x) => ({
|
||||||
|
label: x.name,
|
||||||
|
value: `begin@${x.key}`,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, [getBeginNodeDataQuery]);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useBuildVariableOptions = (nodeId?: string) => {
|
||||||
const nodeOutputOptions = useBuildNodeOutputOptions(nodeId);
|
const nodeOutputOptions = useBuildNodeOutputOptions(nodeId);
|
||||||
|
const beginOptions = useBuildBeginVariableOptions();
|
||||||
|
|
||||||
|
const options = useMemo(() => {
|
||||||
|
return [...beginOptions, ...nodeOutputOptions];
|
||||||
|
}, [beginOptions, nodeOutputOptions]);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetComponentLabelByValue = (nodeId: string) => {
|
||||||
|
const options = useBuildVariableOptions(nodeId);
|
||||||
|
|
||||||
|
const flattenOptions = useMemo(() => {
|
||||||
|
return options.reduce<DefaultOptionType[]>((pre, cur) => {
|
||||||
|
return [...pre, ...cur.options];
|
||||||
|
}, []);
|
||||||
|
}, [options]);
|
||||||
|
|
||||||
|
const getLabel = useCallback(
|
||||||
|
(val?: string) => {
|
||||||
|
return flattenOptions.find((x) => x.value === val)?.label;
|
||||||
|
},
|
||||||
|
[flattenOptions],
|
||||||
|
);
|
||||||
|
return getLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useBuildQueryVariableOptions() {
|
||||||
|
const { data } = useFetchAgent();
|
||||||
|
const node = useContext(AgentFormContext);
|
||||||
|
const options = useBuildVariableOptions(node?.id);
|
||||||
|
|
||||||
|
const nextOptions = useMemo(() => {
|
||||||
|
const globalOptions = Object.keys(data?.dsl?.globals ?? {}).map((x) => ({
|
||||||
|
label: x,
|
||||||
|
value: x,
|
||||||
|
}));
|
||||||
|
return [
|
||||||
|
{ ...options[0], options: [...options[0]?.options, ...globalOptions] },
|
||||||
|
...options.slice(1),
|
||||||
|
];
|
||||||
|
}, [data.dsl.globals, options]);
|
||||||
|
|
||||||
|
return nextOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useBuildComponentIdOptions(nodeId?: string, parentId?: string) {
|
||||||
|
const nodes = useGraphStore((state) => state.nodes);
|
||||||
|
|
||||||
// Limit the nodes inside iteration to only reference peer nodes with the same parentId and other external nodes other than their parent nodes
|
// Limit the nodes inside iteration to only reference peer nodes with the same parentId and other external nodes other than their parent nodes
|
||||||
const filterChildNodesToSameParentOrExternal = useCallback(
|
const filterChildNodesToSameParentOrExternal = useCallback(
|
||||||
@ -140,57 +202,21 @@ export const useBuildComponentIdSelectOptions = (
|
|||||||
.map((x) => ({ label: x.data.name, value: x.id }));
|
.map((x) => ({ label: x.data.name, value: x.id }));
|
||||||
}, [nodes, nodeId, filterChildNodesToSameParentOrExternal]);
|
}, [nodes, nodeId, filterChildNodesToSameParentOrExternal]);
|
||||||
|
|
||||||
const options = useMemo(() => {
|
|
||||||
const query: BeginQuery[] = getBeginNodeDataQuery();
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: <span>Begin Input</span>,
|
label: <span>Component Output</span>,
|
||||||
title: 'Begin Input',
|
title: 'Component Output',
|
||||||
options: query.map((x) => ({
|
options: componentIdOptions,
|
||||||
label: x.name,
|
|
||||||
value: `begin@${x.key}`,
|
|
||||||
})),
|
|
||||||
},
|
},
|
||||||
...nodeOutputOptions,
|
|
||||||
];
|
];
|
||||||
}, [getBeginNodeDataQuery, nodeOutputOptions]);
|
}
|
||||||
|
|
||||||
return options;
|
export function useBuildComponentIdAndBeginOptions(
|
||||||
};
|
nodeId?: string,
|
||||||
|
parentId?: string,
|
||||||
export const useGetComponentLabelByValue = (nodeId: string) => {
|
) {
|
||||||
const options = useBuildComponentIdSelectOptions(nodeId);
|
const componentIdOptions = useBuildComponentIdOptions(nodeId, parentId);
|
||||||
|
const beginOptions = useBuildBeginVariableOptions();
|
||||||
const flattenOptions = useMemo(() => {
|
|
||||||
return options.reduce<DefaultOptionType[]>((pre, cur) => {
|
return [...beginOptions, ...componentIdOptions];
|
||||||
return [...pre, ...cur.options];
|
|
||||||
}, []);
|
|
||||||
}, [options]);
|
|
||||||
|
|
||||||
const getLabel = useCallback(
|
|
||||||
(val?: string) => {
|
|
||||||
return flattenOptions.find((x) => x.value === val)?.label;
|
|
||||||
},
|
|
||||||
[flattenOptions],
|
|
||||||
);
|
|
||||||
return getLabel;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useBuildQueryVariableOptions() {
|
|
||||||
const { data } = useFetchAgent();
|
|
||||||
const node = useContext(AgentFormContext);
|
|
||||||
const options = useBuildComponentIdSelectOptions(node?.id, node?.parentId);
|
|
||||||
|
|
||||||
const nextOptions = useMemo(() => {
|
|
||||||
const globalOptions = Object.keys(data?.dsl?.globals ?? {}).map((x) => ({
|
|
||||||
label: x,
|
|
||||||
value: x,
|
|
||||||
}));
|
|
||||||
return [
|
|
||||||
{ ...options[0], options: [...options[0]?.options, ...globalOptions] },
|
|
||||||
...options.slice(1),
|
|
||||||
];
|
|
||||||
}, [data.dsl.globals, options]);
|
|
||||||
|
|
||||||
return nextOptions;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user