balibabu
feat: Disable clicking the Next button while uploading files in RunDrawer #3355 (#3477)
8872ee4
import FileIcon from '@/components/file-icon'; | |
import HightLightMarkdown from '@/components/highlight-markdown'; | |
import { ImageWithPopover } from '@/components/image'; | |
import PdfDrawer from '@/components/pdf-drawer'; | |
import { useClickDrawer } from '@/components/pdf-drawer/hooks'; | |
import RetrievalDocuments from '@/components/retrieval-documents'; | |
import SvgIcon from '@/components/svg-icon'; | |
import { | |
useNextFetchKnowledgeList, | |
useSelectTestingResult, | |
} from '@/hooks/knowledge-hooks'; | |
import { useGetPaginationWithRouter } from '@/hooks/logic-hooks'; | |
import { IReference } from '@/interfaces/database/chat'; | |
import { | |
Card, | |
Divider, | |
Flex, | |
FloatButton, | |
Input, | |
Layout, | |
List, | |
Pagination, | |
PaginationProps, | |
Popover, | |
Skeleton, | |
Space, | |
Spin, | |
Tag, | |
Tooltip, | |
} from 'antd'; | |
import DOMPurify from 'dompurify'; | |
import { isEmpty } from 'lodash'; | |
import { useMemo, useState } from 'react'; | |
import { useTranslation } from 'react-i18next'; | |
import MarkdownContent from '../chat/markdown-content'; | |
import { useSendQuestion, useShowMindMapDrawer } from './hooks'; | |
import styles from './index.less'; | |
import MindMapDrawer from './mindmap-drawer'; | |
import SearchSidebar from './sidebar'; | |
const { Content } = Layout; | |
const { Search } = Input; | |
const SearchPage = () => { | |
const { t } = useTranslation(); | |
const [checkedList, setCheckedList] = useState<string[]>([]); | |
const { chunks, total } = useSelectTestingResult(); | |
const { list: knowledgeList } = useNextFetchKnowledgeList(); | |
const checkedWithoutEmbeddingIdList = useMemo(() => { | |
return checkedList.filter((x) => knowledgeList.some((y) => y.id === x)); | |
}, [checkedList, knowledgeList]); | |
const { | |
sendQuestion, | |
handleClickRelatedQuestion, | |
handleSearchStrChange, | |
handleTestChunk, | |
setSelectedDocumentIds, | |
answer, | |
sendingLoading, | |
relatedQuestions, | |
searchStr, | |
loading, | |
isFirstRender, | |
selectedDocumentIds, | |
isSearchStrEmpty, | |
} = useSendQuestion(checkedWithoutEmbeddingIdList); | |
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = | |
useClickDrawer(); | |
const { pagination } = useGetPaginationWithRouter(); | |
const { | |
mindMapVisible, | |
hideMindMapModal, | |
showMindMapModal, | |
mindMapLoading, | |
mindMap, | |
} = useShowMindMapDrawer(checkedWithoutEmbeddingIdList, searchStr); | |
const onChange: PaginationProps['onChange'] = (pageNumber, pageSize) => { | |
pagination.onChange?.(pageNumber, pageSize); | |
handleTestChunk(selectedDocumentIds, pageNumber, pageSize); | |
}; | |
const InputSearch = ( | |
<Search | |
value={searchStr} | |
onChange={handleSearchStrChange} | |
placeholder={t('header.search')} | |
allowClear | |
enterButton | |
onSearch={sendQuestion} | |
size="large" | |
loading={sendingLoading} | |
disabled={checkedWithoutEmbeddingIdList.length === 0} | |
className={isFirstRender ? styles.globalInput : styles.partialInput} | |
/> | |
); | |
return ( | |
<> | |
<Layout className={styles.searchPage}> | |
<SearchSidebar | |
isFirstRender={isFirstRender} | |
checkedList={checkedWithoutEmbeddingIdList} | |
setCheckedList={setCheckedList} | |
></SearchSidebar> | |
<Layout className={isFirstRender ? styles.mainLayout : ''}> | |
<Content> | |
{isFirstRender ? ( | |
<Flex justify="center" className={styles.firstRenderContent}> | |
<Flex vertical align="center" gap={'large'}> | |
{InputSearch} | |
</Flex> | |
</Flex> | |
) : ( | |
<Flex className={styles.content}> | |
<section className={styles.main}> | |
{InputSearch} | |
<Card | |
title={ | |
<Flex gap={10}> | |
<img src="/logo.svg" alt="" width={20} /> | |
{t('chat.answerTitle')} | |
</Flex> | |
} | |
className={styles.answerWrapper} | |
> | |
{isEmpty(answer) && sendingLoading ? ( | |
<Skeleton active /> | |
) : ( | |
answer.answer && ( | |
<MarkdownContent | |
loading={sendingLoading} | |
content={answer.answer} | |
reference={answer.reference ?? ({} as IReference)} | |
clickDocumentButton={clickDocumentButton} | |
></MarkdownContent> | |
) | |
)} | |
</Card> | |
<Divider></Divider> | |
<RetrievalDocuments | |
selectedDocumentIds={selectedDocumentIds} | |
setSelectedDocumentIds={setSelectedDocumentIds} | |
onTesting={handleTestChunk} | |
></RetrievalDocuments> | |
<Divider></Divider> | |
<Spin spinning={loading}> | |
{chunks.length > 0 && ( | |
<List | |
dataSource={chunks} | |
className={styles.chunks} | |
renderItem={(item) => ( | |
<List.Item> | |
<Card className={styles.card}> | |
<Space> | |
<ImageWithPopover | |
id={item.img_id} | |
></ImageWithPopover> | |
<Flex vertical gap={10}> | |
<Popover | |
content={ | |
<div className={styles.popupMarkdown}> | |
<HightLightMarkdown> | |
{item.content_with_weight} | |
</HightLightMarkdown> | |
</div> | |
} | |
> | |
<div | |
dangerouslySetInnerHTML={{ | |
__html: DOMPurify.sanitize( | |
`${item.highlight}...`, | |
), | |
}} | |
className={styles.highlightContent} | |
></div> | |
</Popover> | |
<Space | |
className={styles.documentReference} | |
onClick={() => | |
clickDocumentButton( | |
item.doc_id, | |
item as any, | |
) | |
} | |
> | |
<FileIcon | |
id={item.image_id} | |
name={item.docnm_kwd} | |
></FileIcon> | |
{item.docnm_kwd} | |
</Space> | |
</Flex> | |
</Space> | |
</Card> | |
</List.Item> | |
)} | |
/> | |
)} | |
</Spin> | |
{relatedQuestions?.length > 0 && ( | |
<Card title={t('chat.relatedQuestion')}> | |
<Flex wrap="wrap" gap={'10px 0'}> | |
{relatedQuestions?.map((x, idx) => ( | |
<Tag | |
key={idx} | |
className={styles.tag} | |
onClick={handleClickRelatedQuestion(x)} | |
> | |
{x} | |
</Tag> | |
))} | |
</Flex> | |
</Card> | |
)} | |
<Divider></Divider> | |
<Pagination | |
{...pagination} | |
total={total} | |
onChange={onChange} | |
className={styles.pagination} | |
/> | |
</section> | |
</Flex> | |
)} | |
</Content> | |
</Layout> | |
</Layout> | |
{!isFirstRender && | |
!isSearchStrEmpty && | |
!isEmpty(checkedWithoutEmbeddingIdList) && ( | |
<Tooltip title={t('chunk.mind')} zIndex={1}> | |
<FloatButton | |
className={styles.mindMapFloatButton} | |
onClick={showMindMapModal} | |
icon={ | |
<SvgIcon name="paper-clip" width={24} height={30}></SvgIcon> | |
} | |
/> | |
</Tooltip> | |
)} | |
{visible && ( | |
<PdfDrawer | |
visible={visible} | |
hideModal={hideModal} | |
documentId={documentId} | |
chunk={selectedChunk} | |
></PdfDrawer> | |
)} | |
{mindMapVisible && ( | |
<MindMapDrawer | |
visible={mindMapVisible} | |
hideModal={hideMindMapModal} | |
data={mindMap} | |
loading={mindMapLoading} | |
></MindMapDrawer> | |
)} | |
</> | |
); | |
}; | |
export default SearchPage; | |