import { apiInterceptors, getKeys, getVariablesByKey } from '@/client/api'; import { IFlowUpdateParam, IGetKeysResponseData, IVariableItem } from '@/types/flow'; import { buildVariableString } from '@/utils/flow'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Cascader, Form, Input, InputNumber, Modal, Select, Space } from 'antd'; import { DefaultOptionType } from 'antd/es/cascader'; import { uniqBy } from 'lodash'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; const { Option } = Select; const VALUE_TYPES = ['str', 'int', 'float', 'bool', 'ref'] as const; type ValueType = (typeof VALUE_TYPES)[number]; type Props = { flowInfo?: IFlowUpdateParam; setFlowInfo: React.Dispatch>; }; export const AddFlowVariableModal: React.FC = ({ flowInfo, setFlowInfo }) => { const { t } = useTranslation(); const [isModalOpen, setIsModalOpen] = useState(false); const [form] = Form.useForm(); const [controlTypes, setControlTypes] = useState(['str']); const [refVariableOptions, setRefVariableOptions] = useState([]); useEffect(() => { getKeysData(); }, []); const getKeysData = async () => { const [err, res] = await apiInterceptors(getKeys()); if (err) return; const keyOptions = res?.map(({ key, label, scope }: IGetKeysResponseData) => ({ value: key, label, scope, isLeaf: false, })); setRefVariableOptions(keyOptions); }; const onFinish = (values: any) => { const newFlowInfo = { ...flowInfo, variables: values?.parameters || [] } as IFlowUpdateParam; setFlowInfo(newFlowInfo); setIsModalOpen(false); }; const onNameChange = (e: React.ChangeEvent, index: number) => { const name = e.target.value; const newValue = name ?.split('_') ?.map(word => word.charAt(0).toUpperCase() + word.slice(1)) ?.join(' '); form.setFields([ { name: ['parameters', index, 'label'], value: newValue, }, ]); }; const onValueTypeChange = (type: ValueType, index: number) => { const newControlTypes = [...controlTypes]; newControlTypes[index] = type; setControlTypes(newControlTypes); }; const loadData = (selectedOptions: DefaultOptionType[]) => { const targetOption = selectedOptions[selectedOptions.length - 1]; const { value, scope } = targetOption as DefaultOptionType & { scope: string }; setTimeout(async () => { const [err, res] = await apiInterceptors(getVariablesByKey({ key: value as string, scope })); if (err) return; if (res?.total_count === 0) { targetOption.isLeaf = true; return; } const uniqueItems = uniqBy(res?.items, 'name'); targetOption.children = uniqueItems?.map(item => ({ value: item?.name, label: item.label, item: item, })); setRefVariableOptions([...refVariableOptions]); }, 1000); }; const onRefTypeValueChange = ( value: (string | number | null)[], selectedOptions: DefaultOptionType[], index: number, ) => { // when select ref variable, must be select two options(key and variable) if (value?.length !== 2) return; const [selectRefKey, selectedRefVariable] = selectedOptions as DefaultOptionType[]; const selectedVariable = selectRefKey?.children?.find( ({ value }) => value === selectedRefVariable?.value, ) as DefaultOptionType & { item: IVariableItem }; // build variable string by rule const variableStr = buildVariableString(selectedVariable?.item); const parameters = form.getFieldValue('parameters'); const param = parameters?.[index]; if (param) { param.value = variableStr; param.category = selectedVariable?.item?.category; param.value_type = selectedVariable?.item?.value_type; form.setFieldsValue({ parameters: [...parameters], }); } }; // Helper function to render the appropriate control component const renderVariableValue = (type: string, index: number) => { switch (type) { case 'ref': return ( onRefTypeValueChange(value, selectedOptions, index)} changeOnSelect /> ); case 'str': return ; case 'int': return ( value?.replace(/[^\-?\d]/g, '') || 0} style={{ width: '100%' }} /> ); case 'float': return ; case 'bool': return ( ); default: return ; } }; return ( <> , , ]} >
{(fields, { add, remove }) => ( <> {fields.map(({ key, name, ...restField }, index) => ( onNameChange(e, index)} /> {renderVariableValue(controlTypes[index], index)} remove(name)} /> ))} )}
); };