Feat: Add a loop exception condition component.
This commit is contained in:
parent
52f9e7ca91
commit
f33a0bd735
8 changed files with 488 additions and 39 deletions
24
web/src/components/logical-operator.tsx
Normal file
24
web/src/components/logical-operator.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { useBuildSwitchLogicOperatorOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { RAGFlowFormItem } from './ragflow-form';
|
||||
import { RAGFlowSelect } from './ui/select';
|
||||
|
||||
type LogicalOperatorProps = { name: string };
|
||||
|
||||
export function LogicalOperator({ name }: LogicalOperatorProps) {
|
||||
const switchLogicOperatorOptions = useBuildSwitchLogicOperatorOptions();
|
||||
|
||||
return (
|
||||
<div className="relative min-w-14">
|
||||
<RAGFlowFormItem
|
||||
name={name}
|
||||
className="absolute top-1/2 -translate-y-1/2 right-1 left-0 z-10 bg-bg-base"
|
||||
>
|
||||
<RAGFlowSelect
|
||||
options={switchLogicOperatorOptions}
|
||||
triggerClassName="w-full text-xs px-1 py-0 h-6"
|
||||
></RAGFlowSelect>
|
||||
</RAGFlowFormItem>
|
||||
<div className="absolute border-l border-y w-5 right-0 top-4 bottom-4 rounded-l-lg"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -17,15 +17,13 @@ import { Input } from '@/components/ui/input';
|
|||
import { Separator } from '@/components/ui/separator';
|
||||
import { SwitchLogicOperator, SwitchOperatorOptions } from '@/constants/agent';
|
||||
import { useBuildSwitchOperatorOptions } from '@/hooks/logic-hooks/use-build-operator-options';
|
||||
import { useBuildSwitchLogicOperatorOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { useFetchKnowledgeMetadata } from '@/hooks/use-knowledge-request';
|
||||
import { PromptEditor } from '@/pages/agent/form/components/prompt-editor';
|
||||
import { Plus, X } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RAGFlowFormItem } from '../ragflow-form';
|
||||
import { RAGFlowSelect } from '../ui/select';
|
||||
import { LogicalOperator } from '../logical-operator';
|
||||
|
||||
export function MetadataFilterConditions({
|
||||
kbIds,
|
||||
|
|
@ -44,8 +42,6 @@ export function MetadataFilterConditions({
|
|||
|
||||
const switchOperatorOptions = useBuildSwitchOperatorOptions();
|
||||
|
||||
const switchLogicOperatorOptions = useBuildSwitchLogicOperatorOptions();
|
||||
|
||||
const { fields, remove, append } = useFieldArray({
|
||||
name,
|
||||
control: form.control,
|
||||
|
|
@ -53,14 +49,16 @@ export function MetadataFilterConditions({
|
|||
|
||||
const add = useCallback(
|
||||
(key: string) => () => {
|
||||
form.setValue(logic, SwitchLogicOperator.And);
|
||||
if (fields.length === 1) {
|
||||
form.setValue(logic, SwitchLogicOperator.And);
|
||||
}
|
||||
append({
|
||||
key,
|
||||
value: '',
|
||||
op: SwitchOperatorOptions[0].value,
|
||||
});
|
||||
},
|
||||
[append, form, logic],
|
||||
[append, fields.length, form, logic],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
@ -85,20 +83,7 @@ export function MetadataFilterConditions({
|
|||
</DropdownMenu>
|
||||
</div>
|
||||
<section className="flex">
|
||||
{fields.length > 1 && (
|
||||
<div className="relative min-w-14">
|
||||
<RAGFlowFormItem
|
||||
name={logic}
|
||||
className="absolute top-1/2 -translate-y-1/2 right-1 left-0 z-10 bg-bg-base"
|
||||
>
|
||||
<RAGFlowSelect
|
||||
options={switchLogicOperatorOptions}
|
||||
triggerClassName="w-full text-xs px-1 py-0 h-6"
|
||||
></RAGFlowSelect>
|
||||
</RAGFlowFormItem>
|
||||
<div className="absolute border-l border-y w-5 right-0 top-4 bottom-4 rounded-l-lg"></div>
|
||||
</div>
|
||||
)}
|
||||
{fields.length > 1 && <LogicalOperator name={logic}></LogicalOperator>}
|
||||
<div className="space-y-5 flex-1">
|
||||
{fields.map((field, index) => {
|
||||
const typeField = `${name}.${index}.key`;
|
||||
|
|
|
|||
|
|
@ -902,3 +902,84 @@ export const ArrayFields = [
|
|||
TypesWithArray.ArrayString,
|
||||
TypesWithArray.ArrayObject,
|
||||
];
|
||||
|
||||
export enum InputMode {
|
||||
Constant = 'constant',
|
||||
Variable = 'variable',
|
||||
}
|
||||
|
||||
export enum LoopTerminationComparisonOperator {
|
||||
Contains = ComparisonOperator.Contains,
|
||||
NotContains = ComparisonOperator.NotContains,
|
||||
StartWith = ComparisonOperator.StartWith,
|
||||
EndWith = ComparisonOperator.EndWith,
|
||||
IsEmpty = 'is empty',
|
||||
IsNotEmpty = 'is not empty',
|
||||
Is = 'is',
|
||||
IsNot = 'is not',
|
||||
}
|
||||
|
||||
export const LoopTerminationStringComparisonOperator = [
|
||||
LoopTerminationComparisonOperator.Contains,
|
||||
LoopTerminationComparisonOperator.NotContains,
|
||||
LoopTerminationComparisonOperator.StartWith,
|
||||
LoopTerminationComparisonOperator.EndWith,
|
||||
LoopTerminationComparisonOperator.Is,
|
||||
LoopTerminationComparisonOperator.IsNot,
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
|
||||
export const LoopTerminationBooleanComparisonOperator = [
|
||||
LoopTerminationComparisonOperator.Is,
|
||||
LoopTerminationComparisonOperator.IsNot,
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
// object or object array
|
||||
export const LoopTerminationObjectComparisonOperator = [
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
|
||||
// string array or number array
|
||||
export const LoopTerminationStringArrayComparisonOperator = [
|
||||
LoopTerminationComparisonOperator.Contains,
|
||||
LoopTerminationComparisonOperator.NotContains,
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
|
||||
export const LoopTerminationBooleanArrayComparisonOperator = [
|
||||
LoopTerminationComparisonOperator.Is,
|
||||
LoopTerminationComparisonOperator.IsNot,
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
|
||||
export const LoopTerminationNumberComparisonOperator = [
|
||||
ComparisonOperator.Equal,
|
||||
ComparisonOperator.NotEqual,
|
||||
ComparisonOperator.GreatThan,
|
||||
ComparisonOperator.LessThan,
|
||||
ComparisonOperator.GreatEqual,
|
||||
ComparisonOperator.LessEqual,
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
|
||||
export const LoopTerminationStringComparisonOperatorMap = {
|
||||
[TypesWithArray.String]: LoopTerminationStringComparisonOperator,
|
||||
[TypesWithArray.Number]: LoopTerminationNumberComparisonOperator,
|
||||
[TypesWithArray.Boolean]: LoopTerminationBooleanComparisonOperator,
|
||||
[TypesWithArray.Object]: LoopTerminationObjectComparisonOperator,
|
||||
[TypesWithArray.ArrayString]: LoopTerminationStringArrayComparisonOperator,
|
||||
[TypesWithArray.ArrayNumber]: LoopTerminationStringArrayComparisonOperator,
|
||||
[TypesWithArray.ArrayBoolean]: LoopTerminationBooleanArrayComparisonOperator,
|
||||
[TypesWithArray.ArrayObject]: LoopTerminationObjectComparisonOperator,
|
||||
};
|
||||
|
||||
export enum RadioVariable {
|
||||
Yes = 'yes',
|
||||
No = 'no',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,26 +8,21 @@ import { Label } from '@/components/ui/label';
|
|||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { buildOptions } from '@/utils/form';
|
||||
import { Editor, loader } from '@monaco-editor/react';
|
||||
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
||||
import { X } from 'lucide-react';
|
||||
import { ReactNode, useCallback } from 'react';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
import { TypesWithArray } from '../../constant';
|
||||
import { buildConversationVariableSelectOptions } from '../../utils';
|
||||
import { InputMode, TypesWithArray } from '../../constant';
|
||||
import {
|
||||
InputModeOptions,
|
||||
buildConversationVariableSelectOptions,
|
||||
} from '../../utils';
|
||||
import { DynamicFormHeader } from '../components/dynamic-fom-header';
|
||||
import { QueryVariable } from '../components/query-variable';
|
||||
|
||||
loader.config({ paths: { vs: '/vs' } });
|
||||
|
||||
enum InputMode {
|
||||
Constant = 'constant',
|
||||
Variable = 'variable',
|
||||
}
|
||||
|
||||
const InputModeOptions = buildOptions(InputMode);
|
||||
|
||||
type SelectKeysProps = {
|
||||
name: string;
|
||||
label: ReactNode;
|
||||
|
|
@ -112,12 +107,6 @@ export function DynamicVariables({
|
|||
(mode: string, valueFieldAlias: string, operatorFieldAlias: string) => {
|
||||
const variableType = form.getValues(operatorFieldAlias);
|
||||
initializeValue(mode, variableType, valueFieldAlias);
|
||||
// if (mode === InputMode.Variable) {
|
||||
// form.setValue(valueFieldAlias, '');
|
||||
// } else {
|
||||
// const val = ConstantValueMap[variableType as TypesWithArray];
|
||||
// form.setValue(valueFieldAlias, val);
|
||||
// }
|
||||
},
|
||||
[form, initializeValue],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { SliderInputFormField } from '@/components/slider-input-form-field';
|
||||
import { Form } from '@/components/ui/form';
|
||||
import { FormLayout } from '@/constants/form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { memo } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
|
@ -9,6 +11,7 @@ import { useWatchFormChange } from '../../hooks/use-watch-form-change';
|
|||
import { INextOperatorForm } from '../../interface';
|
||||
import { FormWrapper } from '../components/form-wrapper';
|
||||
import { DynamicVariables } from './dynamic-variables';
|
||||
import { LoopTerminationCondition } from './loop-termination-condition';
|
||||
|
||||
const FormSchema = z.object({
|
||||
loop_variables: z.array(
|
||||
|
|
@ -19,14 +22,16 @@ const FormSchema = z.object({
|
|||
input_mode: z.string(),
|
||||
}),
|
||||
),
|
||||
logical_operator: z.string(),
|
||||
loop_termination_condition: z.array(
|
||||
z.object({
|
||||
variable: z.string().optional(),
|
||||
operator: z.string().optional(),
|
||||
value: z.string().or(z.number()).or(z.boolean()).optional(),
|
||||
input_mode: z.string(),
|
||||
input_mode: z.string().optional(),
|
||||
}),
|
||||
),
|
||||
maximum_loop_count: z.number(),
|
||||
});
|
||||
|
||||
function LoopForm({ node }: INextOperatorForm) {
|
||||
|
|
@ -46,6 +51,17 @@ function LoopForm({ node }: INextOperatorForm) {
|
|||
name="loop_variables"
|
||||
label="Variables"
|
||||
></DynamicVariables>
|
||||
<LoopTerminationCondition
|
||||
name="loop_termination_condition"
|
||||
label="Termination Condition"
|
||||
></LoopTerminationCondition>
|
||||
<SliderInputFormField
|
||||
min={1}
|
||||
max={100}
|
||||
name="maximum_loop_count"
|
||||
label="maximum_loop_count"
|
||||
layout={FormLayout.Vertical}
|
||||
></SliderInputFormField>
|
||||
</FormWrapper>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,333 @@
|
|||
import { LogicalOperator } from '@/components/logical-operator';
|
||||
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { SwitchLogicOperator } from '@/constants/agent';
|
||||
import { loader } from '@monaco-editor/react';
|
||||
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
||||
import { toLower } from 'lodash';
|
||||
import { X } from 'lucide-react';
|
||||
import { ReactNode, useCallback } from 'react';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
import {
|
||||
InputMode,
|
||||
JsonSchemaDataType,
|
||||
LoopTerminationComparisonOperator,
|
||||
RadioVariable,
|
||||
} from '../../constant';
|
||||
import { useGetVariableLabelOrTypeByValue } from '../../hooks/use-get-begin-query';
|
||||
import { InputModeOptions } from '../../utils';
|
||||
import { DynamicFormHeader } from '../components/dynamic-fom-header';
|
||||
import { QueryVariable } from '../components/query-variable';
|
||||
import { useBuildLogicalOptions } from './use-build-logical-options';
|
||||
|
||||
loader.config({ paths: { vs: '/vs' } });
|
||||
|
||||
type SelectKeysProps = {
|
||||
name: string;
|
||||
label: ReactNode;
|
||||
tooltip?: string;
|
||||
keyField?: string;
|
||||
valueField?: string;
|
||||
operatorField?: string;
|
||||
modeField?: string;
|
||||
};
|
||||
|
||||
type RadioGroupProps = React.ComponentProps<typeof RadioGroupPrimitive.Root>;
|
||||
|
||||
type RadioButtonProps = Partial<
|
||||
Omit<RadioGroupProps, 'onValueChange'> & {
|
||||
onChange: RadioGroupProps['onValueChange'];
|
||||
}
|
||||
>;
|
||||
|
||||
function RadioButton({ value, onChange }: RadioButtonProps) {
|
||||
return (
|
||||
<RadioGroup
|
||||
defaultValue={RadioVariable.Yes}
|
||||
className="flex"
|
||||
value={value}
|
||||
onValueChange={onChange}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value={RadioVariable.Yes} id="r1" />
|
||||
<Label htmlFor="r1">Yes</Label>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<RadioGroupItem value="no" id="r2" />
|
||||
<Label htmlFor="r2">No</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const EmptyFields = [
|
||||
LoopTerminationComparisonOperator.IsEmpty,
|
||||
LoopTerminationComparisonOperator.IsNotEmpty,
|
||||
];
|
||||
|
||||
const LogicalOperatorFieldName = 'logical_operator';
|
||||
|
||||
export function LoopTerminationCondition({
|
||||
name,
|
||||
label,
|
||||
tooltip,
|
||||
keyField = 'variable',
|
||||
valueField = 'value',
|
||||
operatorField = 'operator',
|
||||
modeField = 'input_mode',
|
||||
}: SelectKeysProps) {
|
||||
const form = useFormContext();
|
||||
const { getType } = useGetVariableLabelOrTypeByValue();
|
||||
|
||||
const { fields, remove, append } = useFieldArray({
|
||||
name: name,
|
||||
control: form.control,
|
||||
});
|
||||
|
||||
const { buildLogicalOptions } = useBuildLogicalOptions();
|
||||
|
||||
const getVariableType = useCallback(
|
||||
(keyFieldName: string) => {
|
||||
const key = form.getValues(keyFieldName);
|
||||
return toLower(getType(key));
|
||||
},
|
||||
[form, getType],
|
||||
);
|
||||
|
||||
const initializeMode = useCallback(
|
||||
(modeFieldAlias: string, keyFieldAlias: string) => {
|
||||
const keyType = getVariableType(keyFieldAlias);
|
||||
|
||||
if (keyType === JsonSchemaDataType.Number) {
|
||||
form.setValue(modeFieldAlias, InputMode.Constant, {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
[form, getVariableType],
|
||||
);
|
||||
|
||||
const initializeValue = useCallback(
|
||||
(valueFieldAlias: string, keyFieldAlias: string) => {
|
||||
const keyType = getVariableType(keyFieldAlias);
|
||||
let initialValue: string | boolean | number = '';
|
||||
|
||||
if (keyType === JsonSchemaDataType.Number) {
|
||||
initialValue = 0;
|
||||
} else if (keyType === JsonSchemaDataType.Boolean) {
|
||||
initialValue = RadioVariable.Yes;
|
||||
}
|
||||
|
||||
form.setValue(valueFieldAlias, initialValue, {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
});
|
||||
},
|
||||
[form, getVariableType],
|
||||
);
|
||||
|
||||
const handleVariableChange = useCallback(
|
||||
(
|
||||
operatorFieldAlias: string,
|
||||
valueFieldAlias: string,
|
||||
keyFieldAlias: string,
|
||||
modeFieldAlias: string,
|
||||
) => {
|
||||
return () => {
|
||||
const logicalOptions = buildLogicalOptions(
|
||||
getVariableType(keyFieldAlias),
|
||||
);
|
||||
|
||||
form.setValue(operatorFieldAlias, logicalOptions?.at(0)?.value, {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
});
|
||||
|
||||
initializeMode(modeFieldAlias, keyFieldAlias);
|
||||
|
||||
initializeValue(valueFieldAlias, keyFieldAlias);
|
||||
};
|
||||
},
|
||||
[
|
||||
buildLogicalOptions,
|
||||
form,
|
||||
getVariableType,
|
||||
initializeMode,
|
||||
initializeValue,
|
||||
],
|
||||
);
|
||||
|
||||
const handleOperatorChange = useCallback(
|
||||
(
|
||||
valueFieldAlias: string,
|
||||
keyFieldAlias: string,
|
||||
modeFieldAlias: string,
|
||||
) => {
|
||||
initializeMode(modeFieldAlias, keyFieldAlias);
|
||||
initializeValue(valueFieldAlias, keyFieldAlias);
|
||||
},
|
||||
[initializeMode, initializeValue],
|
||||
);
|
||||
|
||||
const handleModeChange = useCallback(
|
||||
(mode: string, valueFieldAlias: string) => {
|
||||
form.setValue(valueFieldAlias, mode === InputMode.Constant ? 0 : '', {
|
||||
shouldDirty: true,
|
||||
});
|
||||
},
|
||||
[form],
|
||||
);
|
||||
|
||||
const renderParameterPanel = useCallback(
|
||||
(
|
||||
keyFieldName: string,
|
||||
valueFieldAlias: string,
|
||||
modeFieldAlias: string,
|
||||
operatorFieldAlias: string,
|
||||
) => {
|
||||
const type = getVariableType(keyFieldName);
|
||||
const mode = form.getValues(modeFieldAlias);
|
||||
const operator = form.getValues(operatorFieldAlias);
|
||||
|
||||
if (EmptyFields.includes(operator)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type === JsonSchemaDataType.Number) {
|
||||
return (
|
||||
<section className="flex items-center gap-1">
|
||||
<RAGFlowFormItem name={modeFieldAlias}>
|
||||
{(field) => (
|
||||
<SelectWithSearch
|
||||
value={field.value}
|
||||
onChange={(val) => {
|
||||
handleModeChange(val, valueFieldAlias);
|
||||
field.onChange(val);
|
||||
}}
|
||||
options={InputModeOptions}
|
||||
></SelectWithSearch>
|
||||
)}
|
||||
</RAGFlowFormItem>
|
||||
<Separator className="w-2" />
|
||||
{mode === InputMode.Constant ? (
|
||||
<RAGFlowFormItem name={valueFieldAlias}>
|
||||
<Input type="number" />
|
||||
</RAGFlowFormItem>
|
||||
) : (
|
||||
<QueryVariable
|
||||
types={[JsonSchemaDataType.Number]}
|
||||
hideLabel
|
||||
pureQuery
|
||||
name={valueFieldAlias}
|
||||
className="flex-1 min-w-0"
|
||||
></QueryVariable>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === JsonSchemaDataType.Boolean) {
|
||||
return (
|
||||
<RAGFlowFormItem name={valueFieldAlias} className="w-full">
|
||||
<RadioButton></RadioButton>
|
||||
</RAGFlowFormItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<RAGFlowFormItem name={valueFieldAlias} className="w-full">
|
||||
<Input />
|
||||
</RAGFlowFormItem>
|
||||
);
|
||||
},
|
||||
[form, getVariableType, handleModeChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="space-y-2">
|
||||
<DynamicFormHeader
|
||||
label={label}
|
||||
tooltip={tooltip}
|
||||
onClick={() => {
|
||||
if (fields.length === 1) {
|
||||
form.setValue(LogicalOperatorFieldName, SwitchLogicOperator.And);
|
||||
}
|
||||
append({ [keyField]: '', [valueField]: '' });
|
||||
}}
|
||||
></DynamicFormHeader>
|
||||
<section className="flex">
|
||||
{fields.length > 1 && (
|
||||
<LogicalOperator name={LogicalOperatorFieldName}></LogicalOperator>
|
||||
)}
|
||||
<div className="space-y-5 flex-1 min-w-0">
|
||||
{fields.map((field, index) => {
|
||||
const keyFieldAlias = `${name}.${index}.${keyField}`;
|
||||
const valueFieldAlias = `${name}.${index}.${valueField}`;
|
||||
const operatorFieldAlias = `${name}.${index}.${operatorField}`;
|
||||
const modeFieldAlias = `${name}.${index}.${modeField}`;
|
||||
|
||||
return (
|
||||
<section key={field.id} className="flex gap-2">
|
||||
<div className="flex-1 space-y-3 min-w-0">
|
||||
<div className="flex items-center">
|
||||
<QueryVariable
|
||||
name={keyFieldAlias}
|
||||
hideLabel
|
||||
className="flex-1 min-w-0"
|
||||
onChange={handleVariableChange(
|
||||
operatorFieldAlias,
|
||||
valueFieldAlias,
|
||||
keyFieldAlias,
|
||||
modeFieldAlias,
|
||||
)}
|
||||
></QueryVariable>
|
||||
|
||||
<Separator className="w-2" />
|
||||
|
||||
<RAGFlowFormItem
|
||||
name={operatorFieldAlias}
|
||||
className="w-1/3"
|
||||
>
|
||||
{({ onChange, value }) => (
|
||||
<SelectWithSearch
|
||||
value={value}
|
||||
onChange={(val) => {
|
||||
handleOperatorChange(
|
||||
valueFieldAlias,
|
||||
keyFieldAlias,
|
||||
modeFieldAlias,
|
||||
);
|
||||
onChange(val);
|
||||
}}
|
||||
options={buildLogicalOptions(
|
||||
getVariableType(keyFieldAlias),
|
||||
)}
|
||||
></SelectWithSearch>
|
||||
)}
|
||||
</RAGFlowFormItem>
|
||||
</div>
|
||||
{renderParameterPanel(
|
||||
keyFieldAlias,
|
||||
valueFieldAlias,
|
||||
modeFieldAlias,
|
||||
operatorFieldAlias,
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Button variant={'ghost'} onClick={() => remove(index)}>
|
||||
<X />
|
||||
</Button>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { lowerCase } from 'lodash';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LoopTerminationStringComparisonOperatorMap } from '../../constant';
|
||||
|
||||
export function useBuildLogicalOptions() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const buildLogicalOptions = useCallback((type: string) => {
|
||||
return LoopTerminationStringComparisonOperatorMap[
|
||||
lowerCase(type) as keyof typeof LoopTerminationStringComparisonOperatorMap
|
||||
]?.map((x) => ({ label: x, value: x }));
|
||||
}, []);
|
||||
|
||||
return {
|
||||
buildLogicalOptions,
|
||||
};
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from '@/interfaces/database/agent';
|
||||
import { DSLComponents, RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||
import { buildSelectOptions } from '@/utils/component-util';
|
||||
import { removeUselessFieldsFromValues } from '@/utils/form';
|
||||
import { buildOptions, removeUselessFieldsFromValues } from '@/utils/form';
|
||||
import { Edge, Node, XYPosition } from '@xyflow/react';
|
||||
import { FormInstance, FormListFieldData } from 'antd';
|
||||
import { humanId } from 'human-id';
|
||||
|
|
@ -27,6 +27,7 @@ import {
|
|||
CategorizeAnchorPointPositions,
|
||||
FileType,
|
||||
FileTypeSuffixMap,
|
||||
InputMode,
|
||||
NoCopyOperatorsList,
|
||||
NoDebugOperatorsList,
|
||||
NodeHandleId,
|
||||
|
|
@ -772,3 +773,5 @@ export function getArrayElementType(type: string) {
|
|||
export function buildConversationVariableSelectOptions() {
|
||||
return buildSelectOptions(Object.values(TypesWithArray));
|
||||
}
|
||||
|
||||
export const InputModeOptions = buildOptions(InputMode);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue