fix: instance form ux
This commit is contained in:
@@ -42,6 +42,8 @@ export default {
|
||||
'Please make sure the <a href={link} target="_blank">prerequisites</a> for {label} are met before executing the following command.',
|
||||
'clusters.create.addCommand.tips':
|
||||
'On the Worker that needs to be added, run the following command to join it to the cluster.',
|
||||
'clusters.create.addCommand.k8s.tips':
|
||||
'On the Kubernetes cluster that needs to be registered, run the following command to create the Kubernetes resources and register the cluster.',
|
||||
'clusters.create.register.tips':
|
||||
'On the Kubernetes cluster that needs to be added, run the following command to join its nodes to the cluster.',
|
||||
'cluster.create.checkEnv.tips':
|
||||
|
||||
@@ -42,6 +42,8 @@ export default {
|
||||
'Please make sure the <a href={link} target="_blank">prerequisites</a> for {label} are met before executing the following command.',
|
||||
'clusters.create.addCommand.tips':
|
||||
'On the Worker that needs to be added, run the following command to join it to the cluster.',
|
||||
'clusters.create.addCommand.k8s.tips':
|
||||
'登録する Kubernetes クラスターで以下のコマンドを実行し、Kubernetes リソースを作成してクラスターを登録します。',
|
||||
'cluster.create.checkEnv.tips':
|
||||
'Use the following command to check if the environment is ready.',
|
||||
'clusters.create.register.tips':
|
||||
|
||||
@@ -42,6 +42,8 @@ export default {
|
||||
'Пожалуйста, убедитесь, что выполнены <a href={link} target="_blank">предварительные условия</a> для {label} перед выполнением следующей команды.',
|
||||
'clusters.create.addCommand.tips':
|
||||
'На воркере, который необходимо добавить, выполните следующую команду, чтобы присоединить его к кластеру.',
|
||||
'clusters.create.addCommand.k8s.tips':
|
||||
'На Kubernetes-кластере, который необходимо зарегистрировать, выполните следующую команду, чтобы создать ресурсы Kubernetes и зарегистрировать этот кластер.',
|
||||
'cluster.create.checkEnv.tips':
|
||||
'Используйте следующую команду для проверки готовности окружения',
|
||||
'clusters.create.register.tips':
|
||||
|
||||
@@ -42,6 +42,8 @@ export default {
|
||||
'Aşağıdaki komutu çalıştırmadan önce lütfen {label} için <a href={link} target="_blank">ön koşulların</a> karşılandığından emin olun.',
|
||||
'clusters.create.addCommand.tips':
|
||||
'Eklenmesi gereken İşçi Düğümde, kümeye katılması için aşağıdaki komutu çalıştırın.',
|
||||
'clusters.create.addCommand.k8s.tips':
|
||||
'Kaydedilmesi gereken Kubernetes kümesinde, Kubernetes kaynaklarını oluşturmak ve kümeyi kaydetmek için aşağıdaki komutu çalıştırın.',
|
||||
'clusters.create.register.tips':
|
||||
'Eklenmesi gereken Kubernetes kümesinde, düğümlerini kümeye katılması için aşağıdaki komutu çalıştırın.',
|
||||
'cluster.create.checkEnv.tips':
|
||||
|
||||
@@ -41,6 +41,8 @@ export default {
|
||||
'在执行以下命令之前,请确保已满足 {label} 的<a href={link} target="_blank">先决条件</a>。',
|
||||
'clusters.create.addCommand.tips':
|
||||
'在需要添加的节点上运行以下命令,将其加入到集群中。',
|
||||
'clusters.create.addCommand.k8s.tips':
|
||||
'在需要注册的 Kubernetes 集群中运行以下命令,创建 Kubernetes 资源,注册该集群。',
|
||||
'clusters.create.register.tips':
|
||||
'在需要添加的 Kubernetes 集群上运行以下命令,将其中的节点加入到集群中。',
|
||||
'cluster.create.checkEnv.tips': '使用以下命令检查环境是否准备妥当。',
|
||||
|
||||
@@ -113,7 +113,7 @@ const NumberSelection: React.FC<NumberSelectionProps> = ({
|
||||
aria-disabled={disabled}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
className={classNames(styles.numberItem, {
|
||||
[styles.active]: num === value
|
||||
[styles.active]: num === value && !!value
|
||||
})}
|
||||
onClick={() => handleSelect(num)}
|
||||
onKeyDown={(e) => {
|
||||
|
||||
@@ -30,7 +30,7 @@ const K8sRunCommand: React.FC<AddWorkerStepProps> = ({ disabled }) => {
|
||||
}}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'clusters.create.addCommand.tips'
|
||||
id: 'clusters.create.addCommand.k8s.tips'
|
||||
})}
|
||||
</Typography.Paragraph>
|
||||
<RegisterClusterInner
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AutoTooltip, IconFont, StatusTag, ThemeTag } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Flex } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { manufactureColorMap } from '../../templates/config';
|
||||
import {
|
||||
convertKiToGi,
|
||||
InstanceTypePhaseLabelMap,
|
||||
@@ -67,7 +68,10 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({
|
||||
const name = item.metadata?.name;
|
||||
const acceleratable = item.spec?.acceleratable;
|
||||
|
||||
const manufacturer = item.spec?.manufacturer?.toUpperCase();
|
||||
const manufacturerKey = item.spec?.manufacturer;
|
||||
const manufacturer = manufacturerKey?.toUpperCase();
|
||||
const manufacturerColor =
|
||||
(manufacturerKey && manufactureColorMap[manufacturerKey]) ?? 'purple';
|
||||
|
||||
const renderName = () => {
|
||||
const product = item.spec?.product;
|
||||
@@ -91,7 +95,7 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({
|
||||
fontWeight: 400
|
||||
}}
|
||||
>
|
||||
<ThemeTag color="purple">{manufacturer}</ThemeTag>
|
||||
<ThemeTag color={manufacturerColor}>{manufacturer}</ThemeTag>
|
||||
</span>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface FormData {
|
||||
name: string;
|
||||
namespace: string;
|
||||
};
|
||||
enable_ssh?: boolean;
|
||||
spec: {
|
||||
type: string;
|
||||
image: string;
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
CheckboxField,
|
||||
CollapsePanel,
|
||||
IconFont,
|
||||
MultipleSelect,
|
||||
ScrollSpyTabs,
|
||||
Select,
|
||||
useFinishFailed,
|
||||
useScrollActiveChange,
|
||||
useWrapperContext
|
||||
@@ -25,6 +25,7 @@ import TemplateBasicForm, {
|
||||
BasicResourceMax
|
||||
} from '../../templates/forms/basic';
|
||||
import { FormData, InstanceTypeItem, ListItem } from '../config/types';
|
||||
import instanceStyles from '../styles/instances.module.less';
|
||||
import Basic from './basic';
|
||||
import InstanceTypeFormItem from './instance-type';
|
||||
import StorageVolume from './storage-volume';
|
||||
@@ -123,6 +124,22 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
||||
}
|
||||
}, [open, action]);
|
||||
|
||||
const handleSSHEnableChange = (e: any) => {
|
||||
if (!e?.target?.checked) {
|
||||
return;
|
||||
}
|
||||
const currentPorts = form.getFieldValue(['spec', 'ports']) || [];
|
||||
const hasSSHPort = currentPorts.some(
|
||||
(item: any) => item?.protocol === 'TCP' && item?.port === SSH_PORT
|
||||
);
|
||||
if (!hasSSHPort) {
|
||||
form.setFieldValue(
|
||||
['spec', 'ports'],
|
||||
[...currentPorts, { protocol: 'TCP', port: SSH_PORT, name: 'SSH' }]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const segmentOptions = useMemo(
|
||||
() => [
|
||||
{
|
||||
@@ -363,31 +380,39 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
||||
<CheckboxField
|
||||
disabled={disabled}
|
||||
label={'启用 SSH 访问'}
|
||||
onChange={handleSSHEnableChange}
|
||||
></CheckboxField>
|
||||
</Form.Item>
|
||||
{sshEnabled && (
|
||||
<Form.Item<FormData> name={['spec', 'sshPublicKey', 'name']}>
|
||||
<Select
|
||||
disabled={disabled}
|
||||
mode="multiple"
|
||||
maxTagCount={1}
|
||||
label={'SSH 公钥'}
|
||||
options={[
|
||||
{
|
||||
label: 'SSH-key-1',
|
||||
value: 'gpustack-ssh-public-key'
|
||||
},
|
||||
{
|
||||
label: 'SSH-key-2',
|
||||
value: 'gpustack-ssh-public-key-2'
|
||||
},
|
||||
{
|
||||
label: 'SSH-key-3',
|
||||
value: 'gpustack-ssh-public-key-3'
|
||||
}
|
||||
]}
|
||||
></Select>
|
||||
</Form.Item>
|
||||
<div className={instanceStyles.sshkeySelection}>
|
||||
<Form.Item<FormData> name={['spec', 'sshPublicKey', 'name']}>
|
||||
<MultipleSelect
|
||||
disabled={disabled}
|
||||
mode="multiple"
|
||||
maxTagCount={1}
|
||||
label={'SSH 公钥'}
|
||||
styles={{
|
||||
wrapper: {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
options={[
|
||||
{
|
||||
label: 'SSH-key-1',
|
||||
value: 'gpustack-ssh-public-key'
|
||||
},
|
||||
{
|
||||
label: 'SSH-key-2',
|
||||
value: 'gpustack-ssh-public-key-2'
|
||||
},
|
||||
{
|
||||
label: 'SSH-key-3',
|
||||
value: 'gpustack-ssh-public-key-3'
|
||||
}
|
||||
]}
|
||||
></MultipleSelect>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
</Form>
|
||||
</ScrollSpyTabs>
|
||||
|
||||
@@ -87,7 +87,8 @@ const StorageVolume = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldBlock>
|
||||
<>
|
||||
<div data-field="storage"></div>
|
||||
<Flex
|
||||
style={{
|
||||
justifyContent: 'space-between',
|
||||
@@ -149,7 +150,6 @@ const StorageVolume = ({
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
<div data-field="storage"></div>
|
||||
|
||||
{storageMode === StorageModeValueMap.Existing && (
|
||||
<Form.Item
|
||||
@@ -230,7 +230,7 @@ const StorageVolume = ({
|
||||
onCancel={() => setOverlayOpen(false)}
|
||||
onSubmit={handleCreateStorage}
|
||||
/>
|
||||
</FieldBlock>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -32,3 +32,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sshkeySelection {
|
||||
:global {
|
||||
.ant-select-content .ant-tag {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Tag } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { templateActions } from '../config';
|
||||
import { manufactureColorMap, templateActions } from '../config';
|
||||
import { ListItem } from '../config/types';
|
||||
|
||||
const imageLogoMap = {
|
||||
@@ -40,19 +40,6 @@ const imageLogoMap = {
|
||||
ubuntu: ubuntuLogo
|
||||
} as const;
|
||||
|
||||
export const manufactureColorMap: Record<string, string> = {
|
||||
nvidia: 'green',
|
||||
amd: 'volcano',
|
||||
ascend: 'orange',
|
||||
hygon: 'magenta',
|
||||
moorthreads: 'cyan',
|
||||
iluvatar: 'purple',
|
||||
metax: 'geekblue',
|
||||
cambricon: 'gold',
|
||||
thead: 'red',
|
||||
cpu: 'blue'
|
||||
};
|
||||
|
||||
const manufacturerLabelMap: Record<string, string> = Object.values(
|
||||
GPUsConfigs
|
||||
).reduce(
|
||||
|
||||
@@ -35,6 +35,19 @@ export const ImagePullPolicyOptions: {
|
||||
|
||||
export const DefaultImagePullPolicy: ImagePullPolicy = 'IfNotPresent';
|
||||
|
||||
export const manufactureColorMap: Record<string, string> = {
|
||||
nvidia: 'green',
|
||||
amd: 'volcano',
|
||||
ascend: 'orange',
|
||||
hygon: 'magenta',
|
||||
moorthreads: 'cyan',
|
||||
iluvatar: 'purple',
|
||||
metax: 'geekblue',
|
||||
cambricon: 'gold',
|
||||
thead: 'red',
|
||||
cpu: 'blue'
|
||||
};
|
||||
|
||||
export const normalizeCommand = (value: string): string[] => {
|
||||
if (!value) return [];
|
||||
const tokens: string[] = [];
|
||||
|
||||
Reference in New Issue
Block a user