From 5d75cfdfc5ba22b728f05e5826993dfd30a1bd1e Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 13 May 2026 16:24:07 +0800 Subject: [PATCH] fix: name validation --- src/config/index.ts | 2 +- src/locales/en-US/gpuservice.ts | 6 ++- src/locales/ja-JP/gpuservice.ts | 6 ++- src/locales/ru-RU/gpuservice.ts | 6 ++- src/locales/tr-TR/gpuservice.ts | 6 ++- src/locales/zh-CN/gpuservice.ts | 6 ++- .../instances/components/add-modal.tsx | 54 +++++-------------- .../components/instance-type-item.tsx | 2 +- .../gpu-service/instances/forms/basic.tsx | 5 ++ .../instances/forms/instance-type.tsx | 7 +-- .../instances/hooks/use-view-logs.ts | 4 +- .../instances/styles/instances.module.less | 27 ++++++++++ src/pages/gpu-service/storage/forms/basic.tsx | 5 ++ 13 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 src/pages/gpu-service/instances/styles/instances.module.less diff --git a/src/config/index.ts b/src/config/index.ts index b6e7d15b..a2e1d5cc 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -84,4 +84,4 @@ export const modelNameReg = */ export const validateLabelNameRegxFor63 = - /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/; + /^(?![0-9])(?!.*--)[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/; diff --git a/src/locales/en-US/gpuservice.ts b/src/locales/en-US/gpuservice.ts index 6952183c..a15a7ff5 100644 --- a/src/locales/en-US/gpuservice.ts +++ b/src/locales/en-US/gpuservice.ts @@ -76,7 +76,9 @@ export default { 'gpuservice.storage.persistentVolume': 'Persistent Volume', 'gpuservice.storage.persistentVolume.required': 'Please select a persistent volume', - 'gpuservice.storage.tempCapacity': 'Storage Capacity (GB)', + 'gpuservice.storage.tempCapacity': 'Capacity (GB)', 'gpuservice.storage.tempCapacity.required': - 'Please enter the local temporary storage capacity' + 'Please enter the temporary storage capacity', + 'gpuservice.form.rule.name': + "Lowercase letters, numbers, and '-'. Start and end with a letter or number, no consecutive '-', max 63 characters." }; diff --git a/src/locales/ja-JP/gpuservice.ts b/src/locales/ja-JP/gpuservice.ts index e9b2730d..ed59c68e 100644 --- a/src/locales/ja-JP/gpuservice.ts +++ b/src/locales/ja-JP/gpuservice.ts @@ -74,7 +74,9 @@ export default { 'gpuservice.storage.persistentVolume': '永続ボリューム', 'gpuservice.storage.persistentVolume.required': '永続ボリュームを選択してください', - 'gpuservice.storage.tempCapacity': 'ストレージ容量 (GB)', + 'gpuservice.storage.tempCapacity': '容量 (GB)', 'gpuservice.storage.tempCapacity.required': - 'ローカルの一時ストレージ容量を入力してください' + '一時ストレージ容量を入力してください', + 'gpuservice.form.rule.name': + "小文字、数字、'-' のみ使用可能。文字または数字で始まり、文字または数字で終わる必要があり、連続する '-' は不可、最大 63 文字。" }; diff --git a/src/locales/ru-RU/gpuservice.ts b/src/locales/ru-RU/gpuservice.ts index 8df0092e..06fb38c0 100644 --- a/src/locales/ru-RU/gpuservice.ts +++ b/src/locales/ru-RU/gpuservice.ts @@ -75,7 +75,9 @@ export default { 'gpuservice.storage.temporary': 'Временное', 'gpuservice.storage.persistentVolume': 'Постоянный том', 'gpuservice.storage.persistentVolume.required': 'Выберите постоянный том', - 'gpuservice.storage.tempCapacity': 'Объём хранилища (ГБ)', + 'gpuservice.storage.tempCapacity': 'Объём (ГБ)', 'gpuservice.storage.tempCapacity.required': - 'Введите объём локального временного хранилища' + 'Введите объём временного хранилища', + 'gpuservice.form.rule.name': + "Строчные буквы, цифры и '-'. Должно начинаться и заканчиваться буквой или цифрой, без подряд идущих '-', максимум 63 символа." }; diff --git a/src/locales/tr-TR/gpuservice.ts b/src/locales/tr-TR/gpuservice.ts index 8c77ebdd..b049fde1 100644 --- a/src/locales/tr-TR/gpuservice.ts +++ b/src/locales/tr-TR/gpuservice.ts @@ -75,7 +75,9 @@ export default { 'gpuservice.storage.persistentVolume': 'Kalıcı Hacim', 'gpuservice.storage.persistentVolume.required': 'Lütfen bir kalıcı hacim seçin', - 'gpuservice.storage.tempCapacity': 'Depolama Kapasitesi (GB)', + 'gpuservice.storage.tempCapacity': 'Kapasite (GB)', 'gpuservice.storage.tempCapacity.required': - 'Lütfen yerel geçici depolama kapasitesini girin' + 'Lütfen geçici depolama kapasitesini girin', + 'gpuservice.form.rule.name': + "Küçük harfler, rakamlar ve '-'. Harf veya rakamla başlamalı ve bitmeli, ardışık '-' içermemeli, en fazla 63 karakter." }; diff --git a/src/locales/zh-CN/gpuservice.ts b/src/locales/zh-CN/gpuservice.ts index ed2e20e6..1fbd2d6c 100644 --- a/src/locales/zh-CN/gpuservice.ts +++ b/src/locales/zh-CN/gpuservice.ts @@ -71,6 +71,8 @@ export default { 'gpuservice.storage.temporary': '临时', 'gpuservice.storage.persistentVolume': '持久卷', 'gpuservice.storage.persistentVolume.required': '请选择持久卷', - 'gpuservice.storage.tempCapacity': '存储容量 (GB)', - 'gpuservice.storage.tempCapacity.required': '请输入本地临时存储容量' + 'gpuservice.storage.tempCapacity': '容量(GB)', + 'gpuservice.storage.tempCapacity.required': '请输入临时存储容量', + 'gpuservice.form.rule.name': + '由小写字母、数字和 "-" 组成,以字母或数字开头和结尾,不能包含连续的 "-",最多 63 个字符。' }; diff --git a/src/pages/gpu-service/instances/components/add-modal.tsx b/src/pages/gpu-service/instances/components/add-modal.tsx index c055173c..888f6d1a 100644 --- a/src/pages/gpu-service/instances/components/add-modal.tsx +++ b/src/pages/gpu-service/instances/components/add-modal.tsx @@ -6,43 +6,15 @@ import { ColumnWrapper, GSDrawer, ModalFooter } from '@gpustack/core-ui'; import { useIntl } from '@umijs/max'; import { Empty, Input, Typography } from 'antd'; import { useEffect, useRef, useState } from 'react'; -import styled from 'styled-components'; import { ListItem as TemplateItem } from '../../templates/config/types'; import useQueryTemplates from '../../templates/services/use-query-templates'; import { FormData, InstanceTypeItem, ListItem } from '../config/types'; import GPUServiceInstanceForm from '../forms'; import TemplateSelector from '../forms/template-selector'; import useQueryInstanceTypes from '../services/use-query-instance-types'; +import styles from '../styles/instances.module.less'; import InstanceTypeList from './instance-type-list'; -const Container = styled.div` - display: flex; - height: 100%; - min-height: 0; -`; - -const ColWrapper = styled.div` - display: flex; - flex: 1; - max-width: 33%; - min-height: 0; -`; - -const PanelBody = styled.div` - display: flex; - flex-direction: column; - gap: 16px; - height: 100%; - min-height: 0; -`; - -const FormWrapper = styled.div` - display: flex; - flex: 1; - max-width: 34%; - min-height: 0; -`; - type AddModalProps = { title: string; action: PageActionType; @@ -280,10 +252,10 @@ const AddModal: React.FC = ({ }} footer={false} > - - +
+
- +
{intl.formatMessage({ id: 'gpuservice.instance.types' })} @@ -311,13 +283,13 @@ const AddModal: React.FC = ({ loading={instanceTypesLoading} onChange={handleInstanceTypeChange} /> - +
- - +
+
- +
{intl.formatMessage({ id: 'gpuservice.instance.templates' })} @@ -348,11 +320,11 @@ const AddModal: React.FC = ({ ) : ( )} - +
- - +
+
= ({ /> - - +
+
); }; diff --git a/src/pages/gpu-service/instances/components/instance-type-item.tsx b/src/pages/gpu-service/instances/components/instance-type-item.tsx index 9b96eef2..3a3e8133 100644 --- a/src/pages/gpu-service/instances/components/instance-type-item.tsx +++ b/src/pages/gpu-service/instances/components/instance-type-item.tsx @@ -72,7 +72,7 @@ const InstanceTypeItem: React.FC = ({ <Flex gap={8} align="center"> <AutoTooltip ghost minWidth={20} maxWidth={180}> - {displayName} + {item.spec ? displayName : '-'} </AutoTooltip> {acceleratable && manufacturer && ( <span diff --git a/src/pages/gpu-service/instances/forms/basic.tsx b/src/pages/gpu-service/instances/forms/basic.tsx index 0f8d580e..5132d8d8 100644 --- a/src/pages/gpu-service/instances/forms/basic.tsx +++ b/src/pages/gpu-service/instances/forms/basic.tsx @@ -1,3 +1,4 @@ +import { validateLabelNameRegxFor63 } from '@/config'; import { Input as CInput } from '@gpustack/core-ui'; import { useIntl } from '@umijs/max'; import { Form } from 'antd'; @@ -16,6 +17,10 @@ const Basic = () => { message: intl.formatMessage({ id: 'gpuservice.instance.name.required' }) + }, + { + pattern: validateLabelNameRegxFor63, + message: intl.formatMessage({ id: 'gpuservice.form.rule.name' }) } ]} > diff --git a/src/pages/gpu-service/instances/forms/instance-type.tsx b/src/pages/gpu-service/instances/forms/instance-type.tsx index fbc3943a..8403d64b 100644 --- a/src/pages/gpu-service/instances/forms/instance-type.tsx +++ b/src/pages/gpu-service/instances/forms/instance-type.tsx @@ -32,11 +32,12 @@ const InstanceTypePicker: React.FC<InstanceTypePickerProps> = ({ dataList }) => { const selected = useMemo(() => { - return dataList.find((item) => (item.metadata?.name || '') === value); + return ( + dataList.find((item) => (item.metadata?.name || '') === value) || + ({} as InstanceTypeItemModel) + ); }, [value, dataList]); - if (!selected) return null; - return ( <SelectedCard> <InstanceTypeItem item={selected} showStatus={false} /> diff --git a/src/pages/gpu-service/instances/hooks/use-view-logs.ts b/src/pages/gpu-service/instances/hooks/use-view-logs.ts index 0e199d01..6b14e15e 100644 --- a/src/pages/gpu-service/instances/hooks/use-view-logs.ts +++ b/src/pages/gpu-service/instances/hooks/use-view-logs.ts @@ -1,14 +1,14 @@ import { currentClusterAtom } from '@/atoms/gpuservice'; -import { getCurrentOrganizationId } from '@/atoms/user'; +import { getCurrentOrgNamespace } from '@/atoms/user'; import { useAtomValue } from 'jotai'; import { useState } from 'react'; import { GPU_SERVICE_INSTANCES_API } from '../apis'; import { ListItem } from '../config/types'; const useViewLogs = () => { - const namespace = getCurrentOrganizationId(); const currentCluster = useAtomValue(currentClusterAtom); const clusterID = currentCluster?.id; + const namespace = getCurrentOrgNamespace(currentCluster?.owner_principal_id); const [openModalStatus, setOpenModalStatus] = useState<{ open: boolean; diff --git a/src/pages/gpu-service/instances/styles/instances.module.less b/src/pages/gpu-service/instances/styles/instances.module.less new file mode 100644 index 00000000..2cb12403 --- /dev/null +++ b/src/pages/gpu-service/instances/styles/instances.module.less @@ -0,0 +1,27 @@ +.container { + display: flex; + height: 100%; + min-height: 0; +} + +.colWrapper { + display: flex; + flex: 1; + max-width: 33%; + min-height: 0; +} + +.panelBody { + display: flex; + flex-direction: column; + gap: 16px; + height: 100%; + min-height: 0; +} + +.formWrapper { + display: flex; + flex: 1; + max-width: 34%; + min-height: 0; +} diff --git a/src/pages/gpu-service/storage/forms/basic.tsx b/src/pages/gpu-service/storage/forms/basic.tsx index 676d76a4..6e1e22ab 100644 --- a/src/pages/gpu-service/storage/forms/basic.tsx +++ b/src/pages/gpu-service/storage/forms/basic.tsx @@ -1,3 +1,4 @@ +import { validateLabelNameRegxFor63 } from '@/config'; import { Input as CInput, InputNumber, @@ -29,6 +30,10 @@ const Basic = ({ open }: { open: boolean }) => { { required: true, message: getRuleMessage('input', 'common.table.name') + }, + { + pattern: validateLabelNameRegxFor63, + message: intl.formatMessage({ id: 'gpuservice.form.rule.name' }) } ]} >