fix: pvc events api

This commit is contained in:
jialin
2026-05-26 19:16:50 +08:00
committed by jialin
parent c6e34db329
commit 7f14eb544c
13 changed files with 51 additions and 41 deletions
+1 -1
View File
@@ -186,7 +186,6 @@ const baseRoutes = [
name: 'gpuService', name: 'gpuService',
path: '/gpu-service', path: '/gpu-service',
key: 'gpuService', key: 'gpuService',
access: 'canSeeAdmin',
routes: [ routes: [
{ {
path: '/gpu-service', path: '/gpu-service',
@@ -224,6 +223,7 @@ const baseRoutes = [
path: '/gpu-service/storage-types', path: '/gpu-service/storage-types',
key: 'gpuServiceStorageTypes', key: 'gpuServiceStorageTypes',
icon: 'icon-storage-outlined', icon: 'icon-storage-outlined',
access: 'canSeeAdmin',
selectedIcon: 'icon-storage-filled', selectedIcon: 'icon-storage-filled',
defaultIcon: 'icon-storage-outlined', defaultIcon: 'icon-storage-outlined',
component: './gpu-service/storage-types' component: './gpu-service/storage-types'
@@ -46,9 +46,11 @@ const NumberSelection: React.FC<NumberSelectionProps> = ({
{ length: Math.max(0, maxCount) }, { length: Math.max(0, maxCount) },
(_, i) => i + 1 (_, i) => i + 1
); );
if (min <= 0) {
presetItems.unshift(0);
}
const items = presetItems; const items = presetItems;
const isItemDisabled = (num: number) => const isItemDisabled = (num: number) => !!disabled || num > max || num < min;
!!disabled || num > max || num < min;
const [inputValue, setInputValue] = useState<number | null>(() => const [inputValue, setInputValue] = useState<number | null>(() =>
value !== undefined && value !== null && !presetItems.includes(value) value !== undefined && value !== null && !presetItems.includes(value)
? value ? value
@@ -113,7 +115,7 @@ const NumberSelection: React.FC<NumberSelectionProps> = ({
aria-disabled={itemDisabled} aria-disabled={itemDisabled}
tabIndex={itemDisabled ? -1 : 0} tabIndex={itemDisabled ? -1 : 0}
className={classNames(styles.numberItem, { className={classNames(styles.numberItem, {
[styles.active]: num === value && !!value, [styles.active]: num === value && value != null,
[styles.itemDisabled]: itemDisabled && !disabled [styles.itemDisabled]: itemDisabled && !disabled
})} })}
onClick={() => handleSelect(num)} onClick={() => handleSelect(num)}
@@ -134,7 +136,7 @@ const NumberSelection: React.FC<NumberSelectionProps> = ({
<div className={styles.line}></div> <div className={styles.line}></div>
<div <div
className={classNames(styles.inputContainer, { className={classNames(styles.inputContainer, {
[styles.hasValue]: !!inputValue [styles.hasValue]: inputValue != null
})} })}
> >
<InputNumber <InputNumber
@@ -144,7 +146,7 @@ const NumberSelection: React.FC<NumberSelectionProps> = ({
max={max} max={max}
step={step} step={step}
disabled={disabled} disabled={disabled}
value={inputValue || undefined} value={inputValue ?? undefined}
style={{ style={{
fontSize: 14, fontSize: 14,
width: 60, width: 60,
@@ -154,7 +156,7 @@ const NumberSelection: React.FC<NumberSelectionProps> = ({
}} }}
styles={{ styles={{
input: { input: {
fontWeight: inputValue ? 500 : 400, fontWeight: inputValue != null ? 500 : 400,
...(styles?.input as React.CSSProperties) ...(styles?.input as React.CSSProperties)
} }
}} }}
@@ -162,7 +162,7 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({ item }) => {
show={!!remainingData.cpu} show={!!remainingData.cpu}
showDot={true} showDot={true}
icon="icon-cpu" icon="icon-cpu"
label="vCPU" label="CPU"
value={remainingData.cpu ?? '-'} value={remainingData.cpu ?? '-'}
></MetaItem> ></MetaItem>
</span> </span>
@@ -18,6 +18,7 @@ type ViewEventsModalProps = {
open: boolean; open: boolean;
name: string; name: string;
namespace: string; namespace: string;
volumeName?: string;
clusterID?: number; clusterID?: number;
hasPersistentVolume?: boolean; hasPersistentVolume?: boolean;
onCancel: () => void; onCancel: () => void;
@@ -32,8 +33,15 @@ const eventTypeStatus: Record<string, 'success' | 'warning' | 'error'> = {
const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => { const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
const intl = useIntl(); const intl = useIntl();
const { open, onCancel, name, namespace, clusterID, hasPersistentVolume } = const {
props || {}; open,
onCancel,
name,
namespace,
clusterID,
volumeName,
hasPersistentVolume
} = props || {};
const [activeKey, setActiveKey] = useState('instance'); const [activeKey, setActiveKey] = useState('instance');
const { const {
@@ -57,7 +65,7 @@ const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
if (!name || !namespace || !clusterID) return; if (!name || !namespace || !clusterID) return;
fetchInstanceEvents({ name, namespace, clusterID }); fetchInstanceEvents({ name, namespace, clusterID });
if (hasPersistentVolume) { if (hasPersistentVolume) {
fetchVolumeEvents({ name, namespace, clusterID }); fetchVolumeEvents({ name: volumeName || '', namespace, clusterID });
} }
}; };
@@ -206,7 +214,10 @@ const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
return ( return (
<ScrollerModal <ScrollerModal
title={ title={
<span className="flex flex-center" style={{ gap: 8 }}> <span
className="flex flex-center"
style={{ gap: 8, paddingInline: 24 }}
>
<span style={{ fontWeight: 'var(--font-weight-bold)' }}> <span style={{ fontWeight: 'var(--font-weight-bold)' }}>
{intl.formatMessage({ id: 'common.button.viewevent' })} {intl.formatMessage({ id: 'common.button.viewevent' })}
</span> </span>
@@ -232,6 +243,9 @@ const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
styles={{ styles={{
wrapper: { wrapper: {
borderRadius: 0 borderRadius: 0
},
container: {
paddingInline: 0
} }
}} }}
width="1000px" width="1000px"
@@ -13,7 +13,8 @@ export const InstanceStatusValueMap = {
Initialized: 'Initialized', Initialized: 'Initialized',
Preparing: 'Preparing', Preparing: 'Preparing',
NotReady: 'NotReady', NotReady: 'NotReady',
Ready: 'Ready' Ready: 'Ready',
Staring: 'Staring'
}; };
export const InstanceStatusLabelMap: Record<string, string> = { export const InstanceStatusLabelMap: Record<string, string> = {
@@ -25,7 +26,8 @@ export const InstanceStatusLabelMap: Record<string, string> = {
[InstanceStatusValueMap.Initialized]: 'Initialized', [InstanceStatusValueMap.Initialized]: 'Initialized',
[InstanceStatusValueMap.Preparing]: 'Preparing', [InstanceStatusValueMap.Preparing]: 'Preparing',
[InstanceStatusValueMap.NotReady]: 'NotReady', [InstanceStatusValueMap.NotReady]: 'NotReady',
[InstanceStatusValueMap.Ready]: 'Ready' [InstanceStatusValueMap.Ready]: 'Ready',
[InstanceStatusValueMap.Staring]: 'Staring'
}; };
export const status: Record<string, StatusType> = { export const status: Record<string, StatusType> = {
@@ -37,7 +39,8 @@ export const status: Record<string, StatusType> = {
[InstanceStatusValueMap.Initialized]: StatusMaps.transitioning, [InstanceStatusValueMap.Initialized]: StatusMaps.transitioning,
[InstanceStatusValueMap.Preparing]: StatusMaps.transitioning, [InstanceStatusValueMap.Preparing]: StatusMaps.transitioning,
[InstanceStatusValueMap.NotReady]: StatusMaps.error, [InstanceStatusValueMap.NotReady]: StatusMaps.error,
[InstanceStatusValueMap.Ready]: StatusMaps.success [InstanceStatusValueMap.Ready]: StatusMaps.success,
[InstanceStatusValueMap.Staring]: StatusMaps.transitioning
}; };
// Lifecycle actions (logs/events/start/stop) require K8s proxy endpoints that // Lifecycle actions (logs/events/start/stop) require K8s proxy endpoints that
@@ -207,6 +210,10 @@ export const pickCandidateForAccelerator = <
const sorted = [...tiers].sort( const sorted = [...tiers].sort(
(a, b) => parseQuantity(a.onceMaxRequest) - parseQuantity(b.onceMaxRequest) (a, b) => parseQuantity(a.onceMaxRequest) - parseQuantity(b.onceMaxRequest)
); );
const tier = sorted.find((t) => parseQuantity(t.onceMaxRequest) >= count); const tier = sorted.find((t) =>
count === 0
? parseQuantity(t.onceMaxRequest) > count
: parseQuantity(t.onceMaxRequest) >= count
);
return tier?.candidates?.[0] ?? null; return tier?.candidates?.[0] ?? null;
}; };
@@ -199,6 +199,7 @@ const StorageVolume = ({
> >
<Select <Select
disabled={disabled} disabled={disabled}
showSearch
label={intl.formatMessage({ label={intl.formatMessage({
id: 'gpuservice.storage.persistentVolume' id: 'gpuservice.storage.persistentVolume'
})} })}
@@ -113,7 +113,7 @@ const useInstancesColumns = ({
title: intl.formatMessage({ id: 'common.table.name' }), title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
sorter: false, sorter: true,
ellipsis: { ellipsis: {
showTitle: false showTitle: false
}, },
@@ -9,12 +9,14 @@ const useViewEvents = () => {
name: string; name: string;
namespace: string; namespace: string;
clusterID?: number; clusterID?: number;
volumeName?: string;
hasPersistentVolume: boolean; hasPersistentVolume: boolean;
}>({ }>({
open: false, open: false,
name: '', name: '',
namespace: '', namespace: '',
clusterID: undefined, clusterID: undefined,
volumeName: undefined,
hasPersistentVolume: false hasPersistentVolume: false
}); });
@@ -25,7 +27,9 @@ const useViewEvents = () => {
name: row?.name || '', name: row?.name || '',
namespace: row?.status?.namespace || '', namespace: row?.status?.namespace || '',
clusterID: row?.clusterId ?? undefined, clusterID: row?.clusterId ?? undefined,
hasPersistentVolume: !!volume?.persistent?.name volumeName: volume?.persistent?.name || volume?.persistentTemplate?.name,
hasPersistentVolume:
!!volume?.persistent?.name || !!volume?.persistentTemplate?.name
}); });
}; };
@@ -35,6 +39,7 @@ const useViewEvents = () => {
name: '', name: '',
namespace: '', namespace: '',
clusterID: undefined, clusterID: undefined,
volumeName: undefined,
hasPersistentVolume: false hasPersistentVolume: false
}); });
}; };
@@ -233,6 +233,7 @@ const GPUService: React.FC = () => {
name={openViewEventsModalStatus.name} name={openViewEventsModalStatus.name}
namespace={openViewEventsModalStatus.namespace} namespace={openViewEventsModalStatus.namespace}
clusterID={openViewEventsModalStatus.clusterID} clusterID={openViewEventsModalStatus.clusterID}
volumeName={openViewEventsModalStatus.volumeName}
hasPersistentVolume={openViewEventsModalStatus.hasPersistentVolume} hasPersistentVolume={openViewEventsModalStatus.hasPersistentVolume}
onCancel={closeViewEventsModal} onCancel={closeViewEventsModal}
/> />
@@ -36,12 +36,6 @@ const Basic = ({ action }: { action: string }) => {
label={intl.formatMessage({ id: 'common.table.displayName' })} label={intl.formatMessage({ id: 'common.table.displayName' })}
/> />
</Form.Item> </Form.Item>
<Form.Item<FormData> name="description">
<Textarea
scaleSize={true}
label={intl.formatMessage({ id: 'common.table.description' })}
/>
</Form.Item>
<Form.Item<FormData> <Form.Item<FormData>
name={['spec', 'data']} name={['spec', 'data']}
rules={[ rules={[
@@ -39,7 +39,7 @@ const usePublicKeyColumns = ({
title: intl.formatMessage({ id: 'common.table.name' }), title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
sorter: false, sorter: true,
ellipsis: { ellipsis: {
showTitle: false showTitle: false
}, },
@@ -49,20 +49,6 @@ const usePublicKeyColumns = ({
</AutoTooltip> </AutoTooltip>
) )
}, },
{
title: intl.formatMessage({ id: 'common.table.description' }),
dataIndex: 'description',
key: 'description',
sorter: false,
ellipsis: {
showTitle: false
},
render: (text: string) => (
<AutoTooltip ghost style={{ maxWidth: 360 }}>
{text || '-'}
</AutoTooltip>
)
},
{ {
title: intl.formatMessage({ id: 'common.table.createTime' }), title: intl.formatMessage({ id: 'common.table.createTime' }),
dataIndex: 'created_at', dataIndex: 'created_at',
@@ -52,7 +52,7 @@ const useStorageTypeColumns = ({
title: intl.formatMessage({ id: 'common.table.name' }), title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
sorter: false, sorter: true,
ellipsis: { showTitle: false }, ellipsis: { showTitle: false },
render: (text: string, record: ListItem) => ( render: (text: string, record: ListItem) => (
<AutoTooltip ghost minWidth={20}> <AutoTooltip ghost minWidth={20}>
@@ -24,7 +24,7 @@ const useStorageColumns = ({
title: intl.formatMessage({ id: 'common.table.name' }), title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
sorter: false, sorter: true,
ellipsis: { ellipsis: {
showTitle: false showTitle: false
}, },