mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-15 01:18:26 +08:00
Feat: Adjust the timeline style. (#16894)
### Summary Feat: Adjust the timeline style.
This commit is contained in:
@@ -2,7 +2,6 @@ import {
|
||||
useFetchNextChunkList,
|
||||
useSwitchChunk,
|
||||
} from '@/hooks/use-chunk-request';
|
||||
import classNames from 'classnames';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ChunkCard from './components/chunk-card';
|
||||
@@ -29,13 +28,17 @@ import {
|
||||
RAGFlowPagination,
|
||||
RAGFlowPaginationType,
|
||||
} from '@/components/ui/ragflow-pagination';
|
||||
import {
|
||||
ResizableHandle,
|
||||
ResizablePanel,
|
||||
ResizablePanelGroup,
|
||||
} from '@/components/ui/resizable';
|
||||
import { Spin } from '@/components/ui/spin';
|
||||
import {
|
||||
QueryStringMap,
|
||||
useNavigatePage,
|
||||
} from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { LucideArrowBigLeft } from 'lucide-react';
|
||||
import styles from './index.module.less';
|
||||
|
||||
function Chunk() {
|
||||
const [filterChunkIds, setFilterChunkIds] = useState<string[]>([]);
|
||||
@@ -52,7 +55,6 @@ function Chunk() {
|
||||
dataUpdatedAt,
|
||||
} = useFetchNextChunkList(true, { chunkIds: filterChunkIds });
|
||||
const { handleChunkCardClick, selectedChunkId } = useHandleChunkCardClick();
|
||||
const isPdf = documentInfo?.type === 'pdf';
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { changeChunkTextMode, textMode } = useChangeChunkTextMode();
|
||||
@@ -197,93 +199,99 @@ function Chunk() {
|
||||
|
||||
<Card className="mx-5 mb-5 flex-1 h-0 p-0 bg-transparent shadow-none">
|
||||
<CardContent className="p-0 h-full flex flex-row divide-x-0.5 rtl:divide-x-reverse">
|
||||
<article className="w-2/5 flex flex-col">
|
||||
<DocumentViewSwitch
|
||||
documentInfo={documentInfo}
|
||||
fileType={fileType}
|
||||
highlights={highlights}
|
||||
setWidthAndHeight={setWidthAndHeight}
|
||||
url={fileUrl}
|
||||
onChunkIdsChange={handleChunkIdsChange}
|
||||
<ResizablePanelGroup direction="horizontal" className="flex-1">
|
||||
<ResizablePanel defaultSize={40} minSize={30}>
|
||||
<article className="h-full flex flex-col">
|
||||
<DocumentViewSwitch
|
||||
documentInfo={documentInfo}
|
||||
fileType={fileType}
|
||||
highlights={highlights}
|
||||
setWidthAndHeight={setWidthAndHeight}
|
||||
url={fileUrl}
|
||||
onChunkIdsChange={handleChunkIdsChange}
|
||||
/>
|
||||
</article>
|
||||
</ResizablePanel>
|
||||
|
||||
<ResizableHandle
|
||||
withHandle
|
||||
className="bg-border-button w-[0.5px]"
|
||||
/>
|
||||
</article>
|
||||
|
||||
<article
|
||||
className={classNames(
|
||||
{ [styles.pagePdfWrapper]: isPdf },
|
||||
'flex flex-col w-3/5',
|
||||
)}
|
||||
>
|
||||
<header className="flex-0 p-5 pb-2.5 border-b-0.5 border-b-border-button">
|
||||
<h2 className="text-[24px]">{t('chunk.chunkResult')}</h2>
|
||||
<div className="text-[14px] text-text-secondary">
|
||||
{t('chunk.chunkResultTip')}
|
||||
</div>
|
||||
</header>
|
||||
<ResizablePanel defaultSize={60} minSize={30}>
|
||||
<article className="h-full flex flex-col">
|
||||
<header className="flex-0 p-5 pb-2.5 border-b-0.5 border-b-border-button">
|
||||
<h2 className="text-[24px]">{t('chunk.chunkResult')}</h2>
|
||||
<div className="text-[14px] text-text-secondary">
|
||||
{t('chunk.chunkResultTip')}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<Spin spinning={loading} className="flex-1 h-0" size="large">
|
||||
<div className="relative @container h-full px-5 pb-5 overflow-hidden flex flex-col">
|
||||
<div
|
||||
className="
|
||||
sticky top-0 z-[1] bg-bg-base space-y-4 py-5
|
||||
@4xl:flex @4xl:justify-between @4xl:items-center
|
||||
@4xl:space-y-0 @4xl:gap-4
|
||||
"
|
||||
role="toolbar"
|
||||
>
|
||||
<ChunkResultBar
|
||||
className="@4xl:order-2"
|
||||
handleInputChange={handleInputChange}
|
||||
searchString={searchString}
|
||||
changeChunkTextMode={changeChunkTextMode}
|
||||
createChunk={showChunkUpdatingModal}
|
||||
available={available}
|
||||
selectAllChunk={selectAllChunk}
|
||||
handleSetAvailable={handleSetAvailable}
|
||||
/>
|
||||
<Spin spinning={loading} className="flex-1 h-0" size="large">
|
||||
<div className="relative @container h-full px-5 pb-5 overflow-hidden flex flex-col">
|
||||
<div
|
||||
className="
|
||||
sticky top-0 z-[1] bg-bg-base space-y-4 py-5
|
||||
@4xl:flex @4xl:justify-between @4xl:items-center
|
||||
@4xl:space-y-0 @4xl:gap-4
|
||||
"
|
||||
role="toolbar"
|
||||
>
|
||||
<ChunkResultBar
|
||||
className="@4xl:order-2"
|
||||
handleInputChange={handleInputChange}
|
||||
searchString={searchString}
|
||||
changeChunkTextMode={changeChunkTextMode}
|
||||
createChunk={showChunkUpdatingModal}
|
||||
available={available}
|
||||
selectAllChunk={selectAllChunk}
|
||||
handleSetAvailable={handleSetAvailable}
|
||||
/>
|
||||
|
||||
<CheckboxSets
|
||||
className="h-8"
|
||||
selectAllChunk={selectAllChunk}
|
||||
switchChunk={handleSwitchChunk}
|
||||
removeChunk={handleRemoveChunk}
|
||||
checked={selectedChunkIds.length === data.length}
|
||||
selectedChunkIds={selectedChunkIds}
|
||||
/>
|
||||
</div>
|
||||
<CheckboxSets
|
||||
className="h-8"
|
||||
selectAllChunk={selectAllChunk}
|
||||
switchChunk={handleSwitchChunk}
|
||||
removeChunk={handleRemoveChunk}
|
||||
checked={selectedChunkIds.length === data.length}
|
||||
selectedChunkIds={selectedChunkIds}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 flex-1 overflow-y-auto min-h-0">
|
||||
{chunkList.map((item) => (
|
||||
<ChunkCard
|
||||
item={item}
|
||||
key={item.chunk_id}
|
||||
editChunk={showChunkUpdatingModal}
|
||||
checked={selectedChunkIds.some(
|
||||
(x) => x === item.chunk_id,
|
||||
)}
|
||||
handleCheckboxClick={handleSingleCheckboxClick}
|
||||
switchChunk={handleSwitchChunk}
|
||||
clickChunkCard={handleChunkCardClick}
|
||||
selected={item.chunk_id === selectedChunkId}
|
||||
textMode={textMode}
|
||||
t={dataUpdatedAt}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="space-y-4 flex-1 overflow-y-auto min-h-0">
|
||||
{chunkList.map((item) => (
|
||||
<ChunkCard
|
||||
item={item}
|
||||
key={item.chunk_id}
|
||||
editChunk={showChunkUpdatingModal}
|
||||
checked={selectedChunkIds.some(
|
||||
(x) => x === item.chunk_id,
|
||||
)}
|
||||
handleCheckboxClick={handleSingleCheckboxClick}
|
||||
switchChunk={handleSwitchChunk}
|
||||
clickChunkCard={handleChunkCardClick}
|
||||
selected={item.chunk_id === selectedChunkId}
|
||||
textMode={textMode}
|
||||
t={dataUpdatedAt}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<footer className="mt-5">
|
||||
<RAGFlowPagination
|
||||
pageSize={pagination.pageSize}
|
||||
current={pagination.current}
|
||||
total={total}
|
||||
onChange={(page, pageSize) => {
|
||||
onPaginationChange(page, pageSize);
|
||||
}}
|
||||
/>
|
||||
</footer>
|
||||
</div>
|
||||
</Spin>
|
||||
</article>
|
||||
<footer className="mt-5">
|
||||
<RAGFlowPagination
|
||||
pageSize={pagination.pageSize}
|
||||
current={pagination.current}
|
||||
total={total}
|
||||
onChange={(page, pageSize) => {
|
||||
onPaginationChange(page, pageSize);
|
||||
}}
|
||||
/>
|
||||
</footer>
|
||||
</div>
|
||||
</Spin>
|
||||
</article>
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { DagreLayout } from '@antv/layout';
|
||||
import { Graph, type EdgeMetadata, type NodeMetadata } from '@antv/x6';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import { type TimelineX6NodeData } from '../../../utils/adapters';
|
||||
import { type TimelineNodeValue, type TimelineX6GraphProps } from '../types';
|
||||
|
||||
export function useX6Graph(
|
||||
@@ -54,7 +55,6 @@ export function useX6Graph(
|
||||
const dagreLayout = new DagreLayout({
|
||||
type: 'dagre',
|
||||
rankdir: 'LR',
|
||||
align: 'UL',
|
||||
ranksep: 240,
|
||||
nodesep: 200,
|
||||
edgeMinLen: 2,
|
||||
@@ -70,10 +70,11 @@ export function useX6Graph(
|
||||
const positionedNodes = new Map<string, NodeMetadata>();
|
||||
|
||||
dagreLayout.forEachNode((node) => {
|
||||
const original = node._original as TimelineX6NodeData;
|
||||
positionedNodes.set(String(node.id), {
|
||||
...(node._original as NodeMetadata),
|
||||
x: node.x,
|
||||
y: node.y,
|
||||
x: (node.x ?? 0) - original.width / 2,
|
||||
y: (node.y ?? 0) - original.height / 2,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -185,20 +185,29 @@ export function adaptTimelineToX6Data(template: IStructureGraphTemplate): {
|
||||
return {
|
||||
id: entity.id,
|
||||
shape: isTimestamp ? ('circle' as const) : ('rect' as const),
|
||||
width: isTimestamp ? 96 : 200,
|
||||
height: isTimestamp ? 96 : 80,
|
||||
width: isTimestamp ? 40 : 200,
|
||||
height: isTimestamp ? 40 : 80,
|
||||
label: entity.name,
|
||||
data: entity,
|
||||
attrs: {
|
||||
body: {
|
||||
fill: isTimestamp ? '#e6f7ff' : '#fff7e6',
|
||||
stroke: isTimestamp ? '#1890ff' : '#fa8c16',
|
||||
fill: isTimestamp ? 'rgb(var(--accent-primary))' : 'transparent',
|
||||
stroke: 'rgb(var(--accent-primary))',
|
||||
rx: isTimestamp ? 48 : 8,
|
||||
ry: isTimestamp ? 48 : 8,
|
||||
},
|
||||
label: {
|
||||
fill: '#262626',
|
||||
fill: isTimestamp
|
||||
? 'rgb(var(--accent-primary))'
|
||||
: 'rgb(var(--text-primary))',
|
||||
fontSize: 12,
|
||||
...(isTimestamp && {
|
||||
refX: '50%',
|
||||
refY: 0,
|
||||
refY2: -8,
|
||||
textAnchor: 'middle',
|
||||
textVerticalAnchor: 'bottom',
|
||||
}),
|
||||
textWrap: {
|
||||
width: isTimestamp ? 80 : 180,
|
||||
height: isTimestamp ? 80 : 64,
|
||||
|
||||
@@ -152,7 +152,7 @@ export function TemplateSidebar({
|
||||
<span className="text-sm font-medium text-text-primary">
|
||||
{t('setting.templates')}
|
||||
</span>
|
||||
{!isAddButtonHidden && (
|
||||
{false && !isAddButtonHidden && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
|
||||
Reference in New Issue
Block a user