feat: locate the specific location of the document based on the coordinates of the chunk and add Upload to AssistantSetting (#92)
* feat: add Upload to AssistantSetting * feat: locate the specific location of the document based on the coordinates of the chunk
This commit is contained in:
@@ -13,6 +13,28 @@
|
||||
color: red;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
caption {
|
||||
color: @blurBackground;
|
||||
font-size: 20px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
th {
|
||||
color: #fff;
|
||||
background-color: @blurBackground;
|
||||
}
|
||||
|
||||
td:hover {
|
||||
background: @blurBackgroundHover;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
}
|
||||
|
||||
.cardSelected {
|
||||
|
||||
@@ -64,9 +64,7 @@ const ChunkCard = ({
|
||||
onClick={handleContentClick}
|
||||
className={styles.content}
|
||||
dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
|
||||
>
|
||||
{/* {item.content_with_weight} */}
|
||||
</section>
|
||||
></section>
|
||||
<div>
|
||||
<Switch checked={enabled} onChange={onChange} />
|
||||
</div>
|
||||
|
||||
@@ -6,21 +6,27 @@ export const testHighlights = [
|
||||
position: {
|
||||
boundingRect: {
|
||||
x1: 219.7,
|
||||
// x1: 419.7,
|
||||
y1: 204.3,
|
||||
// y1: 304.3,
|
||||
x2: 547.0,
|
||||
// x2: 747.0,
|
||||
y2: 264.0,
|
||||
width: 849,
|
||||
height: 1200,
|
||||
// y2: 364.0,
|
||||
},
|
||||
rects: [
|
||||
{
|
||||
x1: 219.7,
|
||||
y1: 204.3,
|
||||
x2: 547.0,
|
||||
y2: 264.0,
|
||||
width: 849,
|
||||
height: 1200,
|
||||
},
|
||||
// {
|
||||
// x1: 219.7,
|
||||
// // x1: 419.7,
|
||||
// y1: 204.3,
|
||||
// // y1: 304.3,
|
||||
// x2: 547.0,
|
||||
// // x2: 747.0,
|
||||
// y2: 264.0,
|
||||
// // y2: 364.0,
|
||||
// width: 849,
|
||||
// height: 1200,
|
||||
// },
|
||||
],
|
||||
pageNumber: 9,
|
||||
},
|
||||
@@ -28,6 +34,56 @@ export const testHighlights = [
|
||||
text: 'Flow or TypeScript?',
|
||||
emoji: '🔥',
|
||||
},
|
||||
id: '8245652131754351',
|
||||
id: 'jsdlihdkghergjl',
|
||||
},
|
||||
];
|
||||
{
|
||||
content: {
|
||||
text: '图2:乘联会预计6 月新能源乘用车厂商批发销量74 万辆,环比增长10%,同比增长30%。',
|
||||
},
|
||||
position: {
|
||||
boundingRect: {
|
||||
x1: 219.0,
|
||||
x2: 546.0,
|
||||
y1: 616.0,
|
||||
y2: 674.7,
|
||||
},
|
||||
rects: [],
|
||||
pageNumber: 6,
|
||||
},
|
||||
comment: {
|
||||
text: 'Flow or TypeScript?',
|
||||
emoji: '🔥',
|
||||
},
|
||||
id: 'bfdbtymkhjildbfghserrgrt',
|
||||
},
|
||||
{
|
||||
content: {
|
||||
text: '图2:乘联会预计6 月新能源乘用车厂商批发销量74 万辆,环比增长10%,同比增长30%。',
|
||||
},
|
||||
position: {
|
||||
boundingRect: {
|
||||
x1: 73.7,
|
||||
x2: 391.7,
|
||||
y1: 570.3,
|
||||
y2: 676.3,
|
||||
},
|
||||
rects: [],
|
||||
pageNumber: 1,
|
||||
},
|
||||
comment: {
|
||||
text: '',
|
||||
emoji: '',
|
||||
},
|
||||
id: 'fgnhxdvsesgmghyu',
|
||||
},
|
||||
].map((x) => {
|
||||
const boundingRect = x.position.boundingRect;
|
||||
const ret: any = {
|
||||
width: 849,
|
||||
height: 1200,
|
||||
};
|
||||
Object.entries(boundingRect).forEach(([key, value]) => {
|
||||
ret[key] = value / 0.7;
|
||||
});
|
||||
return { ...x, position: { ...x.position, boundingRect: ret, rects: [ret] } };
|
||||
});
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
position: relative;
|
||||
:global(.PdfHighlighter) {
|
||||
overflow-x: hidden;
|
||||
// left: 0;
|
||||
}
|
||||
:global(.Highlight--scrolledTo .Highlight__part) {
|
||||
overflow-x: hidden;
|
||||
background-color: rgba(255, 226, 143, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { Spin } from 'antd';
|
||||
import { useRef, useState } from 'react';
|
||||
import type { NewHighlight } from 'react-pdf-highlighter';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import {
|
||||
AreaHighlight,
|
||||
Highlight,
|
||||
NewHighlight,
|
||||
PdfHighlighter,
|
||||
PdfLoader,
|
||||
Popup,
|
||||
Tip,
|
||||
} from 'react-pdf-highlighter';
|
||||
import { useGetSelectedChunk } from '../../hooks';
|
||||
import { testHighlights } from './hightlights';
|
||||
import { useGetChunkHighlights, useGetSelectedChunk } from '../../hooks';
|
||||
import { useGetDocumentUrl } from './hooks';
|
||||
|
||||
import styles from './index.less';
|
||||
@@ -36,7 +35,9 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
||||
const url = useGetDocumentUrl();
|
||||
const selectedChunk = useGetSelectedChunk(selectedChunkId);
|
||||
|
||||
const [state, setState] = useState<any>(testHighlights);
|
||||
// const [state, setState] = useState<any>(testHighlights);
|
||||
const state = useGetChunkHighlights(selectedChunkId);
|
||||
|
||||
const ref = useRef((highlight: any) => {});
|
||||
|
||||
const parseIdFromHash = () =>
|
||||
@@ -67,7 +68,7 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
||||
|
||||
console.log('Saving highlight', highlight);
|
||||
|
||||
setState([{ ...highlight, id: getNextId() }, ...highlights]);
|
||||
// setState([{ ...highlight, id: getNextId() }, ...highlights]);
|
||||
};
|
||||
|
||||
const updateHighlight = (
|
||||
@@ -77,29 +78,31 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
||||
) => {
|
||||
console.log('Updating highlight', highlightId, position, content);
|
||||
|
||||
setState(
|
||||
state.map((h: any) => {
|
||||
const {
|
||||
id,
|
||||
position: originalPosition,
|
||||
content: originalContent,
|
||||
...rest
|
||||
} = h;
|
||||
return id === highlightId
|
||||
? {
|
||||
id,
|
||||
position: { ...originalPosition, ...position },
|
||||
content: { ...originalContent, ...content },
|
||||
...rest,
|
||||
}
|
||||
: h;
|
||||
}),
|
||||
);
|
||||
// setState(
|
||||
// state.map((h: any) => {
|
||||
// const {
|
||||
// id,
|
||||
// position: originalPosition,
|
||||
// content: originalContent,
|
||||
// ...rest
|
||||
// } = h;
|
||||
// return id === highlightId
|
||||
// ? {
|
||||
// id,
|
||||
// position: { ...originalPosition, ...position },
|
||||
// content: { ...originalContent, ...content },
|
||||
// ...rest,
|
||||
// }
|
||||
// : h;
|
||||
// }),
|
||||
// );
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// ref.current(testHighlights[0]);
|
||||
// }, [selectedChunk]);
|
||||
useEffect(() => {
|
||||
if (state.length > 0) {
|
||||
ref.current(state[0]);
|
||||
}
|
||||
}, [state]);
|
||||
|
||||
return (
|
||||
<div className={styles.documentContainer}>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { IHighlight } from 'react-pdf-highlighter';
|
||||
import { useSelector } from 'umi';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export const useSelectDocumentInfo = () => {
|
||||
const documentInfo: IKnowledgeFile = useSelector(
|
||||
@@ -28,5 +30,46 @@ export const useHandleChunkCardClick = () => {
|
||||
|
||||
export const useGetSelectedChunk = (selectedChunkId: string) => {
|
||||
const chunkList: IChunk[] = useSelectChunkList();
|
||||
return chunkList.find((x) => x.chunk_id === selectedChunkId);
|
||||
return (
|
||||
chunkList.find((x) => x.chunk_id === selectedChunkId) ?? ({} as IChunk)
|
||||
);
|
||||
};
|
||||
|
||||
export const useGetChunkHighlights = (
|
||||
selectedChunkId: string,
|
||||
): IHighlight[] => {
|
||||
const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId);
|
||||
|
||||
const highlights: IHighlight[] = useMemo(() => {
|
||||
return Array.isArray(selectedChunk?.positions)
|
||||
? selectedChunk?.positions?.map((x) => {
|
||||
const actualPositions = x.map((y, index) =>
|
||||
index !== 0 ? y / 0.7 : y,
|
||||
);
|
||||
const boundingRect = {
|
||||
width: 849,
|
||||
height: 1200,
|
||||
x1: actualPositions[1],
|
||||
x2: actualPositions[2],
|
||||
y1: actualPositions[3],
|
||||
y2: actualPositions[4],
|
||||
};
|
||||
return {
|
||||
id: uuid(),
|
||||
comment: {
|
||||
text: '',
|
||||
emoji: '',
|
||||
},
|
||||
content: { text: selectedChunk.content_with_weight },
|
||||
position: {
|
||||
boundingRect: boundingRect,
|
||||
rects: [boundingRect],
|
||||
pageNumber: x[0],
|
||||
},
|
||||
};
|
||||
})
|
||||
: [];
|
||||
}, [selectedChunk]);
|
||||
|
||||
return highlights;
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import { PaginationProps } from 'antd/lib';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Link, useDispatch, useNavigate, useSelector } from 'umi';
|
||||
import { useDispatch, useNavigate, useSelector } from 'umi';
|
||||
import CreateEPModal from './createEFileModal';
|
||||
import styles from './index.less';
|
||||
import ParsingActionCell from './parsing-action-cell';
|
||||
@@ -144,19 +144,22 @@ const KnowledgeFile = () => {
|
||||
});
|
||||
}, [dispatch]);
|
||||
|
||||
const linkToUploadPage = useCallback(() => {
|
||||
navigate(`/knowledge/dataset/upload?id=${knowledgeBaseId}`);
|
||||
}, [navigate, knowledgeBaseId]);
|
||||
|
||||
const actionItems: MenuProps['items'] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
key: '1',
|
||||
onClick: linkToUploadPage,
|
||||
label: (
|
||||
<div>
|
||||
<Button type="link">
|
||||
<Link to={`/knowledge/dataset/upload?id=${knowledgeBaseId}`}>
|
||||
<Space>
|
||||
<FileTextOutlined />
|
||||
Local files
|
||||
</Space>
|
||||
</Link>
|
||||
<Space>
|
||||
<FileTextOutlined />
|
||||
Local files
|
||||
</Space>
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
@@ -164,9 +167,10 @@ const KnowledgeFile = () => {
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: '2',
|
||||
onClick: showCEFModal,
|
||||
label: (
|
||||
<div>
|
||||
<Button type="link" onClick={showCEFModal}>
|
||||
<Button type="link">
|
||||
<FileOutlined />
|
||||
Create empty file
|
||||
</Button>
|
||||
@@ -175,7 +179,7 @@ const KnowledgeFile = () => {
|
||||
// disabled: true,
|
||||
},
|
||||
];
|
||||
}, [knowledgeBaseId, showCEFModal]);
|
||||
}, [linkToUploadPage, showCEFModal]);
|
||||
|
||||
const toChunk = (id: string) => {
|
||||
navigate(
|
||||
|
||||
Reference in New Issue
Block a user