feat: benchmark detail page
This commit is contained in:
@@ -122,6 +122,7 @@ export default [
|
||||
icon: 'icon-speed',
|
||||
selectedIcon: 'icon-speed-filled',
|
||||
defaultIcon: 'icon-speed',
|
||||
access: 'canSeeAdmin',
|
||||
component: './benchmark/index'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -107,7 +107,47 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
|
||||
const renderRight = useMemo(() => {
|
||||
const renderLeft = () => {
|
||||
return (
|
||||
<Space>
|
||||
<Input
|
||||
prefix={
|
||||
<SearchOutlined
|
||||
style={{ color: 'var(--ant-color-text-placeholder)' }}
|
||||
></SearchOutlined>
|
||||
}
|
||||
placeholder={
|
||||
inputHolder ||
|
||||
intl.formatMessage({
|
||||
id: 'common.filter.name'
|
||||
})
|
||||
}
|
||||
style={{ width: widths?.input || 230 }}
|
||||
allowClear
|
||||
onChange={handleInputChange}
|
||||
></Input>
|
||||
{showSelect && (
|
||||
<BaseSelect
|
||||
allowClear
|
||||
showSearch={false}
|
||||
placeholder={selectHolder}
|
||||
style={{ width: widths?.select || 230 }}
|
||||
size="large"
|
||||
onChange={handleSelectChange}
|
||||
options={selectOptions}
|
||||
></BaseSelect>
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||
onClick={handleSearch}
|
||||
icon={<SyncOutlined></SyncOutlined>}
|
||||
></Button>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
const renderRight = () => {
|
||||
if (!handleClickPrimary && !handleDeleteByBatch) {
|
||||
return null;
|
||||
}
|
||||
@@ -156,56 +196,14 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
}, [
|
||||
actionItems,
|
||||
actionType,
|
||||
rowSelection?.selectedRowKeys,
|
||||
handleClickPrimary,
|
||||
intl
|
||||
]);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageTools
|
||||
marginBottom={marginBottom}
|
||||
marginTop={0}
|
||||
left={
|
||||
<Space>
|
||||
<Input
|
||||
prefix={
|
||||
<SearchOutlined
|
||||
style={{ color: 'var(--ant-color-text-placeholder)' }}
|
||||
></SearchOutlined>
|
||||
}
|
||||
placeholder={
|
||||
inputHolder ||
|
||||
intl.formatMessage({
|
||||
id: 'common.filter.name'
|
||||
})
|
||||
}
|
||||
style={{ width: widths?.input || 230 }}
|
||||
allowClear
|
||||
onChange={handleInputChange}
|
||||
></Input>
|
||||
{showSelect && (
|
||||
<BaseSelect
|
||||
allowClear
|
||||
showSearch={false}
|
||||
placeholder={selectHolder}
|
||||
style={{ width: widths?.select || 230 }}
|
||||
size="large"
|
||||
onChange={handleSelectChange}
|
||||
options={selectOptions}
|
||||
></BaseSelect>
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||
onClick={handleSearch}
|
||||
icon={<SyncOutlined></SyncOutlined>}
|
||||
></Button>
|
||||
</Space>
|
||||
}
|
||||
right={right || renderRight}
|
||||
left={left || renderLeft()}
|
||||
right={right || renderRight()}
|
||||
></PageTools>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,5 +22,9 @@ export default {
|
||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||
'benchmark.form.profile.custom': 'Custom',
|
||||
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length'
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||
'benchmark.detail.summary.title': 'Summary',
|
||||
'benchmark.detail.configure.title': 'Configure',
|
||||
'benchmark.detail.environment.title': 'Environment',
|
||||
'benchmark.detail.logs.title': 'Logs'
|
||||
};
|
||||
|
||||
@@ -22,5 +22,9 @@ export default {
|
||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||
'benchmark.form.profile.custom': 'Custom',
|
||||
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length'
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||
'benchmark.detail.summary.title': 'Summary',
|
||||
'benchmark.detail.configure.title': 'Configure',
|
||||
'benchmark.detail.environment.title': 'Environment',
|
||||
'benchmark.detail.logs.title': 'Logs'
|
||||
};
|
||||
|
||||
@@ -22,5 +22,9 @@ export default {
|
||||
'benchmark.form.profile.heavy': 'Generation Heavy',
|
||||
'benchmark.form.profile.custom': 'Custom',
|
||||
'benchmark.table.inputTokenLength': 'Input Token Length',
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length'
|
||||
'benchmark.table.outputTokenLength': 'Output Token Length',
|
||||
'benchmark.detail.summary.title': 'Summary',
|
||||
'benchmark.detail.configure.title': 'Configure',
|
||||
'benchmark.detail.environment.title': 'Environment',
|
||||
'benchmark.detail.logs.title': 'Logs'
|
||||
};
|
||||
|
||||
@@ -22,5 +22,9 @@ export default {
|
||||
'benchmark.form.profile.heavy': '高生成量',
|
||||
'benchmark.form.profile.custom': '自定义',
|
||||
'benchmark.table.inputTokenLength': '输入 Token 长度',
|
||||
'benchmark.table.outputTokenLength': '输出 Token 长度'
|
||||
'benchmark.table.outputTokenLength': '输出 Token 长度',
|
||||
'benchmark.detail.summary.title': '摘要',
|
||||
'benchmark.detail.configure.title': '配置',
|
||||
'benchmark.detail.environment.title': '环境',
|
||||
'benchmark.detail.logs.title': '日志'
|
||||
};
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { useHover } from 'ahooks';
|
||||
import { Popover } from 'antd';
|
||||
import { useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid var(--ant-color-border);
|
||||
border-radius: 4px;
|
||||
padding: 8.5px 11px;
|
||||
height: 40px;
|
||||
width: 240px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
border-color: var(--ant-color-primary-hover);
|
||||
}
|
||||
&:active {
|
||||
box-shadow: var(--ant-input-active-shadow);
|
||||
}
|
||||
.holder {
|
||||
color: var(--ant-color-text-placeholder);
|
||||
}
|
||||
`;
|
||||
const CompareConditions: React.FC = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const isHovering = useHover(containerRef);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
trigger={'click'}
|
||||
content="Compare Conditions Content"
|
||||
arrow={false}
|
||||
placement="bottom"
|
||||
styles={{
|
||||
root: {
|
||||
width: '240px'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Container>
|
||||
<span className="holder">Compare Filter</span>
|
||||
</Container>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompareConditions;
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
|
||||
const Configure: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
return <div>Configure Content</div>;
|
||||
};
|
||||
|
||||
export default Configure;
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
|
||||
const Environment: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
return <div>Environment Content</div>;
|
||||
};
|
||||
|
||||
export default Environment;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Input, Space } from 'antd';
|
||||
import React from 'react';
|
||||
import CompareConditions from './compare-conditions';
|
||||
|
||||
export interface RightActionsProps {
|
||||
handleInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const RightActions: React.FC<RightActionsProps> = ({
|
||||
handleInputChange,
|
||||
handleSearch
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Space>
|
||||
<Input
|
||||
prefix={
|
||||
<SearchOutlined
|
||||
style={{ color: 'var(--ant-color-text-placeholder)' }}
|
||||
></SearchOutlined>
|
||||
}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'common.filter.name'
|
||||
})}
|
||||
style={{ width: 230 }}
|
||||
allowClear
|
||||
onChange={handleInputChange}
|
||||
></Input>
|
||||
<CompareConditions></CompareConditions>
|
||||
<Button
|
||||
type="text"
|
||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||
onClick={handleSearch}
|
||||
icon={<SyncOutlined></SyncOutlined>}
|
||||
></Button>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default RightActions;
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
|
||||
const Logs: React.FC = () => {
|
||||
const { id } = useDetailContext();
|
||||
return <div>Logs Content</div>;
|
||||
};
|
||||
|
||||
export default Logs;
|
||||
@@ -11,7 +11,6 @@ export interface RightActionsProps {
|
||||
handleDeleteByBatch: () => void;
|
||||
handleClickPrimary?: () => void;
|
||||
handleSettingFields?: () => void;
|
||||
handleCompare?: () => void;
|
||||
buttonText?: string;
|
||||
rowSelection: {
|
||||
selectedRowKeys: React.Key[];
|
||||
@@ -21,7 +20,6 @@ export interface RightActionsProps {
|
||||
const RightActions: React.FC<RightActionsProps> = ({
|
||||
handleDeleteByBatch,
|
||||
handleClickPrimary,
|
||||
handleCompare,
|
||||
handleSettingFields,
|
||||
buttonText,
|
||||
rowSelection
|
||||
@@ -31,9 +29,6 @@ const RightActions: React.FC<RightActionsProps> = ({
|
||||
return (
|
||||
<Space size={16}>
|
||||
<Button onClick={handleSettingFields} icon={<SettingOutlined />}></Button>
|
||||
<Button variant="solid" color="orange" onClick={handleCompare}>
|
||||
Compare
|
||||
</Button>
|
||||
<Button
|
||||
icon={<PlusOutlined></PlusOutlined>}
|
||||
type="primary"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { useDetailContext } from '../../config/detail-context';
|
||||
|
||||
const Summary: React.FC = () => {
|
||||
const { detailData } = useDetailContext();
|
||||
return <div>Summary Content</div>;
|
||||
};
|
||||
|
||||
export default Summary;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
interface DetailContextProps {
|
||||
detailData: any;
|
||||
id: number;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const DetailContext = createContext<DetailContextProps>(
|
||||
{} as DetailContextProps
|
||||
);
|
||||
|
||||
export const useDetailContext = () => {
|
||||
const context = useContext(DetailContext);
|
||||
if (!context) {
|
||||
throw new Error('useDetailContext must be used within a DetailProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export default DetailContext;
|
||||
@@ -0,0 +1,56 @@
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Tabs, TabsProps } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import PageBox from '../_components/page-box';
|
||||
import Configure from './components/configure';
|
||||
import Environment from './components/environment';
|
||||
import Logs from './components/logs';
|
||||
import Summary from './components/summary';
|
||||
import DetailContext from './config/detail-context';
|
||||
|
||||
const Details: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const [activeKey, setActiveKey] = useState('summary');
|
||||
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
key: 'summary',
|
||||
label: intl.formatMessage({ id: 'benchmark.detail.summary.title' }),
|
||||
children: <Summary />
|
||||
},
|
||||
{
|
||||
key: 'configure',
|
||||
label: intl.formatMessage({ id: 'benchmark.detail.configure.title' }),
|
||||
children: <Configure />
|
||||
},
|
||||
{
|
||||
key: 'environment',
|
||||
label: intl.formatMessage({ id: 'benchmark.detail.environment.title' }),
|
||||
children: <Environment />
|
||||
},
|
||||
{
|
||||
key: 'logs',
|
||||
label: intl.formatMessage({ id: 'benchmark.detail.logs.title' }),
|
||||
children: <Logs />
|
||||
}
|
||||
];
|
||||
|
||||
const handleChangeTab = (key: string) => {
|
||||
setActiveKey(key);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageBox>
|
||||
<DetailContext.Provider value={{}}>
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
onChange={handleChangeTab}
|
||||
items={items}
|
||||
type="card"
|
||||
/>
|
||||
</DetailContext.Provider>
|
||||
</PageBox>
|
||||
);
|
||||
};
|
||||
|
||||
export default Details;
|
||||
@@ -0,0 +1,3 @@
|
||||
const useCompareConditions = () => {};
|
||||
|
||||
export default useCompareConditions;
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
updateBenchmark
|
||||
} from './apis';
|
||||
import AddBenchmarkModal from './components/add-benchmark-modal';
|
||||
import LeftActions from './components/left-actions';
|
||||
import RightActions from './components/right-actions';
|
||||
import { FormData, BenchmarkListItem as ListItem } from './config/types';
|
||||
import useBenchmarkColumns from './hooks/use-benchmark-columns';
|
||||
@@ -123,6 +124,12 @@ const Benchmark: React.FC = () => {
|
||||
handleInputChange={handleNameChange}
|
||||
rowSelection={rowSelection}
|
||||
widths={{ input: 300 }}
|
||||
left={
|
||||
<LeftActions
|
||||
handleSearch={handleSearch}
|
||||
handleInputChange={handleNameChange}
|
||||
></LeftActions>
|
||||
}
|
||||
right={
|
||||
<RightActions
|
||||
handleDeleteByBatch={handleDeleteBatch}
|
||||
|
||||
Reference in New Issue
Block a user