mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
feat: add SelectFiles and add KnowledgeTesting (#60)
* feat: add KnowledgeTesting * feat: add SelectFiles
This commit is contained in:
@ -6,7 +6,7 @@ import { getWidth } from '@/utils';
|
||||
import { AntDesignOutlined } from '@ant-design/icons';
|
||||
import { Avatar, Menu, MenuProps, Space } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useNavigate, useSelector } from 'umi';
|
||||
import { KnowledgeRouteKey, routeMap } from '../../constant';
|
||||
import styles from './index.less';
|
||||
@ -26,23 +26,27 @@ const KnowledgeSidebar = () => {
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
disabled?: boolean,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
disabled,
|
||||
} as MenuItem;
|
||||
}
|
||||
const getItem = useCallback(
|
||||
(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
disabled?: boolean,
|
||||
children?: MenuItem[],
|
||||
type?: 'group',
|
||||
): MenuItem => {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
type,
|
||||
disabled,
|
||||
} as MenuItem;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const items: MenuItem[] = useMemo(() => {
|
||||
return [
|
||||
getItem(
|
||||
@ -60,8 +64,13 @@ const KnowledgeSidebar = () => {
|
||||
KnowledgeRouteKey.Configuration,
|
||||
<ConfigrationIcon />,
|
||||
),
|
||||
getItem(
|
||||
routeMap[KnowledgeRouteKey.TempTesting],
|
||||
KnowledgeRouteKey.TempTesting,
|
||||
<TestingIcon />,
|
||||
),
|
||||
];
|
||||
}, [id]);
|
||||
}, [getItem]);
|
||||
|
||||
useEffect(() => {
|
||||
if (windowWidth.width > 957) {
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
.testingWrapper {
|
||||
flex: 1;
|
||||
background-color: @grayBackground;
|
||||
height: 100%;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import { Flex } from 'antd';
|
||||
import TestingControl from './testing-control';
|
||||
import TestingResult from './testing-result';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
const KnowledgeTesting = () => {
|
||||
return (
|
||||
<Flex className={styles.testingWrapper} gap={16}>
|
||||
<TestingControl></TestingControl>
|
||||
<TestingResult></TestingResult>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default KnowledgeTesting;
|
||||
@ -0,0 +1,26 @@
|
||||
.testingControlWrapper {
|
||||
width: 350px;
|
||||
background-color: white;
|
||||
padding: 30px 20px;
|
||||
.historyTitle {
|
||||
padding: 30px 0 20px;
|
||||
}
|
||||
.historyIcon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.historyCardWrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.historyCard {
|
||||
width: 100%;
|
||||
:global(.ant-card-body) {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
.historyText {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Divider,
|
||||
Flex,
|
||||
Input,
|
||||
Slider,
|
||||
SliderSingleProps,
|
||||
Space,
|
||||
Tag,
|
||||
} from 'antd';
|
||||
|
||||
import { DeleteOutlined, HistoryOutlined } from '@ant-design/icons';
|
||||
import styles from './index.less';
|
||||
|
||||
const list = [1, 2, 3];
|
||||
|
||||
const marks: SliderSingleProps['marks'] = {
|
||||
0: '0°C',
|
||||
26: '26°C',
|
||||
37: '37°C',
|
||||
100: {
|
||||
style: {
|
||||
color: '#f50',
|
||||
},
|
||||
label: <strong>100°C</strong>,
|
||||
},
|
||||
};
|
||||
|
||||
const TestingControl = () => {
|
||||
return (
|
||||
<section className={styles.testingControlWrapper}>
|
||||
<p>
|
||||
<b>Retrieval testing</b>
|
||||
</p>
|
||||
<p>xxxx</p>
|
||||
<Divider></Divider>
|
||||
<section>
|
||||
<Slider range marks={marks} defaultValue={[26, 37]} />
|
||||
<Slider range marks={marks} defaultValue={[26, 37]} />
|
||||
<Card
|
||||
size="small"
|
||||
title="Test text"
|
||||
extra={
|
||||
<Button type="primary" ghost>
|
||||
Semantic Search
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Input.TextArea autoSize={{ minRows: 8 }}></Input.TextArea>
|
||||
<Flex justify={'space-between'}>
|
||||
<Tag>10/200</Tag>
|
||||
<Button type="primary" size="small">
|
||||
Testing
|
||||
</Button>
|
||||
</Flex>
|
||||
</Card>
|
||||
</section>
|
||||
<section>
|
||||
<p className={styles.historyTitle}>
|
||||
<Space size={'middle'}>
|
||||
<HistoryOutlined className={styles.historyIcon} />
|
||||
<b>Test history</b>
|
||||
</Space>
|
||||
</p>
|
||||
<Space
|
||||
direction="vertical"
|
||||
size={'middle'}
|
||||
className={styles.historyCardWrapper}
|
||||
>
|
||||
{list.map((x) => (
|
||||
<Card className={styles.historyCard} key={x}>
|
||||
<Flex justify={'space-between'} gap={'small'}>
|
||||
<span>{x}</span>
|
||||
<div className={styles.historyText}>
|
||||
content dcjsjl snldsh svnodvn svnodrfn svjdoghdtbnhdo
|
||||
sdvhodhbuid sldghdrlh
|
||||
</div>
|
||||
<Flex gap={'small'}>
|
||||
<span>time</span>
|
||||
<DeleteOutlined></DeleteOutlined>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
))}
|
||||
</Space>
|
||||
</section>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestingControl;
|
||||
@ -0,0 +1,16 @@
|
||||
.testingResultWrapper {
|
||||
flex: 1;
|
||||
background-color: white;
|
||||
padding: 30px 20px;
|
||||
|
||||
.selectFilesCollapse {
|
||||
:global(.ant-collapse-header) {
|
||||
padding-left: 22px;
|
||||
}
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.selectFilesTitle {
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
import { ReactComponent as SelectedFilesCollapseIcon } from '@/assets/svg/selected-files-collapse.svg';
|
||||
import { Card, Collapse, Flex, Space } from 'antd';
|
||||
import SelectFiles from './select-files';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
const list = [1, 2, 3, 4];
|
||||
|
||||
const TestingResult = () => {
|
||||
return (
|
||||
<section className={styles.testingResultWrapper}>
|
||||
<Collapse
|
||||
expandIcon={() => (
|
||||
<SelectedFilesCollapseIcon></SelectedFilesCollapseIcon>
|
||||
)}
|
||||
className={styles.selectFilesCollapse}
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
<Flex
|
||||
justify={'space-between'}
|
||||
align="center"
|
||||
className={styles.selectFilesTitle}
|
||||
>
|
||||
<span>4/25 Files Selected</span>
|
||||
<Space size={52}>
|
||||
<b>Hits</b>
|
||||
<b>View</b>
|
||||
</Space>
|
||||
</Flex>
|
||||
),
|
||||
children: (
|
||||
<div>
|
||||
<SelectFiles></SelectFiles>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Flex gap={'large'} vertical>
|
||||
{list.map((x) => (
|
||||
<Card key={x} title="Default size card" extra={<a href="#">More</a>}>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
))}
|
||||
</Flex>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestingResult;
|
||||
@ -0,0 +1,82 @@
|
||||
import { ReactComponent as NavigationPointerIcon } from '@/assets/svg/navigation-pointer.svg';
|
||||
import { Table, TableProps } from 'antd';
|
||||
|
||||
interface DataType {
|
||||
key: string;
|
||||
name: string;
|
||||
hits: number;
|
||||
address: string;
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
const SelectFiles = () => {
|
||||
const columns: TableProps<DataType>['columns'] = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: (text) => <p>{text}</p>,
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Hits',
|
||||
dataIndex: 'hits',
|
||||
key: 'hits',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: 'View',
|
||||
key: 'view',
|
||||
width: 50,
|
||||
render: () => <NavigationPointerIcon />,
|
||||
},
|
||||
];
|
||||
|
||||
const rowSelection = {
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => {
|
||||
console.log(
|
||||
`selectedRowKeys: ${selectedRowKeys}`,
|
||||
'selectedRows: ',
|
||||
selectedRows,
|
||||
);
|
||||
},
|
||||
getCheckboxProps: (record: DataType) => ({
|
||||
disabled: record.name === 'Disabled User', // Column configuration not to be checked
|
||||
name: record.name,
|
||||
}),
|
||||
};
|
||||
|
||||
const data: DataType[] = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
hits: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
tags: ['nice', 'developer'],
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
hits: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
tags: ['loser'],
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
hits: 32,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
tags: ['cool', 'teacher'],
|
||||
},
|
||||
];
|
||||
return (
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
showHeader={false}
|
||||
rowSelection={rowSelection}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectFiles;
|
||||
@ -4,6 +4,7 @@ export const routeMap = {
|
||||
[KnowledgeRouteKey.Dataset]: 'Dataset',
|
||||
[KnowledgeRouteKey.Testing]: 'Retrieval testing',
|
||||
[KnowledgeRouteKey.Configuration]: 'Configuration',
|
||||
[KnowledgeRouteKey.TempTesting]: 'Testing',
|
||||
};
|
||||
|
||||
export enum KnowledgeDatasetRouteKey {
|
||||
|
||||
Reference in New Issue
Block a user