226 lines
6.3 KiB
TypeScript
226 lines
6.3 KiB
TypeScript
import MetadataList from '@/components/metadata-list';
|
|
import SealCascader from '@/components/seal-form/seal-cascader';
|
|
import SealInput from '@/components/seal-form/seal-input';
|
|
import { useIntl } from '@umijs/max';
|
|
import { Form } from 'antd';
|
|
import _ from 'lodash';
|
|
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
|
import { FormData } from '../config/types';
|
|
import useEndpointSourceModels from '../hooks/use-endpoint-source-models';
|
|
|
|
const EndpointsForm = forwardRef((props, ref) => {
|
|
const intl = useIntl();
|
|
const { sourceModels, loading, fetchSourceModels } =
|
|
useEndpointSourceModels();
|
|
const form = Form.useFormInstance<FormData>();
|
|
const endpoints = Form.useWatch('endpoints', form) || [];
|
|
const [fallbackValues, setFallbackValues] = useState<{ value: any[] }>({
|
|
value: []
|
|
});
|
|
const [dataList, setDataList] = useState<
|
|
{
|
|
weight: number | null;
|
|
value: any[];
|
|
}[]
|
|
>([]);
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
initFallbackValues: (values: { value: any[] }) => {
|
|
setFallbackValues(values);
|
|
},
|
|
initDataList: (
|
|
list: {
|
|
weight: number | null;
|
|
value: any[];
|
|
}[]
|
|
) => {
|
|
setDataList(list);
|
|
}
|
|
}));
|
|
|
|
const handleEndpointsChange = (
|
|
value: any[],
|
|
index: number,
|
|
options: any[]
|
|
) => {
|
|
const selectedOption =
|
|
options?.find?.((opt) => opt.value === value[1]) || {};
|
|
const endpointList = [...endpoints];
|
|
endpointList[index] = {
|
|
weight: endpointList[index]?.weight || null,
|
|
...selectedOption?.data
|
|
};
|
|
|
|
form.setFieldValue('endpoints', [...endpointList]);
|
|
|
|
const newDataList = [...dataList];
|
|
newDataList[index] = {
|
|
weight: newDataList[index]?.weight || null,
|
|
value: value
|
|
};
|
|
setDataList(newDataList);
|
|
};
|
|
|
|
const handleOnAdd = () => {
|
|
const newDataList = [
|
|
...dataList,
|
|
{
|
|
weight: null,
|
|
value: []
|
|
}
|
|
];
|
|
setDataList(newDataList);
|
|
};
|
|
|
|
const handleOnDelete = (index: number, item: any) => {
|
|
const newDataList = dataList.filter((_, i) => i !== index);
|
|
setDataList(newDataList);
|
|
|
|
const endpointList = [...endpoints];
|
|
endpointList.splice(index, 1);
|
|
form.setFieldValue('endpoints', [...endpointList]);
|
|
};
|
|
|
|
const handleFallbackChange = (value: any[], options?: any[]) => {
|
|
const selectedOption =
|
|
options?.find?.((opt) => opt.value === value[1]) || {};
|
|
|
|
console.log('fallback selected option data:', value);
|
|
form.setFieldValue('fallback_endpoint', {
|
|
...selectedOption?.data
|
|
});
|
|
setFallbackValues({
|
|
value: value
|
|
});
|
|
};
|
|
|
|
const handleOnWeightChange = (value: any, index: number) => {
|
|
const endpointList = [...endpoints];
|
|
if (endpointList[index]) {
|
|
endpointList[index] = {
|
|
...endpointList[index],
|
|
weight: value
|
|
};
|
|
form.setFieldValue('endpoints', [...endpointList]);
|
|
}
|
|
|
|
const newDataList = [...dataList];
|
|
newDataList[index] = {
|
|
...newDataList[index],
|
|
weight: value
|
|
};
|
|
setDataList(newDataList);
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchSourceModels();
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<Form.Item
|
|
name="endpoints"
|
|
data-field="endpoints"
|
|
rules={[
|
|
({ getFieldValue }) => ({
|
|
validator(rule, value) {
|
|
if (_.keys(value).length > 0) {
|
|
if (_.some(_.keys(value), (k: string) => !value[k])) {
|
|
return Promise.reject(
|
|
intl.formatMessage(
|
|
{
|
|
id: 'common.validate.value'
|
|
},
|
|
{
|
|
name: intl.formatMessage({
|
|
id: 'models.form.selector'
|
|
})
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
return Promise.resolve();
|
|
}
|
|
})
|
|
]}
|
|
>
|
|
<MetadataList
|
|
label={''}
|
|
styles={{
|
|
wrapper: {
|
|
paddingTop: 14
|
|
}
|
|
}}
|
|
dataList={dataList}
|
|
btnText={intl.formatMessage({ id: 'accesses.form.endpoint.add' })}
|
|
onAdd={handleOnAdd}
|
|
onDelete={handleOnDelete}
|
|
>
|
|
{(item, index) => (
|
|
<>
|
|
<SealCascader
|
|
required
|
|
showSearch
|
|
expandTrigger="hover"
|
|
multiple={false}
|
|
onChange={(value, options) =>
|
|
handleEndpointsChange(value, index, options)
|
|
}
|
|
classNames={{
|
|
popup: {
|
|
root: 'cascader-popup-wrapper gpu-selector'
|
|
}
|
|
}}
|
|
maxTagCount={1}
|
|
placeholder={intl.formatMessage({
|
|
id: 'accesses.form.endpoint.model'
|
|
})}
|
|
value={item.value}
|
|
options={sourceModels}
|
|
showCheckedStrategy="SHOW_CHILD"
|
|
getPopupContainer={(triggerNode) => triggerNode.parentNode}
|
|
></SealCascader>
|
|
<span className="seprator">:</span>
|
|
<SealInput.Number
|
|
style={{ flex: 100 }}
|
|
min={0}
|
|
value={item.weight}
|
|
onChange={(value) => handleOnWeightChange(value, index)}
|
|
placeholder={intl.formatMessage({
|
|
id: 'accesses.form.endpoint.weight'
|
|
})}
|
|
></SealInput.Number>
|
|
</>
|
|
)}
|
|
</MetadataList>
|
|
</Form.Item>
|
|
<Form.Item name="fallback_endpoint">
|
|
<div>
|
|
<SealCascader
|
|
showSearch
|
|
expandTrigger="hover"
|
|
multiple={false}
|
|
classNames={{
|
|
popup: {
|
|
root: 'cascader-popup-wrapper gpu-selector'
|
|
}
|
|
}}
|
|
label={intl.formatMessage({
|
|
id: 'accesses.form.endpoint.fallback'
|
|
})}
|
|
maxTagCount={1}
|
|
value={fallbackValues.value}
|
|
options={sourceModels}
|
|
onChange={(value, options) => handleFallbackChange(value, options)}
|
|
showCheckedStrategy="SHOW_CHILD"
|
|
getPopupContainer={(triggerNode) => triggerNode.parentNode}
|
|
></SealCascader>
|
|
</div>
|
|
</Form.Item>
|
|
</>
|
|
);
|
|
});
|
|
|
|
export default EndpointsForm;
|