feat: provider form
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import ListInput from '@/components/list-input';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import { FormData } from '../config/types';
|
||||
|
||||
const AccessToken = () => {
|
||||
const intl = useIntl();
|
||||
const form = Form.useFormInstance<FormData>();
|
||||
|
||||
const handleOnChange = (values: string[]) => {};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="tokens">
|
||||
<ListInput
|
||||
btnText="Add Token"
|
||||
label="Access Tokens"
|
||||
dataList={[]}
|
||||
onChange={handleOnChange}
|
||||
></ListInput>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessToken;
|
||||
@@ -0,0 +1,58 @@
|
||||
import SealInput from '@/components/seal-form/seal-input';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import YamlEditor from '@/pages/_components/yaml-editor';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import React, { forwardRef, useImperativeHandle } from 'react';
|
||||
import { maasProviderType } from '../config';
|
||||
|
||||
const AdvanceConfig: React.FC<{
|
||||
action: PageActionType;
|
||||
provider?: maasProviderType;
|
||||
ref?: any;
|
||||
}> = forwardRef(({ action, provider }, ref) => {
|
||||
const [form] = Form.useForm();
|
||||
const intl = useIntl();
|
||||
const editorRef = React.useRef<any>(null);
|
||||
const [fileContent, setFileContent] = React.useState<string>('');
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getYamlValue: () => {
|
||||
return editorRef.current?.getValue();
|
||||
},
|
||||
setYamlValue: (values: any) => {
|
||||
console.log('setYamlValue:', values);
|
||||
editorRef.current?.setValue(values || '');
|
||||
}
|
||||
}));
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-field="customConfig"></div>
|
||||
<Form.Item
|
||||
hidden
|
||||
name="custom_config"
|
||||
rules={[
|
||||
{
|
||||
required: false,
|
||||
message: ''
|
||||
}
|
||||
]}
|
||||
>
|
||||
<SealInput.TextArea required={false} trim={false}></SealInput.TextArea>
|
||||
</Form.Item>
|
||||
<YamlEditor
|
||||
ref={editorRef}
|
||||
title={'Yaml'}
|
||||
value={fileContent}
|
||||
height={300}
|
||||
onUpload={(content) => {
|
||||
setFileContent(content);
|
||||
}}
|
||||
></YamlEditor>
|
||||
<div className="scroller-to-holder" style={{ height: 1 }}></div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default AdvanceConfig;
|
||||
@@ -0,0 +1,38 @@
|
||||
import SealInput from '@/components/seal-form/seal-input';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import { FormData } from '../config/types';
|
||||
|
||||
const Basic = () => {
|
||||
const intl = useIntl();
|
||||
const form = Form.useFormInstance<FormData>();
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="name" data-field="name">
|
||||
<SealInput.Input
|
||||
required
|
||||
label={intl.formatMessage({
|
||||
id: 'common.table.name'
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="provider" hidden>
|
||||
<SealInput.Input
|
||||
label={intl.formatMessage({
|
||||
id: 'providers.table.providerName'
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="description">
|
||||
<SealInput.TextArea
|
||||
scaleSize={true}
|
||||
label={intl.formatMessage({
|
||||
id: 'common.table.description'
|
||||
})}
|
||||
></SealInput.TextArea>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Basic;
|
||||
@@ -1,17 +1,75 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
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 } from 'react';
|
||||
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
||||
import { maasProviderType } from '../config';
|
||||
import { MaasProviderItem as ListItem } from '../config/types';
|
||||
import AccessToken from './access-token';
|
||||
import AdvanceConfig from './advance-config';
|
||||
import Basic from './basic';
|
||||
import SupportedModels from './supported-models';
|
||||
|
||||
interface ProviderFormProps {
|
||||
ref?: any;
|
||||
action: PageActionType;
|
||||
provider?: maasProviderType;
|
||||
currentData?: ListItem; // Used when action is EDIT
|
||||
onFinish: (values: FormData) => void;
|
||||
}
|
||||
|
||||
const TABKeysMap = {
|
||||
BASIC: 'basic',
|
||||
SUPPORTEDMODELS: 'supportedModels',
|
||||
CUSTOMCONFIG: 'customConfig',
|
||||
ADVANCED: 'advanced'
|
||||
};
|
||||
|
||||
const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
|
||||
const { action, provider, currentData, onFinish } = props;
|
||||
const intl = useIntl();
|
||||
const { getScrollElementScrollableHeight } = useWrapperContext();
|
||||
const [activeKey, setActiveKey] = useState<string[]>([TABKeysMap.BASIC]);
|
||||
const [form] = Form.useForm();
|
||||
const scrollTabsRef = useRef<any>(null);
|
||||
|
||||
const segmentOptions = [
|
||||
{
|
||||
value: TABKeysMap.BASIC,
|
||||
label: 'Basic',
|
||||
icon: <IconFont type="icon-basic" />,
|
||||
field: 'name'
|
||||
},
|
||||
{
|
||||
value: TABKeysMap.SUPPORTEDMODELS,
|
||||
label: 'Supported Models',
|
||||
icon: <IconFont type="icon-speed" />,
|
||||
field: 'supportedModels'
|
||||
},
|
||||
{
|
||||
value: TABKeysMap.CUSTOMCONFIG,
|
||||
label: 'Custom Config',
|
||||
icon: <IconFont type="icon-settings" />,
|
||||
field: 'customConfig'
|
||||
}
|
||||
// {
|
||||
// value: TABKeysMap.ADVANCED,
|
||||
// label: intl.formatMessage({ id: 'resources.form.advanced' }),
|
||||
// icon: <IconFont type="icon-settings" />,
|
||||
// field: 'categories'
|
||||
// }
|
||||
];
|
||||
|
||||
const handleActiveChange = (key: string[]) => {
|
||||
setActiveKey(key);
|
||||
};
|
||||
|
||||
const handleOnCollapseChange = (keys: string | string[]) => {
|
||||
setActiveKey(Array.isArray(keys) ? keys : [keys]);
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
submit: () => {
|
||||
@@ -23,9 +81,47 @@ const ProviderForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
|
||||
}));
|
||||
|
||||
return (
|
||||
<Form form={form} layout="vertical">
|
||||
{/* Form fields go here */}
|
||||
</Form>
|
||||
<ScrollSpyTabs
|
||||
ref={scrollTabsRef}
|
||||
defaultTarget="basic"
|
||||
segmentOptions={segmentOptions}
|
||||
activeKey={activeKey}
|
||||
setActiveKey={handleActiveChange}
|
||||
segmentedTop={{
|
||||
top: 0,
|
||||
offsetTop: 96
|
||||
}}
|
||||
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>
|
||||
)
|
||||
}
|
||||
]}
|
||||
></CollapsePanel>
|
||||
</Form>
|
||||
</ScrollSpyTabs>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import ListInput from '@/components/list-input';
|
||||
import SealSelect from '@/components/seal-form/seal-select';
|
||||
import { CheckCircleFilled } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Form } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { FormData } from '../config/types';
|
||||
|
||||
const SelectWrapper = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.icon-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const SupportedModels = () => {
|
||||
const intl = useIntl();
|
||||
const form = Form.useFormInstance<FormData>();
|
||||
|
||||
const renderModelItem = (
|
||||
data: any,
|
||||
{
|
||||
onChange,
|
||||
onBlur
|
||||
}: { onChange: (value: string) => void; onBlur?: (e: any) => void }
|
||||
) => {
|
||||
return (
|
||||
<SelectWrapper>
|
||||
<SealSelect
|
||||
alwaysFocus={true}
|
||||
value={data.value}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
options={[
|
||||
{ label: 'Model A', value: 'model_a' },
|
||||
{ label: 'Model B', value: 'model_b' },
|
||||
{ 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">
|
||||
Test
|
||||
</Button>
|
||||
</SelectWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const handleOnChange = (values: string[]) => {};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="models">
|
||||
<div data-field="supportedModels"></div>
|
||||
<ListInput
|
||||
btnText="Add Model"
|
||||
label="Supported Models"
|
||||
dataList={[]}
|
||||
renderItem={renderModelItem}
|
||||
onChange={handleOnChange}
|
||||
></ListInput>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupportedModels;
|
||||
Reference in New Issue
Block a user