diff --git a/src/pages/benchmark/components/add-benchmark-modal.tsx b/src/pages/benchmark/components/add-benchmark-modal.tsx index fb4c16db..1be91976 100644 --- a/src/pages/benchmark/components/add-benchmark-modal.tsx +++ b/src/pages/benchmark/components/add-benchmark-modal.tsx @@ -10,6 +10,7 @@ type AddModalProps = { action: PageActionType; open: boolean; currentData?: ListItem; // Used when action is EDIT + clusterList?: Global.BaseOption[]; onOk: (values: FormData) => void; onCancel: () => void; }; @@ -18,6 +19,7 @@ const AddBenchmark: React.FC = ({ action, open, currentData, + clusterList, onOk, onCancel }) => { @@ -51,6 +53,7 @@ const AddBenchmark: React.FC = ({ action={action} open={open} currentData={currentData} + clusterList={clusterList} onFinish={handleOk} /> diff --git a/src/pages/benchmark/components/detail-content.tsx b/src/pages/benchmark/components/detail-content.tsx index c3e3041b..2c1ca27f 100644 --- a/src/pages/benchmark/components/detail-content.tsx +++ b/src/pages/benchmark/components/detail-content.tsx @@ -1,27 +1,18 @@ import IconFont from '@/components/icon-font'; -import { useQueryClusterList } from '@/pages/cluster-management/services/use-query-cluster-list'; import { useIntl, useSearchParams } from '@umijs/max'; import { Tabs, TabsProps } from 'antd'; -import React, { useEffect, useState } from 'react'; -import DetailContext from '../config/detail-context'; -import { BenchmarkListItem } from '../config/types'; -import useQueryDetail from '../services/use-query-detail'; +import React, { useState } from 'react'; import Environment from './environment'; import Summary from './summary'; -const Details: React.FC<{ currentData?: BenchmarkListItem }> = ({ - currentData -}) => { +const Details: React.FC<{ + tabBarExtraContent: { + right: React.ReactNode; + }; +}> = ({ tabBarExtraContent }) => { const intl = useIntl(); - const [searchParams] = useSearchParams(); - const id = searchParams.get('id'); - const { loading, detailData, cancelRequest, fetchData } = useQueryDetail(); - const { - clusterList, - fetchClusterList, - cancelRequest: cancelClusterRequest - } = useQueryClusterList(); const [activeKey, setActiveKey] = useState('summary'); + const [searchParams] = useSearchParams(); const items: TabsProps['items'] = [ { @@ -36,45 +27,21 @@ const Details: React.FC<{ currentData?: BenchmarkListItem }> = ({ children: , icon: } - // { - // key: 'logs', - // label: intl.formatMessage({ id: 'benchmark.detail.logs.title' }), - // children: , - // icon: - // } ]; const handleChangeTab = (key: string) => { setActiveKey(key); }; - useEffect(() => { - if (id) { - fetchData(id); - fetchClusterList({ page: -1 }); - } else { - cancelRequest(); - cancelClusterRequest(); - } - }, [id]); - return ( - - - + ); }; diff --git a/src/pages/benchmark/components/fade-in.less b/src/pages/benchmark/components/fade-in.less new file mode 100644 index 00000000..f9c44a0d --- /dev/null +++ b/src/pages/benchmark/components/fade-in.less @@ -0,0 +1,14 @@ +@keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.fade-in { + animation-name: fade-in; + animation-fill-mode: both; +} diff --git a/src/pages/benchmark/components/fade-in.tsx b/src/pages/benchmark/components/fade-in.tsx new file mode 100644 index 00000000..725d4104 --- /dev/null +++ b/src/pages/benchmark/components/fade-in.tsx @@ -0,0 +1,29 @@ +import React, { PropsWithChildren } from 'react'; +import './fade-in.less'; + +type FadeInProps = PropsWithChildren<{ + duration?: number; + delay?: number; + className?: string; +}>; + +const FadeIn: React.FC = ({ + children, + duration = 200, + delay = 0, + className +}) => { + return ( +
+ {children} +
+ ); +}; + +export default FadeIn; diff --git a/src/pages/benchmark/components/row-actions.tsx b/src/pages/benchmark/components/row-actions.tsx index 0d57ae5d..3c4fb57b 100644 --- a/src/pages/benchmark/components/row-actions.tsx +++ b/src/pages/benchmark/components/row-actions.tsx @@ -53,15 +53,18 @@ const actionList = [ interface RowActionsProps { record: ListItem; + page?: 'detail' | 'list'; handleSelect: (key: string, record: ListItem) => void; } const RowActions: React.FC = (props) => { - const { record, handleSelect } = props; + const { record, handleSelect, page = 'list' } = props; const { onDownloadLog, contextHolder } = useDownloadLogs(); const actions = actionList.filter((action) => { - if (action.status && action.status.length > 0) { + if (page === 'detail' && action.key === 'edit') { + return false; + } else if (action.status && action.status.length > 0) { return action.status?.includes(record.state); } diff --git a/src/pages/benchmark/components/summary/instance.tsx b/src/pages/benchmark/components/summary/instance.tsx index 401d94b9..bd4dc705 100644 --- a/src/pages/benchmark/components/summary/instance.tsx +++ b/src/pages/benchmark/components/summary/instance.tsx @@ -1,14 +1,9 @@ import AutoTooltip from '@/components/auto-tooltip'; import { useIntl } from '@umijs/max'; import { Descriptions, Flex, Tag } from 'antd'; -import _ from 'lodash'; import React, { useMemo } from 'react'; import { useDetailContext } from '../../config/detail-context'; -const calcTotalVram = (vram: Record) => { - return _.sum(_.values(vram)); -}; - const Instance: React.FC = () => { const intl = useIntl(); const { detailData } = useDetailContext(); diff --git a/src/pages/benchmark/details.tsx b/src/pages/benchmark/details.tsx index 9f83e453..2e04d3eb 100644 --- a/src/pages/benchmark/details.tsx +++ b/src/pages/benchmark/details.tsx @@ -1,14 +1,45 @@ +import DeleteModal from '@/components/delete-modal'; +import BaseSelect from '@/components/seal-form/base/select'; import { useIntl, useNavigate, useSearchParams } from '@umijs/max'; -import React, { useEffect } from 'react'; +import { useMemoizedFn } from 'ahooks'; +import React, { useEffect, useRef } from 'react'; import { PageContainerInner } from '../_components/page-box'; import PageBreadcrumb from '../_components/page-breadcrumb'; +import { deleteBenchmark } from './apis'; import DetailContent from './components/detail-content'; +import FadeIn from './components/fade-in'; +import RowActions from './components/row-actions'; +import ViewLogsModal from './components/view-logs-modal'; +import DetailContext from './config/detail-context'; +import { BenchmarkListItem } from './config/types'; +import useViewLogs from './hooks/use-view-logs'; +import useQueryBenchmarkList from './services/use-query-benchmarks'; +import useQueryDetail from './services/use-query-detail'; +import useStopBenchmark from './services/use-stop-benchmark'; const Details: React.FC = () => { + const modalRef = useRef(null); const navigate = useNavigate(); const intl = useIntl(); + const { + dataList: benchmarkList, + fetchData: fetchBenchmarkList, + cancelRequest: cancelBenchmarkRequest + } = useQueryBenchmarkList(); + const { loading, detailData, cancelRequest, fetchData } = useQueryDetail(); + const { openViewLogsModal, closeViewLogsModal, openViewLogsModalStatus } = + useViewLogs(); + const { handleStopBenchmark } = useStopBenchmark(); const [searchParams] = useSearchParams(); const name = searchParams.get('name'); + const id = searchParams.get('id'); + + const handleOnChange = (value: number, option: any) => { + navigate( + `/models/benchmark/detail?id=${option.value}&name=${option.label}`, + { state: 'benchmark-details', replace: true } + ); + }; const breadcrumbItems = [ { @@ -16,20 +47,114 @@ const Details: React.FC = () => { onClick: () => navigate(-1) }, { - title: name + title: ( + + ) } ]; + + const handleDelete = (row: BenchmarkListItem) => { + modalRef.current?.show({ + content: 'benchmark.title', + operation: 'common.delete.single.confirm', + name: row.name, + async onOk() { + await deleteBenchmark(row.id); + fetchBenchmarkList({ page: -1 }).then((items) => { + if (items.length === 0) { + navigate(-1); + } else { + handleOnChange(items[0].id, { + value: items[0].id, + label: items[0].name + }); + } + }); + } + }); + }; + + const handleSelect = useMemoizedFn((val: any, row: BenchmarkListItem) => { + if (val === 'delete') { + handleDelete({ ...row, name: row.name }); + } else if (val === 'viewlog') { + openViewLogsModal(row); + } else if (val === 'stop') { + handleStopBenchmark(row.id); + } + }); + useEffect(() => { document.title = `${intl.formatMessage({ id: 'benchmark.title' })} - ${name}`; }, [name, intl]); + useEffect(() => { + fetchBenchmarkList({ page: -1 }); + return () => { + cancelBenchmarkRequest(); + }; + }, []); + + useEffect(() => { + if (id) { + fetchData(id); + } else { + cancelRequest(); + } + }, [id]); + return ( }} > - + + +
+ +
+ + ) + }} + >
+
+ +
); }; diff --git a/src/pages/benchmark/forms/basic.tsx b/src/pages/benchmark/forms/basic.tsx index 513e5f10..d97fca48 100644 --- a/src/pages/benchmark/forms/basic.tsx +++ b/src/pages/benchmark/forms/basic.tsx @@ -3,7 +3,6 @@ import SealSelect from '@/components/seal-form/seal-select'; import { PageAction } from '@/config'; import useAppUtils from '@/hooks/use-app-utils'; import { ClusterStatusValueMap } from '@/pages/cluster-management/config'; -import { useQueryClusterList } from '@/pages/cluster-management/services/use-query-cluster-list'; import { useIntl } from '@umijs/max'; import { Form } from 'antd'; import React, { useEffect } from 'react'; @@ -15,13 +14,7 @@ const BasicForm: React.FC = () => { const intl = useIntl(); const form = Form.useFormInstance(); const { getRuleMessage } = useAppUtils(); - const { action, open } = useFormContext(); - const { - loading: clusterLoading, - fetchClusterList, - cancelRequest: cancelClusterRequest, - clusterList - } = useQueryClusterList(); + const { action, open, clusterList } = useFormContext(); useEffect(() => { const initClusterId = (list: any[]) => { @@ -37,18 +30,14 @@ const BasicForm: React.FC = () => { return cluster_id; }; - fetchClusterList({ page: -1 }).then((list) => { - if (list.length > 0 && action === PageAction.CREATE) { - form.setFieldValue('cluster_id', initClusterId(list)); - } - }); - }, [form, action]); - - useEffect(() => { - if (!open) { - cancelClusterRequest(); + if ( + clusterList && + clusterList?.length > 0 && + action === PageAction.CREATE + ) { + form.setFieldValue('cluster_id', initClusterId(clusterList)); } - }, [open]); + }, [form, action, clusterList]); return ( <> @@ -78,7 +67,6 @@ const BasicForm: React.FC = () => { > []; onFinish: (values: FormData) => Promise; } @@ -33,7 +34,7 @@ const TABKeysMap = { }; const ProviderForm: React.FC = forwardRef((props, ref) => { - const { action, currentData, onFinish, open } = props; + const { action, currentData, onFinish, open, clusterList } = props; const intl = useIntl(); const [form] = Form.useForm(); const profile = Form.useWatch('profile', form); @@ -109,7 +110,8 @@ const ProviderForm: React.FC = forwardRef((props, ref) => {
{ +const useColumnSettings = (options: { + contentHeight: number; + clusterList: Global.BaseOption[]; +}) => { const intl = useIntl(); - const { contentHeight } = options; + const { contentHeight, clusterList } = options; const [selectedColumns, setSelectedColumns] = React.useState(defaultColumns); @@ -241,22 +244,22 @@ const useColumnSettings = (options: { contentHeight: number }) => { title: renderTitle(intl.formatMessage({ id: 'clusters.title' })), pos: 1, dataIndex: 'cluster_id', - render: (text: string) => ( + render: (text: number) => ( - {text} - - ) - }, - { - title: renderTitle(intl.formatMessage({ id: 'resources.worker' })), - pos: 2, - dataIndex: 'worker_id', - render: (text: string) => ( - - {text} + {clusterList?.find((item) => item.value === text)?.label || text} ) }, + // { + // title: renderTitle(intl.formatMessage({ id: 'resources.worker' })), + // pos: 2, + // dataIndex: 'worker_id', + // render: (text: string) => ( + // + // {text} + // + // ) + // }, { title: renderTitle( intl.formatMessage({ id: 'benchmark.detail.modelName' }) @@ -364,9 +367,8 @@ const useColumnSettings = (options: { contentHeight: number }) => { ); // Sort by pos selected.sort((a, b) => (a.pos || 0) - (b.pos || 0)); - console.log('columns===', selected); return selected; - }, [selectedColumns]); + }, [selectedColumns, clusterList]); const SettingsButton = ( { }); const { openViewLogsModal, closeViewLogsModal, openViewLogsModalStatus } = useViewLogs(); - const { SettingsButton, columns: selectedColumns } = useColumnSettings({ - contentHeight: 320 - }); const { handleStopBenchmark } = useStopBenchmark(); - const { datasetList, fetchDatasetData } = useQueryDataset(); const { exportData } = useExportBenchmark(); + const { + fetchClusterList, + cancelRequest: cancelClusterRequest, + clusterList + } = useQueryClusterList(); + const { SettingsButton, columns: selectedColumns } = useColumnSettings({ + contentHeight: 320, + clusterList + }); useEffect(() => { fetchModelList({ page: -1 }); + fetchClusterList({ page: -1 }); fetchDatasetData(); + return () => { + cancelClusterRequest(); + }; }, []); const handleAddBenchmark = () => { @@ -110,7 +120,7 @@ const Benchmark: React.FC = () => { closeBenchmarkModal(); }; - const handleEditUser = (row: ListItem) => { + const handleEdit = (row: ListItem) => { openBenchmarkModal( PageAction.EDIT, intl.formatMessage({ id: 'benchmark.button.edit' }), @@ -120,7 +130,7 @@ const Benchmark: React.FC = () => { const handleSelect = useMemoizedFn((val: any, row: ListItem) => { if (val === 'edit') { - handleEditUser(row); + handleEdit(row); } else if (val === 'delete') { handleDelete({ ...row, name: row.name }); } else if (val === 'viewlog') { @@ -134,7 +144,8 @@ const Benchmark: React.FC = () => { (record: ListItem, dataIndex: string) => { if (dataIndex === 'name') { navigate( - `/models/benchmark/detail?id=${record.id}&name=${record.name}` + `/models/benchmark/detail?id=${record.id}&name=${record.name}`, + { state: 'benchmark-details' } ); } } @@ -230,6 +241,7 @@ const Benchmark: React.FC = () => { string; + getValue?: (item: ListItem) => any; +}) => { + const { dataList, loading, fetchData, cancelRequest } = useQueryDataList< + ListItem, + Global.SearchParams + >({ + key: 'benchmarkList', + fetchList: queryBenchmarkList + }); + + return { + dataList, + loading, + fetchData, + cancelRequest + }; +}; + +export default useQueryBenchmarkList;