refactor: advance collapse

This commit is contained in:
jialin
2025-10-13 14:40:26 +08:00
parent a5c1b8e15f
commit 46ecc2467b
18 changed files with 423 additions and 177 deletions
+6 -4
View File
@@ -58,12 +58,14 @@ export default defineConfig({
.filename(`js/[name].${t}.js`)
.chunkFilename(`js/[name].${t}.chunk.js`);
compressionPluginConfig(config);
monacoPluginConfig(config);
}
}
: {}),
chainWebpack(config) {
monacoPluginConfig(config);
},
: {
chainWebpack(config) {
monacoPluginConfig(config);
}
}),
favicons: ['/static/favicon.png'],
jsMinifier: 'terser',
cssMinifier: 'cssnano',
+16 -4
View File
@@ -2,11 +2,23 @@ import useOverlayScroller from '@/hooks/use-overlay-scroller';
import React from 'react';
import './style.less';
const ColumnWrapper: React.FC<any> = ({
interface ColumnWrapperProps {
children: React.ReactNode;
footer?: React.ReactNode;
maxHeight?: string | number;
paddingBottom?: number;
styles?: {
wrapper?: React.CSSProperties;
container?: React.CSSProperties;
};
}
const ColumnWrapper: React.FC<ColumnWrapperProps> = ({
children,
footer,
maxHeight,
paddingBottom = 50
paddingBottom = 50,
styles = {}
}) => {
const scroller = React.useRef<any>(null);
const { initialize } = useOverlayScroller({
@@ -27,12 +39,12 @@ const ColumnWrapper: React.FC<any> = ({
<>
<div
className="column-wrapper-footer"
style={{ height: maxHeight || '100%' }}
style={{ height: maxHeight || '100%', ...styles.wrapper }}
>
<div
className="column-wrapper"
ref={scroller}
style={{ padding: '16px 24px' }}
style={{ padding: '16px 24px', ...styles.container }}
>
<div
style={{
+4 -2
View File
@@ -6,7 +6,7 @@ import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max';
import { Segmented, Tabs } from 'antd';
import _ from 'lodash';
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useId, useRef, useState } from 'react';
import styled from 'styled-components';
import ColumnWrapper from '../../_components/column-wrapper';
import { backendFields, json2Yaml } from '../config';
@@ -46,6 +46,7 @@ interface AddModalProps {
const AddModal: React.FC<AddModalProps> = (props) => {
const { action, currentData, onClose, onSubmit, onSubmitYaml, open, title } =
props;
const uid = useId();
const formRef = useRef<any>(null);
const editorRef = useRef<any>(null);
const intl = useIntl();
@@ -121,7 +122,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
setYamlContent(yaml);
setFormContent(formData);
formRef.current?.setFieldsValue?.(formData);
editorRef.current?.setValue?.(yaml);
editorRef.current?.setContent?.(yaml);
}
}, [action, currentData]);
@@ -129,6 +130,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
<GSDrawer
title={title}
open={open}
key={uid}
onClose={onClose}
destroyOnHidden={true}
closeIcon={false}
@@ -1,16 +1,14 @@
import IconFont from '@/components/icon-font';
import LabelSelector from '@/components/label-selector';
import ListInput from '@/components/list-input';
import CheckboxField from '@/components/seal-form/checkbox-field';
import SealSelect from '@/components/seal-form/seal-select';
import TooltipList from '@/components/tooltip-list';
import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max';
import { Collapse, Form, FormInstance, Typography } from 'antd';
import { Collapse, Form, FormInstance } from 'antd';
import _ from 'lodash';
import React, { useCallback, useMemo } from 'react';
import { useCallback, useMemo } from 'react';
import {
backendParamsHolderTips,
getBackendParamsTips,
modelCategories,
placementStrategyOptions,
@@ -21,9 +19,10 @@ import BackendParameters, {
} from '../config/backend-parameters';
import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types';
import BackendFields from '../forms/backend-fields';
import Backend from '../forms/backend';
import BackendParametersList from '../forms/backend-parameters-list';
import Performance from '../forms/performance';
import dataformStyles from '../style/data-form.less';
import Performance from './performance';
interface AdvanceConfigProps {
isGGUF: boolean;
@@ -44,9 +43,9 @@ const placementStrategyTips = [
}
];
const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
const { form, isGGUF, gpuOptions, source, action } = props;
const AdvanceConfig = () => {
const intl = useIntl();
const form = Form.useFormInstance();
const wokerSelector = Form.useWatch('worker_selector', form);
const EnviromentVars = Form.useWatch('env', form);
const scheduleType = Form.useWatch('scheduleType', form);
@@ -57,7 +56,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
const placement_strategy = Form.useWatch('placement_strategy', form);
const gpuSelectorIds = Form.useWatch(['gpu_selector', 'gpu_ids'], form);
const worker_selector = Form.useWatch('worker_selector', form);
const { onValuesChange } = useFormContext();
const { onValuesChange, gpuOptions, source, isGGUF } = useFormContext();
const paramsConfig = useMemo(() => {
return _.get(BackendParameters, backend, []);
@@ -131,7 +130,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
options={modelCategories}
></SealSelect>
</Form.Item>
<BackendFields></BackendFields>
<Backend></Backend>
{scheduleType === ScheduleValueMap.Auto && (
<>
<Form.Item<FormData> name="placement_strategy">
@@ -194,57 +193,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
</>
)}
<Form.Item<FormData> name="backend_parameters">
<ListInput
placeholder={
backendParamsHolderTips[backend]
? intl.formatMessage({
id: backendParamsHolderTips[backend].holder
})
: ''
}
btnText={intl.formatMessage({ id: 'common.button.addParams' })}
label={intl.formatMessage({
id: 'models.form.backend_parameters'
})}
dataList={form.getFieldValue('backend_parameters') || []}
onChange={handleBackendParametersChange}
onBlur={handleBackendParametersOnBlur}
onDelete={handleDeleteBackendParameters}
options={paramsConfig}
description={
backendParamsTips.link && (
<span>
{backend === backendOptionsMap.ascendMindie && (
<span>
{intl.formatMessage({ id: 'models.backend.mindie.310p' })}
</span>
)}
<span style={{ marginLeft: 5 }}>
{intl.formatMessage(
{ id: 'models.form.backend_parameters.vllm.tips' },
{ backend: backendParamsTips.backend || '' }
)}{' '}
<Typography.Link
style={{ display: 'inline' }}
className="flex-center"
href={backendParamsTips.link}
target="_blank"
>
<span>
{intl.formatMessage({ id: 'common.text.here' })}
</span>
<IconFont
type="icon-external-link"
className="font-size-14 m-l-4"
></IconFont>
</Typography.Link>
</span>
</span>
)
}
></ListInput>
</Form.Item>
<BackendParametersList></BackendParametersList>
<Form.Item<FormData> name="env">
<LabelSelector
label={intl.formatMessage({
@@ -313,19 +262,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
forceRender: true,
children: <Performance></Performance>
},
// {
// key: '3',
// label: (
// <span
// style={{ fontWeight: 'var(--font-weight-medium)' }}
// className="font-size-14"
// >
// Scaling
// </span>
// ),
// forceRender: true,
// children: <Scaling></Scaling>
// },
{
key: '1',
label: (
+32 -12
View File
@@ -2,6 +2,7 @@ import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { PageActionType } from '@/config/types';
import useAppUtils from '@/hooks/use-app-utils';
import CollapsePanel from '@/pages/_components/collapse-panel';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import _ from 'lodash';
@@ -17,10 +18,12 @@ import {
} from '../config/types';
import { generateGPUIds } from '../config/utils';
import CatalogFrom from '../forms/catalog';
import HuggingFaceForm from '../forms/hugging-face';
import LocalPathForm from '../forms/local-path';
import LocalPathSource from '../forms/local-path-source';
import OnlineSource from '../forms/online-source';
import { useGenerateGPUOptions } from '../hooks/use-form-initial-values';
import AdvanceConfig from './advance-config';
// import AdvanceConfig from './advance-config';
import AdvanceConfig from '../forms/advance-config';
import Performance from '../forms/performance';
interface DataFormProps {
initialValues?: any;
@@ -59,6 +62,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
const { getRuleMessage } = useAppUtils();
const [form] = Form.useForm();
const intl = useIntl();
const [activeKey, setActiveKey] = React.useState<string[]>([]);
const handleSumit = () => {
form.submit();
@@ -118,6 +122,10 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
onValuesChange?.(changedValues, allValues);
};
const handleOnCollapseChange = (keys: string | string[]) => {
setActiveKey(Array.isArray(keys) ? keys : [keys]);
};
useImperativeHandle(ref, () => {
return {
form: form,
@@ -216,8 +224,8 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
</Form.Item>
)}
<HuggingFaceForm></HuggingFaceForm>
<LocalPathForm></LocalPathForm>
<OnlineSource></OnlineSource>
<LocalPathSource></LocalPathSource>
<Form.Item<FormData>
name="cluster_id"
rules={[
@@ -245,13 +253,25 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
})}
></SealInput.TextArea>
</Form.Item>
<AdvanceConfig
form={form}
gpuOptions={gpuOptions}
isGGUF={isGGUF}
action={action}
source={props.source}
></AdvanceConfig>
<CollapsePanel
activeKey={activeKey}
accordion={false}
onChange={handleOnCollapseChange}
items={[
{
key: 'performance',
label: 'Performance',
forceRender: true,
children: <Performance></Performance>
},
{
key: 'advance_config',
label: 'Advanced',
forceRender: true,
children: <AdvanceConfig></AdvanceConfig>
}
]}
></CollapsePanel>
</Form>
</FormContext.Provider>
);
@@ -1,32 +0,0 @@
import { Col, Row } from 'antd';
import React from 'react';
import '../style/deploy-dropdown.less';
interface DeployDropdownProps {
items: { label: string; value: string; key: string; icon: React.ReactNode }[];
onSelect: (item: {
label: string;
value: string;
key: string;
icon: React.ReactNode;
}) => void;
}
const DeployDropdown: React.FC<DeployDropdownProps> = ({ items, onSelect }) => {
return (
<div className="deploy-dropdown">
<Row gutter={[0, 16]}>
{items.map((item) => (
<Col span={8} key={item.key}>
<div key={item.key} onClick={() => onSelect(item)} className="item">
<span className="icon">{item.icon}</span>
<span className="label">{item.label}</span>
</div>
</Col>
))}
</Row>
</div>
);
};
export default DeployDropdown;
+21 -20
View File
@@ -36,10 +36,15 @@ const ModalFooterStyle = {
justifyContent: 'flex-end'
};
const Container = styled.div`
display: flex;
height: 100%;
`;
const ColWrapper = styled.div`
display: flex;
flex: 1;
maxwidth: 33.33%;
max-width: 33.33%;
`;
const FormWrapper = styled.div`
@@ -445,31 +450,27 @@ const AddModal: FC<AddModalProps> = (props) => {
width={width}
footer={false}
>
<div style={{ display: 'flex', height: '100%' }}>
<Container>
{SEARCH_SOURCE.includes(props.source) &&
deploymentType === 'modelList' && (
<>
<ColWrapper>
<ColumnWrapper>
<SearchModel
hasLinuxWorker={hasLinuxWorker}
modelSource={props.source}
onSelectModel={handleOnSelectModel}
onSelectModelAfterEvaluate={
handleOnSelectModelAfterEvaluate
}
clusterId={
form.current?.getFieldValue?.('cluster_id') ||
initClusterId()
}
displayEvaluateStatus={displayEvaluateStatus}
gpuOptions={[]}
></SearchModel>
</ColumnWrapper>
<SearchModel
hasLinuxWorker={hasLinuxWorker}
modelSource={props.source}
onSelectModel={handleOnSelectModel}
onSelectModelAfterEvaluate={handleOnSelectModelAfterEvaluate}
clusterId={
form.current?.getFieldValue?.('cluster_id') ||
initClusterId()
}
displayEvaluateStatus={displayEvaluateStatus}
gpuOptions={[]}
></SearchModel>
<Separator></Separator>
</ColWrapper>
<ColWrapper>
<ColumnWrapper>
<ColumnWrapper styles={{ container: { paddingTop: 0 } }}>
<ModelCard
selectedModel={selectedModel}
onCollapse={setCollapsed}
@@ -545,7 +546,7 @@ const AddModal: FC<AddModalProps> = (props) => {
</>
</ColumnWrapper>
</FormWrapper>
</div>
</Container>
</GSDrawer>
);
};
+15 -13
View File
@@ -1,6 +1,7 @@
import { getRequestId, setRquestId } from '@/atoms/models';
import BaseSelect from '@/components/seal-form/base/select';
import { createAxiosToken } from '@/hooks/use-chunk-request';
import ColumnWrapper from '@/pages/_components/column-wrapper';
import { useIntl } from '@umijs/max';
import { Pagination } from 'antd';
import _ from 'lodash';
@@ -521,11 +522,11 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
onChange={handleSearchInputChange}
modelSource={modelSource}
></SearchInput>
<div className="gguf-tips">
{/* <div className="gguf-tips">
<span>
{intl.formatMessage({ id: 'models.form.search.gguftips' })}
</span>
</div>
</div> */}
<div className={SearchStyle.filter}>
<span className="flex-center gap-8">
<BaseSelect
@@ -582,18 +583,19 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
}, []);
return (
<div style={{ flex: 1 }}>
<div style={{ width: '100%' }}>
<div className={SearchStyle['search-bar']}>{renderHFSearch()}</div>
<SearchResult
loading={dataSource.loading}
resultList={dataSource.dataList}
networkError={dataSource.networkError}
current={current}
source={modelSource}
isEvaluating={isEvaluating}
onSelect={handleSelectModelManually}
></SearchResult>
<ColumnWrapper maxHeight={'calc(100vh - 210px)'}>
<SearchResult
loading={dataSource.loading}
resultList={dataSource.dataList}
networkError={dataSource.networkError}
current={current}
source={modelSource}
isEvaluating={isEvaluating}
onSelect={handleSelectModelManually}
></SearchResult>
</ColumnWrapper>
</div>
);
};
@@ -1,5 +1,4 @@
import IconFont from '@/components/icon-font';
import SimpleOverlay from '@/components/simple-overlay';
import { SearchOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Empty, Spin } from 'antd';
@@ -121,7 +120,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
}, [networkError, source, intl]);
return (
<SimpleOverlay style={{ height: 'calc(100vh - 224px)' }}>
<>
<div style={{ ...props.style }} className="search-result-wrap">
<Spin spinning={props.loading}>
<div style={{ minHeight: 200 }}>
@@ -167,7 +166,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
</div>
</Spin>
</div>
</SimpleOverlay>
</>
);
};
+1 -1
View File
@@ -7,7 +7,7 @@ interface FormContextProps {
formKey: DeployFormKey;
source: string;
pageAction: PageActionType;
gpuOptions?: any[];
gpuOptions: any[];
backendOptions: BackendOption[];
onValuesChange?: (changedValues: any, allValues: any) => void;
onBackendChange: (backend: string, option: any) => void;
+211
View File
@@ -0,0 +1,211 @@
import LabelSelector from '@/components/label-selector';
import CheckboxField from '@/components/seal-form/checkbox-field';
import SealSelect from '@/components/seal-form/seal-select';
import TooltipList from '@/components/tooltip-list';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import _ from 'lodash';
import { useCallback } from 'react';
import {
modelCategories,
placementStrategyOptions,
ScheduleValueMap
} from '../config';
import { backendOptionsMap } from '../config/backend-parameters';
import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types';
import Backend from '../forms/backend';
import BackendParametersList from '../forms/backend-parameters-list';
const placementStrategyTips = [
{
title: 'Spread',
tips: 'resources.form.spread.tips'
},
{
title: 'Binpack',
tips: 'resources.form.binpack.tips'
}
];
const AdvanceConfig = () => {
const intl = useIntl();
const form = Form.useFormInstance();
const wokerSelector = Form.useWatch('worker_selector', form);
const EnviromentVars = Form.useWatch('env', form);
const scheduleType = Form.useWatch('scheduleType', form);
const backend = Form.useWatch('backend', form);
const { onValuesChange } = useFormContext();
const handleWorkerLabelsChange = useCallback(
(labels: Record<string, any>) => {
form.setFieldValue('worker_selector', labels);
},
[]
);
const handleEnviromentVarsChange = useCallback(
(labels: Record<string, any>) => {
form.setFieldValue('env', labels);
},
[]
);
const onSelectorChange = (field: string, allowEmpty?: boolean) => {
const workerSelector = form.getFieldValue(field);
// check if all keys have values
const hasEmptyValue = _.some(_.keys(workerSelector), (k: string) => {
return !workerSelector[k];
});
if (!hasEmptyValue || allowEmpty) {
onValuesChange?.({}, form.getFieldsValue());
}
};
const handleSelectorOnBlur = () => {
onSelectorChange('worker_selector');
};
const handleDeleteWorkerSelector = (index: number) => {
onValuesChange?.({}, form.getFieldsValue());
};
const handleEnvSelectorOnBlur = () => {
onSelectorChange('env', true);
};
const handleDeleteEnvSelector = (index: number) => {
onValuesChange?.({}, form.getFieldsValue());
};
return (
<>
<Form.Item<FormData> name="categories">
<SealSelect
allowNull
label={intl.formatMessage({
id: 'models.form.categories'
})}
options={modelCategories}
></SealSelect>
</Form.Item>
<Backend></Backend>
{scheduleType === ScheduleValueMap.Auto && (
<>
<Form.Item<FormData> name="placement_strategy">
<SealSelect
label={intl.formatMessage({
id: 'resources.form.placementStrategy'
})}
options={placementStrategyOptions}
description={
<TooltipList list={placementStrategyTips}></TooltipList>
}
></SealSelect>
</Form.Item>
<Form.Item<FormData>
name="worker_selector"
rules={[
({ getFieldValue }) => ({
validator(rule, value) {
if (
getFieldValue('scheduleType') === ScheduleValueMap.Auto &&
_.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();
}
})
]}
>
<LabelSelector
label={intl.formatMessage({
id: 'resources.form.workerSelector'
})}
labels={wokerSelector}
onChange={handleWorkerLabelsChange}
onBlur={handleSelectorOnBlur}
onDelete={handleDeleteWorkerSelector}
description={
<span>
{intl.formatMessage({
id: 'resources.form.workerSelector.description'
})}
</span>
}
></LabelSelector>
</Form.Item>
</>
)}
<BackendParametersList></BackendParametersList>
<Form.Item<FormData> name="env">
<LabelSelector
label={intl.formatMessage({
id: 'models.form.env'
})}
labels={EnviromentVars}
btnText={intl.formatMessage({ id: 'common.button.vars' })}
onBlur={handleEnvSelectorOnBlur}
onDelete={handleDeleteEnvSelector}
onChange={handleEnviromentVarsChange}
></LabelSelector>
</Form.Item>
{scheduleType === ScheduleValueMap.Auto &&
[backendOptionsMap.vllm, backendOptionsMap.ascendMindie].includes(
backend
) && (
<div style={{ paddingBottom: 22, paddingLeft: 10 }}>
<Form.Item<FormData>
name="distributed_inference_across_workers"
valuePropName="checked"
style={{ padding: '0 10px', marginBottom: 0 }}
noStyle
>
<CheckboxField
description={intl.formatMessage({
id: 'models.form.distribution.tips'
})}
label={intl.formatMessage({
id: 'resources.form.enableDistributedInferenceAcrossWorkers'
})}
></CheckboxField>
</Form.Item>
</div>
)}
<div style={{ paddingBottom: 22, paddingLeft: 10 }}>
<Form.Item<FormData>
name="restart_on_error"
valuePropName="checked"
style={{ padding: '0 10px', marginBottom: 0 }}
noStyle
>
<CheckboxField
description={intl.formatMessage({
id: 'models.form.restart.onerror.tips'
})}
label={intl.formatMessage({
id: 'models.form.restart.onerror'
})}
></CheckboxField>
</Form.Item>
</div>
</>
);
};
export default AdvanceConfig;
@@ -0,0 +1,93 @@
import IconFont from '@/components/icon-font';
import ListInput from '@/components/list-input';
import { useIntl } from '@umijs/max';
import { Form, Typography } from 'antd';
import _ from 'lodash';
import { useMemo } from 'react';
import { backendParamsHolderTips, getBackendParamsTips } from '../config';
import BackendParameters, {
backendOptionsMap
} from '../config/backend-parameters';
import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types';
const BackendParametersList: React.FC = () => {
const intl = useIntl();
const { onValuesChange } = useFormContext();
const form = Form.useFormInstance();
const backend = Form.useWatch('backend', form);
const backendParamsTips = useMemo(() => {
return getBackendParamsTips(backend);
}, [backend]);
const paramsConfig = useMemo(() => {
return _.get(BackendParameters, backend, []);
}, [backend]);
const handleBackendParametersChange = (list: string[]) => {
form.setFieldValue('backend_parameters', list);
};
const handleBackendParametersOnBlur = () => {
onValuesChange?.({}, form.getFieldsValue());
};
const handleDeleteBackendParameters = (index: number) => {
onValuesChange?.({}, form.getFieldsValue());
};
return (
<Form.Item<FormData> name="backend_parameters">
<ListInput
placeholder={
backendParamsHolderTips[backend]
? intl.formatMessage({
id: backendParamsHolderTips[backend].holder
})
: ''
}
btnText={intl.formatMessage({ id: 'common.button.addParams' })}
label={intl.formatMessage({
id: 'models.form.backend_parameters'
})}
dataList={form.getFieldValue('backend_parameters') || []}
onChange={handleBackendParametersChange}
onBlur={handleBackendParametersOnBlur}
onDelete={handleDeleteBackendParameters}
options={paramsConfig}
description={
backendParamsTips.link && (
<span>
{backend === backendOptionsMap.ascendMindie && (
<span>
{intl.formatMessage({ id: 'models.backend.mindie.310p' })}
</span>
)}
<span style={{ marginLeft: 5 }}>
{intl.formatMessage(
{ id: 'models.form.backend_parameters.vllm.tips' },
{ backend: backendParamsTips.backend || '' }
)}{' '}
<Typography.Link
style={{ display: 'inline' }}
className="flex-center"
href={backendParamsTips.link}
target="_blank"
>
<span>{intl.formatMessage({ id: 'common.text.here' })}</span>
<IconFont
type="icon-external-link"
className="font-size-14 m-l-4"
></IconFont>
</Typography.Link>
</span>
</span>
)
}
></ListInput>
</Form.Item>
);
};
export default BackendParametersList;
@@ -14,9 +14,14 @@ import useCheckBackend from '../hooks/use-check-backend';
const LocalPathForm: React.FC = () => {
const { checkOnlyAscendNPU } = useCheckBackend();
const form = Form.useFormInstance();
const formCtx = useFormContext();
const source = Form.useWatch('source', form);
const { formKey, gpuOptions, onValuesChange, onBackendChange } = formCtx;
const {
formKey,
gpuOptions,
backendOptions,
onValuesChange,
onBackendChange
} = useFormContext();
const { getRuleMessage } = useAppUtils();
const intl = useIntl();
const localPathCache = useRef<string>(form.getFieldValue('local_path') || '');
@@ -58,7 +63,8 @@ const LocalPathForm: React.FC = () => {
});
if (oldBackend !== backend) {
onBackendChange?.(backend);
const option = backendOptions.find((item) => item.value === backend);
onBackendChange?.(backend, option);
} else {
onValuesChange?.({ local_path: value }, form.getFieldsValue());
}
@@ -5,10 +5,10 @@ import useAppUtils from '@/hooks/use-app-utils';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import React from 'react';
import GPUCard from '../components/gpu-card';
import { scheduleList, ScheduleValueMap } from '../config';
import { backendOptionsMap } from '../config/backend-parameters';
import { useCatalogFormContext, useFormContext } from '../config/form-context';
import GPUCard from './gpu-card';
const scheduleTypeTips = [
{
-5
View File
@@ -26,8 +26,3 @@
justify-content: flex-end;
}
}
.card-wrapper {
padding: 16px 24px;
padding-top: 0;
}
+2 -3
View File
@@ -1,7 +1,6 @@
@padding: 24px;
.search-result-wrap {
padding: 16px @padding;
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
.ant-spin-container.ant-spin-blur {
@@ -21,8 +20,6 @@
}
.search-bar {
left: 0;
right: 0;
padding-inline: @padding;
background: var(--ant-color-bg-elevated);
padding-bottom: 10px;
@@ -32,6 +29,8 @@
justify-content: space-between;
align-items: center;
margin-top: 10px;
row-gap: 10px;
flex-wrap: wrap;
color: var(--ant-color-text-tertiary);
:global {