fix: ux issues

This commit is contained in:
jialin
2026-05-26 19:16:50 +08:00
committed by jialin
parent acb90531b2
commit c6e34db329
27 changed files with 354 additions and 244 deletions
@@ -31,13 +31,6 @@ type AddModalProps = {
onCancel: () => void;
};
type InstanceTypeSelection = {
instanceType?: string;
manufacturer?: string;
};
const EMPTY_INSTANCE_TYPE_SELECTION: InstanceTypeSelection = {};
const matchKeyword = (fields: Array<unknown>, keyword: string) => {
const trimmed = keyword.trim().toLowerCase();
if (!trimmed) return true;
@@ -85,11 +78,17 @@ const AddModal: React.FC<AddModalProps> = ({
const intl = useIntl();
const form = useRef<any>(null);
const sessionRef = useRef(0);
const [instanceTypeSelection, setInstanceTypeSelection] =
useState<InstanceTypeSelection>(EMPTY_INSTANCE_TYPE_SELECTION);
const [instanceTypeSelection, setInstanceTypeSelection] = useState<{
instanceType?: string;
manufacturer?: string;
}>({
instanceType: undefined,
manufacturer: undefined
});
const [templateId, setTemplateId] = useState<number | undefined>();
const [instanceKeyword, setInstanceKeyword] = useState('');
const [templateKeyword, setTemplateKeyword] = useState('');
const [loading, setLoading] = useState(false);
const {
detailData,
@@ -116,6 +115,20 @@ const AddModal: React.FC<AddModalProps> = ({
: undefined;
};
const saveInstanceDataInDescription = (instanceType: InstanceTypeItem) => {
return JSON.stringify(
{
name: instanceType.name,
spec: {
...instanceType.spec
}
},
null,
2
);
};
// apply the selection of instance type and template
const applySelection = (
instanceType: InstanceTypeItem,
template: TemplateItem | undefined
@@ -126,37 +139,29 @@ const AddModal: React.FC<AddModalProps> = ({
instanceType: instanceType.name,
manufacturer
});
setTemplateId(template?.id);
if (template) {
const currentSpec = form.current?.getFieldsValue()?.spec || {};
const formValues = form.current?.getFieldsValue();
form.current?.setFieldsValue({
manufacturer: template.manufacturer,
description: JSON.stringify(
{
name: instanceType.name,
spec: {
...instanceType.spec
}
},
null,
2
),
description: saveInstanceDataInDescription(instanceType),
spec: {
...currentSpec,
...formValues?.spec,
...template.spec,
resources: {
...(currentSpec.resources || {}),
...(template.spec?.resources || {})
sshPublicKeys: formValues?.spec?.sshPublicKeys,
volume: {
...formValues?.spec?.volume
}
}
});
} else {
form.current?.setFieldsValue({
manufacturer: undefined,
description: JSON.stringify(instanceType.spec, null, 2)
description: saveInstanceDataInDescription(instanceType)
});
}
// update form
form.current?.applyInstanceType?.(instanceType);
};
@@ -175,6 +180,7 @@ const AddModal: React.FC<AddModalProps> = ({
);
};
// initial
const applyAutoSelection = (
instanceTypes: InstanceTypeItem[],
templates: TemplateItem[]
@@ -208,7 +214,10 @@ const AddModal: React.FC<AddModalProps> = ({
useEffect(() => {
if (!open) {
sessionRef.current += 1;
setInstanceTypeSelection(EMPTY_INSTANCE_TYPE_SELECTION);
setInstanceTypeSelection({
instanceType: undefined,
manufacturer: undefined
});
setTemplateId(undefined);
setInstanceKeyword('');
setTemplateKeyword('');
@@ -240,6 +249,7 @@ const AddModal: React.FC<AddModalProps> = ({
) {
return false;
}
return matchKeyword(
[item.name, item.spec?.image, item.spec?.volumeMount],
templateKeyword
@@ -256,9 +266,14 @@ const AddModal: React.FC<AddModalProps> = ({
};
const onFinish = async (values: FormData) => {
onOk({
...values
});
setLoading(true);
try {
await onOk({
...values
});
} finally {
setLoading(false);
}
};
const handleInstanceTypeChange = (item: InstanceTypeItem) => {
@@ -271,10 +286,19 @@ const AddModal: React.FC<AddModalProps> = ({
const handleTemplateChange = (id: number, item: TemplateItem) => {
setTemplateId(id);
const formValues = form.current?.getFieldsValue();
form.current?.setFieldsValue({
spec: {
...form.current?.getFieldsValue()?.spec,
...item.spec
...formValues?.spec,
...item.spec,
sshPublicKeys: formValues?.spec?.sshPublicKeys,
resources: {
...item?.spec?.resources,
accelerator: formValues?.spec?.resources?.accelerator
},
volume: {
...formValues?.spec?.volume
}
}
});
};
@@ -400,6 +424,7 @@ const AddModal: React.FC<AddModalProps> = ({
onOk={handleSubmit}
onCancel={handleCancel}
showOkBtn={!readonly}
loading={loading}
style={{
padding: '16px 24px 8px',
display: 'flex',
@@ -34,7 +34,7 @@ const InstanceTypeList: React.FC<InstanceTypeListProps> = ({
loading
}) => {
const handleSelect = (item: InstanceTypeItemModel) => {
if (!isAvailable(item)) return;
if (!isAvailable(item) || value === item.name) return;
onChange?.(item);
};
@@ -19,6 +19,7 @@ type ViewEventsModalProps = {
name: string;
namespace: string;
clusterID?: number;
hasPersistentVolume?: boolean;
onCancel: () => void;
};
@@ -31,7 +32,8 @@ const eventTypeStatus: Record<string, 'success' | 'warning' | 'error'> = {
const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
const intl = useIntl();
const { open, onCancel, name, namespace, clusterID } = props || {};
const { open, onCancel, name, namespace, clusterID, hasPersistentVolume } =
props || {};
const [activeKey, setActiveKey] = useState('instance');
const {
@@ -54,7 +56,9 @@ const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
const refreshAll = () => {
if (!name || !namespace || !clusterID) return;
fetchInstanceEvents({ name, namespace, clusterID });
fetchVolumeEvents({ name, namespace, clusterID });
if (hasPersistentVolume) {
fetchVolumeEvents({ name, namespace, clusterID });
}
};
useEffect(() => {
@@ -184,16 +188,20 @@ const ViewEventsModal: React.FC<ViewEventsModalProps> = (props) => {
}),
children: renderTable(instanceEvents, instanceLoading)
},
{
key: 'volume',
label: intl.formatMessage({
id: 'gpuservice.instance.event.tab.volume'
}),
children: renderTable(volumeEvents, volumeLoading)
}
...(hasPersistentVolume
? [
{
key: 'volume',
label: intl.formatMessage({
id: 'gpuservice.instance.event.tab.volume'
}),
children: renderTable(volumeEvents, volumeLoading)
}
]
: [])
];
const isLoading = instanceLoading || volumeLoading;
const isLoading = instanceLoading || (hasPersistentVolume && volumeLoading);
return (
<ScrollerModal