fix: target model text overflow

This commit is contained in:
jialin
2026-02-10 17:29:57 +08:00
parent c3d5234710
commit 15d635322b
7 changed files with 173 additions and 78 deletions
+16 -14
View File
@@ -35,7 +35,7 @@ const renderTag = (props: any) => {
const OptionNodes = (props: {
data: any;
notFoundContent?: React.ReactNode;
optionNode: React.FC<{ data: any }>;
optionNode?: React.FC<{ data: any }>;
}) => {
const intl = useIntl();
const { data, optionNode: OptionNode, notFoundContent } = props;
@@ -68,11 +68,17 @@ const OptionNodes = (props: {
if (data.parent) {
return (
<AutoTooltip ghost {...width}>
{data.label}
<span>{data.label}</span>
</AutoTooltip>
);
}
return OptionNode ? <OptionNode data={data}></OptionNode> : data.label;
return OptionNode ? (
<OptionNode data={data}></OptionNode>
) : (
<AutoTooltip ghost>
<span>{data.label}</span>
</AutoTooltip>
);
};
const SealCascader: React.FC<
@@ -183,17 +189,13 @@ const SealCascader: React.FC<
{...rest}
placeholder={placeholder}
suffixIcon={<IconFont type="icon-down"></IconFont>}
optionRender={
optionNode
? (data) => (
<OptionNodes
data={data}
notFoundContent={notFoundContent}
optionNode={optionNode}
></OptionNodes>
)
: undefined
}
optionRender={(data) => (
<OptionNodes
data={data}
notFoundContent={notFoundContent}
optionNode={optionNode}
></OptionNodes>
)}
tagRender={tagRender ?? renderTag}
ref={inputRef}
options={children ? null : _options}
@@ -1,54 +1,87 @@
export default `# This is a template for worker_config.
export const dockerConfig = `# This is a template for worker_config.
# debug: false
# ========= directories ===========
# cache_dir: "/var/lib/gpustack/cache"
# log_dir: "/var/lib/gpustack/log"
# bin_dir: "/var/lib/gpustack/bin"
# ========= container & image ===========
# system_default_container_registry: "docker.io"
# image_name_override: "gpustack/gpustack:main"
# image_name_override: "gpustack/gpustack:dev"
# image_repo: "gpustack/gpustack"
# ========= gateway ===========
# gateway_mode: "auto"
# gateway_concurrency: 16
# gateway_kubeconfig: "/var/lib/gpustack/higress/kubeconfig"
# ========= service & networking ===========
# worker_port: 10150
# worker_metrics_port: 10150
# service_port_range: "40000-40063"
# ray_port_range: "41000-41999"
# ========= resources ===========
# system_reserved:
# ram: 2
# vram: 1
# ========= huggingface ===========
# huggingface_token:
# enable_hf_transfer: false
# enable_hf_xet: false
# ========= metrics ===========
# disable_worker_metrics: false
# ========= proxy ===========
# proxy_mode: worker
`;
export const kubernetesConfig = `# This is a template for worker_config.
# debug: false
# ========= directories ===========
# cache_dir: "/var/lib/gpustack/cache"
# log_dir: "/var/lib/gpustack/log"
# ========= container & image ===========
# system_default_container_registry: "docker.io"
# image_name_override: "gpustack/gpustack:dev"
# image_repo: "gpustack/gpustack"
# ========= service & networking ===========
# service_discovery_name: "worker"
# namespace: "gpustack-system"
# worker_port: 10150
# worker_metrics_port: 10150
# service_port_range: "40000-40063"
# ray_port_range: "41000-41999"
# ========= resources ===========
# resources:
# system_reserved:
# ram: 2
# vram: 1
# ========= huggingface ===========
# huggingface_token:
# enable_hf_transfer: false
# enable_hf_xet: false
# ========= metrics ===========
# disable_worker_metrics: false
# ========= tools & runtime ===========
# pipx_path: "/usr/local/bin/pipx"
# tools_download_base_url:
# ========= proxy ===========
# proxy_mode: worker
`;
# proxy_mode: worker`;
@@ -1,14 +1,15 @@
import IconFont from '@/components/icon-font';
import SealInput from '@/components/seal-form/seal-input';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import YamlEditor from '@/pages/_components/yaml-editor';
import { useIntl } from '@umijs/max';
import { Button, Form } from 'antd';
import React, { forwardRef, useImperativeHandle } from 'react';
import { ProviderType } from '../config';
import React, { forwardRef, useEffect, useImperativeHandle } from 'react';
import { ProviderType, ProviderValueMap } from '../config';
import { ClusterFormData as FormData } from '../config/types';
import schema from '../config/worker-config.json';
import yamlTemplate from '../config/yaml-template';
import { dockerConfig, kubernetesConfig } from '../config/yaml-template';
const ClusterAdvanceConfig: React.FC<{
action: PageActionType;
@@ -18,18 +19,32 @@ const ClusterAdvanceConfig: React.FC<{
const [form] = Form.useForm();
const intl = useIntl();
const editorRef = React.useRef<any>(null);
const [fileContent, setFileContent] = React.useState<string>(yamlTemplate);
const [fileContent, setFileContent] = React.useState<string>('');
useImperativeHandle(ref, () => ({
getYamlValue: () => {
return editorRef.current?.getValue();
},
setYamlValue: (values: any) => {
console.log('setYamlValue:', values);
editorRef.current?.setValue(values || yamlTemplate);
editorRef.current?.setValue(
values ||
(provider === ProviderValueMap.Kubernetes
? kubernetesConfig
: dockerConfig)
);
}
}));
useEffect(() => {
if (action === PageAction.CREATE) {
setFileContent(
provider === ProviderValueMap.Kubernetes
? kubernetesConfig
: dockerConfig
);
}
}, [provider, action]);
return (
<>
<Form.Item<FormData>
@@ -21,8 +21,8 @@ const ProviderModels: React.FC<ProviderModelProps> = ({ dataList }) => {
const intl = useIntl();
const head12Items = dataList.slice(0, 8);
const restItems = dataList.slice(8);
const head12Items = dataList.slice(0, 4);
const restItems = dataList.slice(4);
const renderModels = (dataList: ProviderModel[]) => {
return (
+2 -2
View File
@@ -161,14 +161,14 @@ const MaasProvider: React.FC = () => {
<ConfigProvider renderEmpty={renderEmpty}>
<Table
rowKey="id"
tableLayout="auto"
tableLayout="fixed"
sortDirections={TABLE_SORT_DIRECTIONS}
showSorterTooltip={false}
dataSource={dataSource.dataList}
loading={dataSource.loading}
rowSelection={rowSelection}
columns={columns}
scroll={{ x: true }}
scroll={{ x: 900 }}
pagination={{
showSizeChanger: true,
pageSize: queryParams.perPage,
+62 -7
View File
@@ -1,8 +1,10 @@
import AutoTooltip from '@/components/auto-tooltip';
import MetadataList from '@/components/metadata-list';
import SealCascader from '@/components/seal-form/seal-cascader';
import SealInput from '@/components/seal-form/seal-input';
import { PageAction } from '@/config';
import useAppUtils from '@/hooks/use-app-utils';
import ProviderLogo from '@/pages/maas-provider/components/provider-logo';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import _ from 'lodash';
@@ -13,10 +15,23 @@ import {
useRef,
useState
} from 'react';
import styled from 'styled-components';
import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types';
import useTargetSourceModels from '../hooks/use-target-source-models';
const OptionWrapper = styled.span`
display: flex;
align-items: center;
gap: 8px;
`;
const LabelWrapper = styled.div`
display: flex;
align-items: center;
gap: 8px;
`;
const TargetsForm = forwardRef((props, ref) => {
const { onFallbackChange, action } = useFormContext();
const intl = useIntl();
@@ -162,7 +177,6 @@ const TargetsForm = forwardRef((props, ref) => {
return !selectedKeys.has(key) || key === currKey;
});
console.log('children', children);
return {
...model,
@@ -172,13 +186,52 @@ const TargetsForm = forwardRef((props, ref) => {
.filter((model) => model.children && model.children.length > 0);
};
const displayRender = (labels: any[]) => {
const displayRender = (labels: any[], option: any) => {
return (
<span className="flex-center gap-4">
{labels[0]}
<span>/</span>
<span>{labels[1]}</span>
</span>
<LabelWrapper>
<ProviderLogo provider={_.get(option, '0.providerType') as string} />
<AutoTooltip
ghost
maxWidth={300}
title={
<span>
{labels[0]} / {labels[1]}
</span>
}
>
<span>
{labels[0]} / {labels[1]}
</span>
</AutoTooltip>
</LabelWrapper>
);
};
const optionRender = (option: any) => {
const { data } = option;
if (!data.isParent) {
return <AutoTooltip ghost>{data.label}</AutoTooltip>;
}
if (data.providerType === 'deployments') {
return (
<AutoTooltip ghost maxWidth={140}>
<OptionWrapper>
<ProviderLogo provider={data.providerType as string} />
{intl.formatMessage({ id: 'menu.models.deployment' })}
</OptionWrapper>
</AutoTooltip>
);
}
return (
<AutoTooltip ghost maxWidth={140}>
<OptionWrapper>
<ProviderLogo provider={data.providerType as string} />
<span>{data.label}</span>
</OptionWrapper>
</AutoTooltip>
);
};
@@ -269,6 +322,7 @@ const TargetsForm = forwardRef((props, ref) => {
options={filterOptions(item.value)}
showCheckedStrategy="SHOW_CHILD"
displayRender={displayRender}
optionNode={optionRender}
getPopupContainer={(triggerNode) => triggerNode.parentNode}
></SealCascader>
<span className="seprator">:</span>
@@ -320,6 +374,7 @@ const TargetsForm = forwardRef((props, ref) => {
onChange={(value, options) => handleFallbackChange(value, options)}
showCheckedStrategy="SHOW_CHILD"
displayRender={displayRender}
optionNode={optionRender}
getPopupContainer={(triggerNode) => triggerNode.parentNode}
></SealCascader>
</div>
@@ -1,8 +1,6 @@
import GPUStackLogo from '@/assets/images/small-logo-200x200.png';
import { queryModelsList } from '@/pages/llmodels/apis';
import { ListItem as ModelListItem } from '@/pages/llmodels/config/types';
import { queryMaasProviders } from '@/pages/maas-provider/apis';
import ProviderLogo from '@/pages/maas-provider/components/provider-logo';
import { MaasProviderItem } from '@/pages/maas-provider/config/types';
import { useIntl } from '@umijs/max';
import _ from 'lodash';
@@ -44,15 +42,11 @@ const useTargetSourceModels = () => {
const modelsList = [
{
label: (
<OptionWrapper>
<img src={GPUStackLogo} alt="GPUStack" width={16} height={16} />
{intl.formatMessage({ id: 'menu.models.deployment' })}
</OptionWrapper>
),
label: intl.formatMessage({ id: 'menu.models.deployment' }),
value: 'deployments',
providerType: 'deployments',
parent: true,
parent: false,
isParent: true,
children: _.uniqBy(
models.items?.map?.((model: ModelListItem) => ({
label: model.name,
@@ -82,14 +76,10 @@ const useTargetSourceModels = () => {
}));
return {
label: (
<OptionWrapper>
<ProviderLogo provider={provider.config?.type as string} />
<span>{provider.name}</span>
</OptionWrapper>
),
label: provider.name,
value: provider.id,
parent: true,
parent: false,
isParent: true,
providerType: provider.config?.type,
children: _.uniqBy(children, 'value')
};