mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Fix: Optimized the test results page layout and internationalization - Added an empty data component for when test results are empty - Optimized internationalization support for the paging component - Updated the layout and style of the test results page - Added a tooltip for when test results are empty ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
77
web/src/components/empty/empty.tsx
Normal file
77
web/src/components/empty/empty.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { t } from 'i18next';
|
||||
|
||||
type EmptyProps = {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const EmptyIcon = () => (
|
||||
<svg
|
||||
width="184"
|
||||
height="152"
|
||||
viewBox="0 0 184 152"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>{t('common.noData')}</title>
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<g transform="translate(24 31.67)">
|
||||
<ellipse
|
||||
fillOpacity=".8"
|
||||
fill="#F5F5F7"
|
||||
cx="67.797"
|
||||
cy="106.89"
|
||||
rx="67.797"
|
||||
ry="12.668"
|
||||
></ellipse>
|
||||
<path
|
||||
d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
|
||||
fill="#AEB8C2"
|
||||
></path>
|
||||
<path
|
||||
d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
|
||||
fill="url(#linearGradient-1)"
|
||||
transform="translate(13.56)"
|
||||
></path>
|
||||
<path
|
||||
d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
|
||||
fill="#F5F5F7"
|
||||
></path>
|
||||
<path
|
||||
d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
|
||||
fill="#DCE0E6"
|
||||
></path>
|
||||
</g>
|
||||
<path
|
||||
d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
|
||||
fill="#DCE0E6"
|
||||
></path>
|
||||
<g transform="translate(149.65 15.383)" fill="#FFF">
|
||||
<ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse>
|
||||
<path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const Empty = (props: EmptyProps) => {
|
||||
const { className, children } = props;
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col justify-center items-center text-center gap-3',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<EmptyIcon />
|
||||
{!children && (
|
||||
<div className="empty-text mt-4 text-text-secondary">
|
||||
{t('common.noData')}
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Empty;
|
||||
@ -9,6 +9,7 @@ import {
|
||||
} from '@/components/ui/pagination';
|
||||
import { RAGFlowSelect, RAGFlowSelectOptionType } from '@/components/ui/select';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { t } from 'i18next';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
export type RAGFlowPaginationType = {
|
||||
@ -32,7 +33,11 @@ export function RAGFlowPagination({
|
||||
|
||||
const sizeChangerOptions: RAGFlowSelectOptionType[] = useMemo(() => {
|
||||
return [10, 20, 50, 100].map((x) => ({
|
||||
label: <span>{x} / page</span>,
|
||||
label: (
|
||||
<span>
|
||||
{x} / {t('pagination.page')}
|
||||
</span>
|
||||
),
|
||||
value: x.toString(),
|
||||
}));
|
||||
}, []);
|
||||
@ -134,7 +139,7 @@ export function RAGFlowPagination({
|
||||
|
||||
return (
|
||||
<section className="flex items-center justify-end text-text-sub-title-invert">
|
||||
<span className="mr-4">Total {total}</span>
|
||||
<span className="mr-4">{t('pagination.total', { total: total })}</span>
|
||||
<Pagination className="w-auto mx-0 mr-4">
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
|
||||
@ -72,12 +72,14 @@ export const useTestRetrieval = () => {
|
||||
chunks: [],
|
||||
doc_aggs: [],
|
||||
total: 0,
|
||||
isRuned: false,
|
||||
},
|
||||
enabled: false,
|
||||
gcTime: 0,
|
||||
queryFn: async () => {
|
||||
const { data } = await kbService.retrieval_test(queryParams);
|
||||
return data?.data ?? {};
|
||||
const result = data?.data ?? {};
|
||||
return { ...result, isRuned: true };
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -150,6 +150,7 @@ export interface INextTestingResult {
|
||||
doc_aggs: ITestingDocument[];
|
||||
total: number;
|
||||
labels?: Record<string, number>;
|
||||
isRuned?: boolean;
|
||||
}
|
||||
|
||||
export type IRenameTag = { fromTag: string; toTag: string };
|
||||
|
||||
@ -46,6 +46,7 @@ export default {
|
||||
remove: 'Remove',
|
||||
search: 'Search',
|
||||
noDataFound: 'No data found.',
|
||||
noData: 'No data',
|
||||
promptPlaceholder: `Please input or use / to quickly insert variables.`,
|
||||
mcp: {
|
||||
namePlaceholder: 'My MCP Server',
|
||||
@ -138,6 +139,10 @@ export default {
|
||||
processBeginAt: 'Begin at',
|
||||
processDuration: 'Duration',
|
||||
progressMsg: 'Progress',
|
||||
noTestResultsForRuned:
|
||||
'No relevant results found. Try adjusting your query or parameters.',
|
||||
noTestResultsForNotRuned:
|
||||
'No test has been run yet. Results will appear here.',
|
||||
testingDescription:
|
||||
'Conduct a retrieval test to check if RAGFlow can recover the intended content for the LLM. If you have adjusted the default settings, such as keyword similarity weight or similarity threshold, to achieve the optimal results, be aware that these changes will not be automatically saved. You must apply them to your chat assistant settings or the Retrieval agent component settings.',
|
||||
similarityThreshold: 'Similarity threshold',
|
||||
@ -1579,5 +1584,9 @@ This delimiter is used to split the input text into several text pieces echo of
|
||||
korean: 'Korean',
|
||||
vietnamese: 'Vietnamese',
|
||||
},
|
||||
pagination: {
|
||||
total: 'Total {{total}}',
|
||||
page: 'Page',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -45,6 +45,7 @@ export default {
|
||||
remove: '移除',
|
||||
search: '搜索',
|
||||
noDataFound: '没有找到数据。',
|
||||
noData: '暂无数据',
|
||||
promptPlaceholder: '请输入或使用 / 快速插入变量。',
|
||||
},
|
||||
login: {
|
||||
@ -129,6 +130,8 @@ export default {
|
||||
processBeginAt: '开始于',
|
||||
processDuration: '持续时间',
|
||||
progressMsg: '进度',
|
||||
noTestResultsForRuned: '未找到相关结果,请尝试调整查询语句或参数',
|
||||
noTestResultsForNotRuned: '尚未运行测试,结果会显示在这里',
|
||||
testingDescription:
|
||||
'请完成召回测试:确保你的配置可以从数据库召回正确的文本块。如果你调整了这里的默认设置,比如关键词相似度权重,请注意这里的改动不会被自动保存。请务必在聊天助手设置或者召回算子设置处同步更新相关设置。',
|
||||
similarityThreshold: '相似度阈值',
|
||||
@ -1493,5 +1496,9 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
||||
korean: '韩语',
|
||||
vietnamese: '越南语',
|
||||
},
|
||||
pagination: {
|
||||
total: '总共 {{total}} 条',
|
||||
page: '页',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -67,7 +67,7 @@ export function ParsingStatusCell({
|
||||
|
||||
return (
|
||||
<section className="flex gap-8 items-center">
|
||||
<div className="w-fit flex items-center justify-between">
|
||||
<div className="w-[100px] text-ellipsis overflow-hidden flex items-center justify-between">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant={'transparent'} className="border-none" size={'sm'}>
|
||||
|
||||
@ -25,7 +25,7 @@ export default function RetrievalTesting() {
|
||||
<section className="flex justify-between items-center">
|
||||
<TopTitle
|
||||
title={t('knowledgeDetails.retrievalTesting')}
|
||||
description={t('knowledgeDetails.retrievalTestingDescription')}
|
||||
description={t('knowledgeDetails.testingDescription')}
|
||||
></TopTitle>
|
||||
{/* <Button>Save as Preset</Button> */}
|
||||
</section>
|
||||
@ -51,6 +51,7 @@ export default function RetrievalTesting() {
|
||||
<TestingResult
|
||||
data={data}
|
||||
page={page}
|
||||
loading={loading}
|
||||
pageSize={pageSize}
|
||||
filterValue={filterValue}
|
||||
handleFilterSubmit={handleFilterSubmit}
|
||||
@ -68,6 +69,7 @@ export default function RetrievalTesting() {
|
||||
<TestingResult
|
||||
data={data}
|
||||
page={page}
|
||||
loading={loading}
|
||||
pageSize={pageSize}
|
||||
filterValue={filterValue}
|
||||
handleFilterSubmit={handleFilterSubmit}
|
||||
@ -83,6 +85,7 @@ export default function RetrievalTesting() {
|
||||
<TestingResult
|
||||
data={data}
|
||||
page={page}
|
||||
loading={loading}
|
||||
pageSize={pageSize}
|
||||
filterValue={filterValue}
|
||||
handleFilterSubmit={handleFilterSubmit}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import Empty from '@/components/empty/empty';
|
||||
import { FormContainer } from '@/components/form-container';
|
||||
import { FilterButton } from '@/components/list-filter-bar';
|
||||
import { FilterPopover } from '@/components/list-filter-bar/filter-popover';
|
||||
@ -38,6 +39,7 @@ type TestingResultProps = Pick<
|
||||
| 'page'
|
||||
| 'pageSize'
|
||||
| 'onPaginationChange'
|
||||
| 'loading'
|
||||
>;
|
||||
|
||||
export function TestingResult({
|
||||
@ -45,6 +47,7 @@ export function TestingResult({
|
||||
handleFilterSubmit,
|
||||
page,
|
||||
pageSize,
|
||||
loading,
|
||||
onPaginationChange,
|
||||
data,
|
||||
}: TestingResultProps) {
|
||||
@ -77,20 +80,42 @@ export function TestingResult({
|
||||
<FilterButton></FilterButton>
|
||||
</FilterPopover>
|
||||
</div>
|
||||
<section className="flex flex-col gap-5 overflow-auto h-[calc(100vh-241px)] scrollbar-thin mb-5">
|
||||
{data.chunks?.map((x) => (
|
||||
<FormContainer key={x.chunk_id} className="px-5 py-2.5">
|
||||
<ChunkTitle item={x}></ChunkTitle>
|
||||
<p className="!mt-2.5"> {x.content_with_weight}</p>
|
||||
</FormContainer>
|
||||
))}
|
||||
</section>
|
||||
<RAGFlowPagination
|
||||
total={data.total}
|
||||
onChange={onPaginationChange}
|
||||
current={page}
|
||||
pageSize={pageSize}
|
||||
></RAGFlowPagination>
|
||||
{data.chunks?.length > 0 && !loading && (
|
||||
<>
|
||||
<section className="flex flex-col gap-5 overflow-auto h-[calc(100vh-241px)] scrollbar-thin mb-5">
|
||||
{data.chunks?.map((x) => (
|
||||
<FormContainer key={x.chunk_id} className="px-5 py-2.5">
|
||||
<ChunkTitle item={x}></ChunkTitle>
|
||||
<p className="!mt-2.5"> {x.content_with_weight}</p>
|
||||
</FormContainer>
|
||||
))}
|
||||
</section>
|
||||
<RAGFlowPagination
|
||||
total={data.total}
|
||||
onChange={onPaginationChange}
|
||||
current={page}
|
||||
pageSize={pageSize}
|
||||
></RAGFlowPagination>
|
||||
</>
|
||||
)}
|
||||
{!data.chunks?.length && !loading && (
|
||||
<div className="flex justify-center items-center w-full h-[calc(100vh-241px)]">
|
||||
<div>
|
||||
<Empty>
|
||||
{data.isRuned && (
|
||||
<div className="text-text-secondary">
|
||||
{t('knowledgeDetails.noTestResultsForRuned')}
|
||||
</div>
|
||||
)}
|
||||
{!data.isRuned && (
|
||||
<div className="text-text-secondary">
|
||||
{t('knowledgeDetails.noTestResultsForNotRuned')}
|
||||
</div>
|
||||
)}
|
||||
</Empty>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ export default function SearchingView({
|
||||
</div>
|
||||
|
||||
{total > 0 && (
|
||||
<div className="mt-8 px-8 pb-8">
|
||||
<div className="mt-8 px-8 pb-8 text-base">
|
||||
<RAGFlowPagination
|
||||
current={pagination.current}
|
||||
pageSize={pagination.pageSize}
|
||||
|
||||
Reference in New Issue
Block a user