chore: providers ux

This commit is contained in:
jialin
2026-02-03 18:21:08 +08:00
parent b2a8d27178
commit e8e982559d
32 changed files with 469 additions and 128 deletions
@@ -5,13 +5,14 @@ import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import React, { forwardRef, useImperativeHandle } from 'react';
import { maasProviderType } from '../config';
import ProxyConfig from './proxy_config';
const AdvanceConfig: React.FC<{
action: PageActionType;
provider?: maasProviderType;
ref?: any;
}> = forwardRef(({ action, provider }, ref) => {
const [form] = Form.useForm();
const form = Form.useFormInstance();
const intl = useIntl();
const editorRef = React.useRef<any>(null);
const [fileContent, setFileContent] = React.useState<string>('');
@@ -28,7 +29,8 @@ const AdvanceConfig: React.FC<{
return (
<>
<div data-field="customConfig"></div>
<div data-field="advanceConfig"></div>
<ProxyConfig></ProxyConfig>
<Form.Item
hidden
name="custom_config"
@@ -43,14 +45,13 @@ const AdvanceConfig: React.FC<{
</Form.Item>
<YamlEditor
ref={editorRef}
title={'Yaml'}
title={'Custom Config (YAML)'}
value={fileContent}
height={300}
onUpload={(content) => {
setFileContent(content);
}}
></YamlEditor>
<div className="scroller-to-holder" style={{ height: 1 }}></div>
</>
);
});
+61 -38
View File
@@ -1,12 +1,20 @@
import IconFont from '@/components/icon-font';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import CollapsePanel from '@/pages/_components/collapse-panel';
import { useWrapperContext } from '@/pages/_components/column-wrapper/use-wrapper-context';
import ScrollSpyTabs from '@/pages/_components/scroll-spy-tabs';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import {
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState
} from 'react';
import { maasProviderType } from '../config';
import FormContext from '../config/form-context';
import { MaasProviderItem as ListItem } from '../config/types';
import AccessToken from './access-token';
import AdvanceConfig from './advance-config';
@@ -31,9 +39,9 @@ const TABKeysMap = {
const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
const { action, provider, currentData, onFinish } = props;
const intl = useIntl();
const [form] = Form.useForm();
const { getScrollElementScrollableHeight } = useWrapperContext();
const [activeKey, setActiveKey] = useState<string[]>([TABKeysMap.BASIC]);
const [form] = Form.useForm();
const scrollTabsRef = useRef<any>(null);
const segmentOptions = [
@@ -50,17 +58,11 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
field: 'supportedModels'
},
{
value: TABKeysMap.CUSTOMCONFIG,
label: 'Custom Config',
value: TABKeysMap.ADVANCED,
label: intl.formatMessage({ id: 'resources.form.advanced' }),
icon: <IconFont type="icon-settings" />,
field: 'customConfig'
field: 'advanceConfig'
}
// {
// value: TABKeysMap.ADVANCED,
// label: intl.formatMessage({ id: 'resources.form.advanced' }),
// icon: <IconFont type="icon-settings" />,
// field: 'categories'
// }
];
const handleActiveChange = (key: string[]) => {
@@ -80,6 +82,15 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
}
}));
useEffect(() => {
if (action === PageAction.EDIT && currentData) {
form.setFieldsValue({
...currentData,
models: currentData.models || []
});
}
}, [form, currentData, action]);
return (
<ScrollSpyTabs
ref={scrollTabsRef}
@@ -93,34 +104,46 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
}}
getScrollElementScrollableHeight={getScrollElementScrollableHeight}
>
<Form form={form}>
<Basic />
<AccessToken />
<CollapsePanel
activeKey={activeKey}
accordion={false}
onChange={handleOnCollapseChange}
items={[
{
key: TABKeysMap.SUPPORTEDMODELS,
label: 'Supported Models',
forceRender: true,
children: <SupportedModels></SupportedModels>
},
{
key: TABKeysMap.CUSTOMCONFIG,
label: 'Custom Config',
forceRender: true,
children: (
<AdvanceConfig
action={action}
provider={provider}
></AdvanceConfig>
)
<FormContext.Provider value={{ providerType: provider, action }}>
<Form
form={form}
onFinish={onFinish}
initialValues={{
proxy_config: {
enabled: false,
url: '',
timeout: 30
}
]}
></CollapsePanel>
</Form>
}}
>
<Basic />
<AccessToken />
<CollapsePanel
activeKey={activeKey}
accordion={false}
onChange={handleOnCollapseChange}
items={[
{
key: TABKeysMap.SUPPORTEDMODELS,
label: 'Supported Models',
forceRender: true,
children: <SupportedModels></SupportedModels>
},
{
key: TABKeysMap.ADVANCED,
label: 'Advanced',
forceRender: true,
children: (
<AdvanceConfig
action={action}
provider={provider}
></AdvanceConfig>
)
}
]}
></CollapsePanel>
</Form>
</FormContext.Provider>
</ScrollSpyTabs>
);
});
@@ -0,0 +1,59 @@
import CheckboxField from '@/components/seal-form/checkbox-field';
import SealInput from '@/components/seal-form/seal-input';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import React from 'react';
import { useFormContext } from '../config/form-context';
const AdvanceConfig = () => {
const form = Form.useFormInstance();
const intl = useIntl();
const { action } = useFormContext();
const proxyConfigRef = React.useRef<any>({});
const proxyConfigEnabled = Form.useWatch(['proxy_config', 'enabled'], form);
const handleSpeculativeEnabledChange = (e: any) => {
if (e.target.checked) {
form.setFieldValue('speculative_config', {
enabled: true,
url: proxyConfigRef.current?.url || '',
timeout: proxyConfigRef.current?.timeout || 30
});
} else {
proxyConfigRef.current = form.getFieldValue('proxy_config');
}
};
return (
<>
<Form.Item
name={['proxy_config', 'enabled']}
valuePropName="checked"
style={{ marginBottom: 8 }}
>
<CheckboxField
label={'Enable Proxy'}
onChange={handleSpeculativeEnabledChange}
></CheckboxField>
</Form.Item>
{proxyConfigEnabled && (
<>
<Form.Item name={['proxy_config', 'url']}>
<SealInput.Input
label={'Proxy URL'}
placeholder="http://proxy.example.com:8080"
></SealInput.Input>
</Form.Item>
<Form.Item name={['proxy_config', 'timeout']}>
<SealInput.Number
label={'Proxy Timeout'}
placeholder="30"
></SealInput.Number>
</Form.Item>
</>
)}
</>
);
};
export default AdvanceConfig;
@@ -22,6 +22,13 @@ const SupportedModels = () => {
const intl = useIntl();
const form = Form.useFormInstance<FormData>();
const handleTestModel = (data: any) => {
data.loading = true;
setTimeout(() => {
data.loading = false;
}, 1000);
};
const renderModelItem = (
data: any,
{
@@ -32,6 +39,11 @@ const SupportedModels = () => {
return (
<SelectWrapper>
<SealSelect
suffixIcon={
<CheckCircleFilled
style={{ color: 'var(--ant-color-success)', fontSize: 16 }}
/>
}
alwaysFocus={true}
value={data.value}
onChange={onChange}
@@ -42,12 +54,12 @@ const SupportedModels = () => {
{ label: 'Model C', value: 'model_c' }
]}
/>
<span className="icon-wrapper">
<CheckCircleFilled
style={{ color: 'var(--ant-color-success)', fontSize: 16 }}
/>
</span>
<Button type="link" size="small">
<Button
type="link"
size="small"
loading={data.loading}
onClick={() => handleTestModel(data)}
>
Test
</Button>
</SelectWrapper>