style: number selection
This commit is contained in:
@@ -370,9 +370,11 @@ const AddModal: React.FC<AddModalProps> = ({
|
||||
}
|
||||
>
|
||||
<>
|
||||
<ColTitle>
|
||||
{intl.formatMessage({ id: 'common.title.config' })}
|
||||
</ColTitle>
|
||||
{action !== PageAction.VIEW && (
|
||||
<ColTitle>
|
||||
{intl.formatMessage({ id: 'common.title.config' })}
|
||||
</ColTitle>
|
||||
)}
|
||||
<GPUServiceInstanceForm
|
||||
ref={form}
|
||||
action={action}
|
||||
|
||||
@@ -66,16 +66,23 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({
|
||||
const intl = useIntl();
|
||||
const name = item.metadata?.name;
|
||||
const acceleratable = item.spec?.acceleratable;
|
||||
const product = item.spec?.product;
|
||||
const displayName = product || (!acceleratable ? 'CPU' : name);
|
||||
|
||||
const manufacturer = item.spec?.manufacturer?.toUpperCase();
|
||||
|
||||
const renderName = () => {
|
||||
const product = item.spec?.product;
|
||||
const displayName =
|
||||
product ||
|
||||
(!acceleratable ? `${item.status?.cpu?.capacity} vCPUs` : name);
|
||||
return displayName;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title>
|
||||
<Flex gap={8} align="center">
|
||||
<AutoTooltip ghost minWidth={20} maxWidth={180}>
|
||||
{item.spec ? displayName : '-'}
|
||||
{item.spec ? renderName() : '-'}
|
||||
</AutoTooltip>
|
||||
{acceleratable && manufacturer && (
|
||||
<span
|
||||
@@ -165,14 +172,18 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({
|
||||
<span>{toDisplayUnit(item.status?.ram?.capacity) ?? '-'}</span>
|
||||
</Flex>
|
||||
</span>
|
||||
<span className="dot"></span>
|
||||
<span className="meta-item">
|
||||
<IconFont type="icon-cpu" className="meta-icon" />
|
||||
<Flex align="center" gap={4}>
|
||||
<span>vCPU</span>
|
||||
<span>{item.status?.cpu?.capacity ?? '-'}</span>
|
||||
</Flex>
|
||||
</span>
|
||||
{acceleratable && (
|
||||
<>
|
||||
<span className="dot"></span>
|
||||
<span className="meta-item">
|
||||
<IconFont type="icon-cpu" className="meta-icon" />
|
||||
<Flex align="center" gap={4}>
|
||||
<span>vCPU</span>
|
||||
<span>{item.status?.cpu?.capacity ?? '-'}</span>
|
||||
</Flex>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</Meta>
|
||||
</>
|
||||
|
||||
@@ -160,11 +160,6 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
||||
);
|
||||
|
||||
const ports = Form.useWatch(['spec', 'ports'], form) || [];
|
||||
const hasSshPort = useMemo(
|
||||
() =>
|
||||
ports.some((p) => Number(p?.port) === SSH_PORT && p.protocol === 'TCP'),
|
||||
[ports]
|
||||
);
|
||||
|
||||
const selectedTypeName = Form.useWatch(['spec', 'type'], form) as
|
||||
| string
|
||||
@@ -242,6 +237,17 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
||||
});
|
||||
};
|
||||
|
||||
const segmentedTop =
|
||||
action === PageAction.VIEW
|
||||
? {
|
||||
top: 0,
|
||||
offsetTop: 100
|
||||
}
|
||||
: {
|
||||
top: 40,
|
||||
offsetTop: 130
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
submit: () => {
|
||||
form.submit();
|
||||
@@ -262,10 +268,7 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
||||
segmentOptions={segmentOptions}
|
||||
activeKey={activeKey}
|
||||
setActiveKey={handleActiveChange}
|
||||
segmentedTop={{
|
||||
top: 40,
|
||||
offsetTop: 130
|
||||
}}
|
||||
segmentedTop={segmentedTop}
|
||||
getScrollElementScrollableHeight={getScrollElementScrollableHeight}
|
||||
>
|
||||
<Form
|
||||
|
||||
@@ -2,7 +2,7 @@ import { PageAction } from '@/config';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import NumberSelection from '@/pages/_components/number-selection';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import { Alert, Form } from 'antd';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import InstanceTypeItem from '../components/instance-type-item';
|
||||
@@ -118,17 +118,12 @@ const InstanceTypeFormItem: React.FC<InstanceTypeFormItemProps> = ({
|
||||
<InstanceTypePicker dataList={dataList} value={typeName} />
|
||||
</Form.Item>
|
||||
</FieldBlock>
|
||||
{selectedInstanceType?.spec?.acceleratable && (
|
||||
{!selectedInstanceType?.spec?.acceleratable && (
|
||||
<Form.Item
|
||||
name={['spec', 'resources', 'accelerator']}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'gpuservice.instance.gpuCount.required'
|
||||
})
|
||||
},
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (value > maxGpuCount) {
|
||||
return Promise.reject(
|
||||
@@ -143,9 +138,14 @@ const InstanceTypeFormItem: React.FC<InstanceTypeFormItemProps> = ({
|
||||
if (value < 1) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
intl.formatMessage({
|
||||
id: 'gpuservice.instance.gpuCount.min'
|
||||
})
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: 'gpuservice.instance.gpuCount.min'
|
||||
},
|
||||
{
|
||||
count: 1
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -160,6 +160,23 @@ const InstanceTypeFormItem: React.FC<InstanceTypeFormItemProps> = ({
|
||||
step={1}
|
||||
required
|
||||
disabled={disabled || action === PageAction.EDIT}
|
||||
labelExtra={
|
||||
!maxGpuCount && (
|
||||
<Alert
|
||||
showIcon
|
||||
type="warning"
|
||||
title={intl.formatMessage({
|
||||
id: 'gpuservice.instance.gpuCount.noAvailable'
|
||||
})}
|
||||
styles={{
|
||||
root: {
|
||||
marginLeft: 4,
|
||||
paddingBlock: 0
|
||||
}
|
||||
}}
|
||||
></Alert>
|
||||
)
|
||||
}
|
||||
label={intl.formatMessage({ id: 'gpuservice.instance.gpuCount' })}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
@@ -2,9 +2,11 @@ import { currentClusterAtom } from '@/atoms/gpuservice';
|
||||
import { getCurrentOrgNamespace } from '@/atoms/user';
|
||||
import { PageAction } from '@/config';
|
||||
import {
|
||||
Input as CInput,
|
||||
InputNumber as CInputNumber,
|
||||
LabelInfo,
|
||||
Select
|
||||
Select,
|
||||
useAppUtils
|
||||
} from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Flex, Form, Radio } from 'antd';
|
||||
@@ -32,6 +34,7 @@ const StorageVolume = ({
|
||||
action: PageActionType;
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const { getRuleMessage } = useAppUtils();
|
||||
const { fetchData: createStorage } = useCreateStorage();
|
||||
const { detailData: storageData, fetchData: fetchStorage } =
|
||||
useQueryStorage();
|
||||
@@ -84,7 +87,7 @@ const StorageVolume = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldBlock data-field="storage">
|
||||
<FieldBlock>
|
||||
<Flex
|
||||
style={{
|
||||
justifyContent: 'space-between',
|
||||
@@ -146,6 +149,7 @@ const StorageVolume = ({
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
<div data-field="storage"></div>
|
||||
|
||||
{storageMode === StorageModeValueMap.Existing && (
|
||||
<Form.Item
|
||||
@@ -199,6 +203,26 @@ const StorageVolume = ({
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item<FormData>
|
||||
name={['spec', 'volumeMount']}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: getRuleMessage('input', 'gpuservice.template.mountPath')
|
||||
}
|
||||
]}
|
||||
>
|
||||
<CInput.Input
|
||||
required
|
||||
label={intl.formatMessage({
|
||||
id: 'gpuservice.template.mountPath'
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'clusters.volume.mountPath.format'
|
||||
})}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<StorageOverlay
|
||||
open={overlayOpen}
|
||||
|
||||
Reference in New Issue
Block a user