refactor: credential table columns

This commit is contained in:
jialin
2025-09-16 11:26:17 +08:00
parent 43936e21d9
commit 0c1057d554
34 changed files with 648 additions and 503 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ const Credentials: React.FC = () => {
} = useTableFetch<ListItem>({
fetchAPI: queryClusterList,
deleteAPI: deleteCluster,
contentForDelete: 'users.table.user'
contentForDelete: 'menu.clusterManagement.clusters'
});
const intl = useIntl();
@@ -13,7 +13,7 @@ import {
ClusterListItem as ListItem
} from '../config/types';
import CloudProvider from './cloud-provider-form';
import RegisterClusterInner from './resiter-cluster-inner';
import RegisterClusterInner from './register-cluster-inner';
type AddModalProps = {
title: string;
@@ -4,8 +4,8 @@ import SealInput from '@/components/seal-form/seal-input';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max';
import { Button, Form } from 'antd';
import React from 'react';
import { Form } from 'antd';
import React, { useEffect } from 'react';
import { ProviderValueMap } from '../config';
import {
CredentialFormData as FormData,
@@ -41,32 +41,32 @@ const AddModal: React.FC<AddModalProps> = ({
onOk(data);
};
const handleCancel = () => {
form.resetFields();
onCancel();
};
useEffect(() => {
if (currentData) {
form.setFieldsValue(currentData);
}
}, [currentData]);
return (
<ScrollerModal
title={title}
open={open}
centered={true}
onOk={handleSumit}
onCancel={onCancel}
destroyOnClose={true}
closeIcon={false}
maskClosable={false}
keyboard={false}
width={600}
footer={
<ModalFooter
onOk={handleSumit}
onCancel={onCancel}
description={<Button>Validation Test</Button>}
></ModalFooter>
<ModalFooter onOk={handleSumit} onCancel={handleCancel}></ModalFooter>
}
>
<Form
form={form}
onFinish={handleOk}
preserve={false}
initialValues={currentData}
>
<Form form={form} onFinish={handleOk} preserve={false}>
<Form.Item<FormData>
name="name"
rules={[
@@ -88,7 +88,7 @@ const AddModal: React.FC<AddModalProps> = ({
</Form.Item>
{provider === ProviderValueMap.DigitalOcean && (
<>
<Form.Item<FormData>
{/* <Form.Item<FormData>
name="key"
rules={[
{
@@ -103,20 +103,18 @@ const AddModal: React.FC<AddModalProps> = ({
label="Access Key"
required={action === PageAction.CREATE}
></SealInput.Password>
</Form.Item>
</Form.Item> */}
<Form.Item<FormData>
name="secret"
rules={[
{
required: action === PageAction.CREATE,
message: intl.formatMessage({
id: 'users.form.rule.password'
})
message: 'Access Token is required'
}
]}
>
<SealInput.Password
label="Access Secret"
label="Access Token"
required={action === PageAction.CREATE}
></SealInput.Password>
</Form.Item>
@@ -25,6 +25,12 @@ const metricsMap = {
intl: false,
color: 'rgba(114, 46, 209,.8)'
},
allocated: {
label: 'Allocated',
type: 'Allocated',
intl: false,
color: 'rgba(250, 173, 20,.8)'
},
gpu: {
label: 'GPU',
type: 'GPU',
@@ -186,7 +192,7 @@ const ClusterDetail: React.FC<ClusterDetailProps> = ({ data }) => {
</Row>
</div>
<SubTitle>System Load</SubTitle>
<Row style={{ marginBottom: 20 }} gutter={20}>
<Row style={{ marginBottom: 16 }} gutter={16}>
<Col span={12}>
<Card height={CardHeight} clickable={false} ghost>
<TrendChart
@@ -208,14 +214,28 @@ const ClusterDetail: React.FC<ClusterDetailProps> = ({ data }) => {
</Card>
</Col>
</Row>
<Card height={CardHeight} clickable={false} ghost>
<TrendChart
data={detailContent?.history}
metrics={['cpu', 'gpu']}
metricsMap={metricsMap}
title="CPU & GPU"
></TrendChart>
</Card>
<Row gutter={16}>
<Col span={12}>
<Card height={CardHeight} clickable={false} ghost>
<TrendChart
data={detailContent?.history}
metrics={['cpu']}
metricsMap={metricsMap}
title="CPU"
></TrendChart>
</Card>
</Col>
<Col span={12}>
<Card height={CardHeight} clickable={false} ghost>
<TrendChart
data={detailContent?.history}
metrics={['gpu']}
metricsMap={metricsMap}
title="GPU"
></TrendChart>
</Card>
</Col>
</Row>
{data?.provider === ProviderValueMap.DigitalOcean && (
<>
<SubTitle>Worker Pools</SubTitle>
@@ -1,6 +1,6 @@
import ScrollerModal from '@/components/scroller-modal/index';
import React from 'react';
import RegisterClusterInner from './resiter-cluster-inner';
import RegisterClusterInner from './register-cluster-inner';
type AddModalProps = {
title: string;
@@ -38,6 +38,7 @@ const TrendChart: React.FC<TrendChartProps> = ({
: itemConfig.label;
legendData.push(name);
const itemDataList = _.get(data, item, []);
console.log('itemConfig:', itemConfig.color);
return {
name: name,
color: itemConfig.color,
+17 -1
View File
@@ -65,6 +65,22 @@ export const addActions = [
}
];
export const credentialActionList = [
{
key: 'edit',
label: 'common.button.edit',
icon: icons.EditOutlined
},
{
key: 'delete',
props: {
danger: true
},
label: 'common.button.delete',
icon: icons.DeleteOutlined
}
];
export const clusterActionList = [
{
key: 'edit',
@@ -74,7 +90,7 @@ export const clusterActionList = [
{
key: 'details',
label: 'common.button.detail',
icon: icons.DetailInfo
icon: icons.FileTextOutlined
},
{
key: 'add_worker',
+29 -125
View File
@@ -1,20 +1,13 @@
import AutoTooltip from '@/components/auto-tooltip';
import DeleteModal from '@/components/delete-modal';
import DropdownButtons from '@/components/drop-down-buttons';
import IconFont from '@/components/icon-font';
import { FilterBar } from '@/components/page-tools';
import { PageAction } from '@/config';
import type { PageActionType } from '@/config/types';
import useTableFetch from '@/hooks/use-table-fetch';
import {
DeleteOutlined,
EditOutlined,
KubernetesOutlined
} from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { ConfigProvider, Empty, Table, message } from 'antd';
import dayjs from 'dayjs';
import { useState } from 'react';
import {
createCredential,
@@ -23,43 +16,20 @@ import {
updateCredential
} from './apis';
import AddModal from './components/add-credential';
import { ProviderValueMap } from './config';
import { ProviderLabelMap, ProviderValueMap } from './config';
import {
CredentialFormData as FormData,
CredentialListItem as ListItem
} from './config/types';
const { Column } = Table;
const ActionList = [
{
key: 'edit',
label: 'common.button.edit',
icon: <EditOutlined></EditOutlined>
},
{
key: 'delete',
props: {
danger: true
},
label: 'common.button.delete',
icon: <DeleteOutlined></DeleteOutlined>
}
];
import useCredentialColumns from './hooks/use-credential-columns';
const addActions = [
{
label: 'Digital Ocean',
locale: false,
value: 'digital_ocean',
key: 'digital_ocean',
key: ProviderValueMap.DigitalOcean,
value: ProviderValueMap.DigitalOcean,
icon: <IconFont type="icon-digitalocean" />
},
{
label: 'Kubernetes',
locale: false,
value: 'kubernetes',
key: 'kubernetes',
icon: <KubernetesOutlined className="size-16" />
}
];
@@ -80,7 +50,7 @@ const Credentials: React.FC = () => {
} = useTableFetch<ListItem>({
fetchAPI: queryCredentialList,
deleteAPI: deleteCredential,
contentForDelete: 'users.table.user'
contentForDelete: 'menu.clusterManagement.credentials'
});
const intl = useIntl();
@@ -98,12 +68,17 @@ const Credentials: React.FC = () => {
currentData: undefined
});
const handleAddCredential = () => {
const handleAddCredential = (item: { key: string; label: string }) => {
setOpenModalStatus({
provider: ProviderValueMap.DigitalOcean,
provider: item.key,
open: true,
action: PageAction.CREATE,
title: intl.formatMessage({ id: 'clusters.button.addCredential' }),
title: intl.formatMessage(
{ id: 'clusters.button.add.credential' },
{
provider: ProviderLabelMap[item.key] || item.key
}
),
currentData: undefined
});
};
@@ -132,8 +107,11 @@ const Credentials: React.FC = () => {
};
const handleModalCancel = () => {
console.log('handleModalCancel');
setOpenModalStatus({ ...openModalStatus, open: false });
setOpenModalStatus({
...openModalStatus,
open: false,
currentData: undefined
});
};
const handleEditUser = (row: ListItem) => {
@@ -142,20 +120,20 @@ const Credentials: React.FC = () => {
open: true,
action: PageAction.EDIT,
title: intl.formatMessage(
{ id: 'common.buton.edit.item' },
{ id: 'common.button.edit.item' },
{ name: row.name }
),
currentData: row
});
};
const handleSelect = (val: any, row: ListItem) => {
const handleSelect = useMemoizedFn((val: any, row: ListItem) => {
if (val === 'edit') {
handleEditUser(row);
} else if (val === 'delete') {
handleDelete({ ...row, name: row.name });
}
};
});
const renderEmpty = (type?: string) => {
if (type !== 'Table') return;
@@ -169,6 +147,8 @@ const Credentials: React.FC = () => {
return <div></div>;
};
const columns = useCredentialColumns(sortOrder, handleSelect);
return (
<>
<PageContainer
@@ -185,6 +165,8 @@ const Credentials: React.FC = () => {
extra={[]}
>
<FilterBar
actionItems={addActions}
actionType="dropdown"
showSelect={false}
showPrimaryButton={true}
marginBottom={22}
@@ -202,6 +184,8 @@ const Credentials: React.FC = () => {
<ConfigProvider renderEmpty={renderEmpty}>
<Table
tableLayout="fixed"
columns={columns}
dataSource={dataSource.dataList}
rowSelection={rowSelection}
loading={dataSource.loading}
@@ -215,87 +199,7 @@ const Credentials: React.FC = () => {
hideOnSinglePage: queryParams.perPage === 10,
onChange: handlePageChange
}}
>
<Column
title={intl.formatMessage({ id: 'common.table.name' })}
dataIndex="name"
key="name"
ellipsis={{
showTitle: false
}}
render={(text, record) => {
return (
<AutoTooltip ghost minWidth={20}>
{text}
</AutoTooltip>
);
}}
/>
<Column
title={intl.formatMessage({ id: 'clusters.table.provider' })}
dataIndex="provider"
key="provider"
ellipsis={{
showTitle: false
}}
render={(text, record) => {
return (
<AutoTooltip ghost minWidth={20}>
{text}
</AutoTooltip>
);
}}
/>
<Column
title={intl.formatMessage({ id: 'common.table.createTime' })}
dataIndex="created_at"
key="createTime"
defaultSortOrder="descend"
sortOrder={sortOrder}
showSorterTooltip={false}
sorter={false}
ellipsis={{
showTitle: false
}}
render={(text, record) => {
return (
<AutoTooltip ghost minWidth={20}>
{dayjs(text).format('YYYY-MM-DD HH:mm:ss')}
</AutoTooltip>
);
}}
/>
<Column
title={intl.formatMessage({ id: 'common.table.description' })}
dataIndex="description"
key="description"
ellipsis={{
showTitle: false
}}
render={(text, record) => {
return (
<AutoTooltip ghost minWidth={20}>
{text}
</AutoTooltip>
);
}}
/>
<Column
title={intl.formatMessage({ id: 'common.table.operation' })}
key="operation"
ellipsis={{
showTitle: false
}}
render={(text, record: ListItem) => {
return (
<DropdownButtons
items={ActionList}
onSelect={(val) => handleSelect(val, record)}
></DropdownButtons>
);
}}
/>
</Table>
></Table>
</ConfigProvider>
</PageContainer>
<AddModal
@@ -0,0 +1,77 @@
// columns.ts
import AutoTooltip from '@/components/auto-tooltip';
import DropdownButtons from '@/components/drop-down-buttons';
import { useIntl } from '@umijs/max';
import { ColumnsType } from 'antd/es/table';
import type { SortOrder } from 'antd/es/table/interface';
import dayjs from 'dayjs';
import { useMemo } from 'react';
import { ProviderLabelMap, credentialActionList } from '../config';
import { CredentialListItem as ListItem } from '../config/types';
const useCredentialColumns = (
sortOrder: SortOrder,
handleSelect: (val: string, record: ListItem) => void
): ColumnsType<ListItem> => {
const intl = useIntl();
return useMemo(() => {
return [
{
title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name',
render: (text: string) => (
<AutoTooltip ghost minWidth={20}>
{text}
</AutoTooltip>
)
},
{
title: intl.formatMessage({ id: 'clusters.table.provider' }),
dataIndex: 'provider',
render: (value: string) => <span>{ProviderLabelMap[value]}</span>
},
{
title: intl.formatMessage({ id: 'common.table.createTime' }),
dataIndex: 'created_at',
showSorterTooltip: false,
defaultSortOrder: 'descend',
sortOrder: sortOrder,
sorter: false,
ellipsis: {
showTitle: false
},
render: (value: string) => (
<span>{dayjs(value).format('YYYY-MM-DD HH:mm:ss')}</span>
)
},
{
title: intl.formatMessage({ id: 'common.table.description' }),
dataIndex: 'description',
ellipsis: {
showTitle: false
},
render: (value: string) => (
<AutoTooltip ghost minWidth={20}>
{value}
</AutoTooltip>
)
},
{
title: intl.formatMessage({ id: 'common.table.operation' }),
dataIndex: 'operations',
ellipsis: {
showTitle: false
},
render: (value: string, record: ListItem) => (
<DropdownButtons
items={credentialActionList}
onSelect={(val) => handleSelect(val, record)}
></DropdownButtons>
)
}
];
}, [handleSelect, sortOrder]);
};
export default useCredentialColumns;
+5 -5
View File
@@ -46,11 +46,11 @@ export const ActionList: ActionItem[] = [
key: 'edit',
icon: icons.EditOutlined
},
{
label: 'common.button.detail',
key: 'details',
icon: icons.FileTextOutlined
},
// {
// label: 'common.button.detail',
// key: 'details',
// icon: icons.FileTextOutlined
// },
{
label: 'models.openinplayground',
key: 'chat',
+4 -4
View File
@@ -194,6 +194,10 @@ const LoginForm = () => {
return SSOAuth.options.oidc || SSOAuth.options.saml;
}, [SSOAuth.options]);
const isThirdPartyAuthHandling = useMemo(() => {
return loading && !authError;
}, [loading, authError]);
const renderLoginButtons = () => {
// do not render login buttons if using password login or no third-party login
if (!hasThirdPartyLogin || isPassword) return null;
@@ -229,10 +233,6 @@ const LoginForm = () => {
);
};
const isThirdPartyAuthHandling = useMemo(() => {
return loading && !authError;
}, [loading, authError]);
return (
<div>
{contextHolder}
@@ -67,4 +67,4 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
);
};
export default React.memo(AddWorker);
export default AddWorker;
@@ -111,4 +111,4 @@ const UpdateLabels: React.FC<ViewModalProps> = (props) => {
);
};
export default React.memo(UpdateLabels);
export default UpdateLabels;
@@ -63,6 +63,9 @@ const useGPUColumns = (props: {
{
title: intl.formatMessage({ id: 'clusters.title' }),
dataIndex: 'cluster_id',
ellipsis: {
showTitle: false
},
render: (text: number, record: GPUDeviceItem) => (
<AutoTooltip ghost>
{clusterList.find((item) => item.value === text)?.label}
@@ -70,8 +73,11 @@ const useGPUColumns = (props: {
)
},
{
title: intl.formatMessage({ id: 'resources.table.workername' }),
title: 'Worker',
dataIndex: 'worker_name',
ellipsis: {
showTitle: false
},
render: (text: string, record: GPUDeviceItem) => (
<AutoTooltip ghost>{text}</AutoTooltip>
)
@@ -294,7 +294,7 @@ const useInstanceColumns = (props: {
return useMemo(() => {
return [
{
title: intl.formatMessage({ id: 'common.table.name' }),
title: intl.formatMessage({ id: 'resources.model.instance' }),
dataIndex: 'name',
width: 240,
render: (text: string, record: ListItem) => (
@@ -9,6 +9,7 @@ import {
CodeOutlined,
DeleteOutlined,
EditOutlined,
FileTextOutlined,
InfoCircleOutlined
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
@@ -31,7 +32,7 @@ const ActionList = [
{
label: 'common.button.detail',
key: 'details',
icon: <IconFont type="icon-detail-info" />
icon: <FileTextOutlined></FileTextOutlined>
},
{
label: 'common.button.logs',