This commit is contained in:
Joel 2025-03-14 15:01:39 +08:00
commit ded36c4ab8
4 changed files with 48 additions and 45 deletions

View File

@ -1,11 +1,10 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React, { useCallback, useEffect, useMemo, useState } from 'react' import React, { useCallback, useEffect, useMemo, useState } from 'react'
import useSWR from 'swr'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { useDebounce, useDebounceFn } from 'ahooks' import { useDebounce, useDebounceFn } from 'ahooks'
import { groupBy, omit } from 'lodash-es' import { groupBy } from 'lodash-es'
import { PlusIcon } from '@heroicons/react/24/solid' import { PlusIcon } from '@heroicons/react/24/solid'
import { RiDraftLine, RiExternalLinkLine } from '@remixicon/react' import { RiDraftLine, RiExternalLinkLine } from '@remixicon/react'
import AutoDisabledDocument from '../common/document-status-with-action/auto-disabled-document' import AutoDisabledDocument from '../common/document-status-with-action/auto-disabled-document'
@ -15,16 +14,16 @@ import Loading from '@/app/components/base/loading'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input' import Input from '@/app/components/base/input'
import { get } from '@/service/base' import { get } from '@/service/base'
import { createDocument, fetchDocuments } from '@/service/datasets' import { createDocument } from '@/service/datasets'
import { useDatasetDetailContext } from '@/context/dataset-detail' import { useDatasetDetailContext } from '@/context/dataset-detail'
import { NotionPageSelectorModal } from '@/app/components/base/notion-page-selector' import { NotionPageSelectorModal } from '@/app/components/base/notion-page-selector'
import type { NotionPage } from '@/models/common' import type { NotionPage } from '@/models/common'
import type { CreateDocumentReq } from '@/models/datasets' import type { CreateDocumentReq } from '@/models/datasets'
import { DataSourceType } from '@/models/datasets' import { DataSourceType, ProcessMode } from '@/models/datasets'
import IndexFailed from '@/app/components/datasets/common/document-status-with-action/index-failed' import IndexFailed from '@/app/components/datasets/common/document-status-with-action/index-failed'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useInvalidDocumentDetailKey } from '@/service/knowledge/use-document' import { useDocumentList, useInvalidDocumentDetailKey, useInvalidDocumentList } from '@/service/knowledge/use-document'
import { useInvalid } from '@/service/use-base' import { useInvalid } from '@/service/use-base'
import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/use-segment' import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/use-segment'
import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata' import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata'
@ -81,7 +80,7 @@ type IDocumentsProps = {
} }
export const fetcher = (url: string) => get(url, {}, {}) export const fetcher = (url: string) => get(url, {}, {})
const DEFAULT_LIMIT = 15 const DEFAULT_LIMIT = 10
const Documents: FC<IDocumentsProps> = ({ datasetId }) => { const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
const { t } = useTranslation() const { t } = useTranslation()
@ -102,33 +101,33 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
const debouncedSearchValue = useDebounce(searchValue, { wait: 500 }) const debouncedSearchValue = useDebounce(searchValue, { wait: 500 })
const query = useMemo(() => { const { data: documentsRes, isFetching: isListLoading } = useDocumentList({
return { page: currPage + 1, limit, keyword: debouncedSearchValue, fetch: isDataSourceNotion ? true : '' }
}, [currPage, debouncedSearchValue, isDataSourceNotion, limit])
const { data: documentsRes, mutate, isLoading: isListLoading } = useSWR(
{
action: 'fetchDocuments',
datasetId, datasetId,
params: query, query: {
page: currPage + 1,
limit,
keyword: debouncedSearchValue,
}, },
apiParams => fetchDocuments(omit(apiParams, 'action')), refetchInterval: (isDataSourceNotion && timerCanRun) ? 2500 : 0,
{ refreshInterval: (isDataSourceNotion && timerCanRun) ? 2500 : 0 }, })
)
const invalidDocumentList = useInvalidDocumentList(datasetId)
const [isMuting, setIsMuting] = useState(false)
useEffect(() => { useEffect(() => {
if (!isListLoading && isMuting) if (documentsRes) {
setIsMuting(false) const totalPages = Math.ceil(documentsRes.total / limit)
}, [isListLoading, isMuting]) if (totalPages < currPage + 1)
setCurrPage(totalPages === 0 ? 0 : totalPages - 1)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [documentsRes])
const invalidDocumentDetail = useInvalidDocumentDetailKey() const invalidDocumentDetail = useInvalidDocumentDetailKey()
const invalidChunkList = useInvalid(useSegmentListKey) const invalidChunkList = useInvalid(useSegmentListKey)
const invalidChildChunkList = useInvalid(useChildSegmentListKey) const invalidChildChunkList = useInvalid(useChildSegmentListKey)
const handleUpdate = useCallback(() => { const handleUpdate = useCallback(() => {
setIsMuting(true) invalidDocumentList()
mutate()
invalidDocumentDetail() invalidDocumentDetail()
setTimeout(() => { setTimeout(() => {
invalidChunkList() invalidChunkList()
@ -178,8 +177,6 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
router.push(`/datasets/${datasetId}/documents/create`) router.push(`/datasets/${datasetId}/documents/create`)
} }
const isLoading = isListLoading // !documentsRes && !error
const handleSaveNotionPageSelected = async (selectedPages: NotionPage[]) => { const handleSaveNotionPageSelected = async (selectedPages: NotionPage[]) => {
const workspacesMap = groupBy(selectedPages, 'workspace_id') const workspacesMap = groupBy(selectedPages, 'workspace_id')
const workspaces = Object.keys(workspacesMap).map((workspaceId) => { const workspaces = Object.keys(workspacesMap).map((workspaceId) => {
@ -212,7 +209,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
indexing_technique: dataset?.indexing_technique, indexing_technique: dataset?.indexing_technique,
process_rule: { process_rule: {
rules: {}, rules: {},
mode: 'automatic', mode: ProcessMode.general,
}, },
} as CreateDocumentReq } as CreateDocumentReq
@ -220,7 +217,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
datasetId, datasetId,
body: params, body: params,
}) })
mutate() invalidDocumentList()
setTimerCanRun(true) setTimerCanRun(true)
// mutateDatasetIndexingStatus(undefined, { revalidate: true }) // mutateDatasetIndexingStatus(undefined, { revalidate: true })
setNotionPageSelectorModalVisible(false) setNotionPageSelectorModalVisible(false)
@ -251,7 +248,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
} = useEditDocumentMetadata({ } = useEditDocumentMetadata({
datasetId, datasetId,
dataset, dataset,
onUpdateDocList: mutate, onUpdateDocList: invalidDocumentList,
}) })
return ( return (
@ -311,7 +308,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
)} )}
</div> </div>
</div> </div>
{(isLoading && !isMuting) {isListLoading
? <Loading type='app' /> ? <Loading type='app' />
: total > 0 : total > 0
? <List ? <List

View File

@ -517,18 +517,20 @@ const DocumentList: FC<IDocumentListProps> = ({
return ( return (
<div className='flex flex-col relative w-full h-full'> <div className='flex flex-col relative w-full h-full'>
<div className='grow overflow-x-auto'> <div className='relative grow overflow-x-auto'>
<table className={`min-w-[700px] max-w-full w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}> <table className={`min-w-[700px] max-w-full w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}>
<thead className="h-8 leading-8 border-b border-divider-subtle text-text-tertiary font-medium text-xs uppercase"> <thead className="h-8 leading-8 border-b border-divider-subtle text-text-tertiary font-medium text-xs uppercase">
<tr> <tr>
<td className='w-12'> <td className='w-12'>
<div className='flex items-center' onClick={e => e.stopPropagation()}> <div className='flex items-center' onClick={e => e.stopPropagation()}>
{embeddingAvailable && (
<Checkbox <Checkbox
className='shrink-0 mr-2' className='shrink-0 mr-2'
checked={isAllSelected} checked={isAllSelected}
mixed={!isAllSelected && isSomeSelected} mixed={!isAllSelected && isSomeSelected}
onCheck={onSelectedAll} onCheck={onSelectedAll}
/> />
)}
# #
</div> </div>
</td> </td>

View File

@ -11,7 +11,7 @@ import type { CommonResponse } from '@/models/common'
const NAME_SPACE = 'knowledge/document' const NAME_SPACE = 'knowledge/document'
const useDocumentListKey = [NAME_SPACE, 'documentList'] export const useDocumentListKey = [NAME_SPACE, 'documentList']
export const useDocumentList = (payload: { export const useDocumentList = (payload: {
datasetId: string datasetId: string
query: { query: {

View File

@ -1,6 +1,6 @@
import type { BuiltInMetadataItem, MetadataBatchEditToServer, MetadataItemWithValueLength } from '@/app/components/datasets/metadata/types' import type { BuiltInMetadataItem, MetadataBatchEditToServer, MetadataItemWithValueLength } from '@/app/components/datasets/metadata/types'
import { del, get, patch, post } from '../base' import { del, get, patch, post } from '../base'
import { mutate } from 'swr' import { useDocumentListKey, useInvalidDocumentList } from './use-document'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useInvalid } from '../use-base' import { useInvalid } from '../use-base'
import type { DocumentDetailResponse } from '@/models/datasets' import type { DocumentDetailResponse } from '@/models/datasets'
@ -44,14 +44,14 @@ export const useInvalidAllDocumentMetaData = (datasetId: string) => {
const useInvalidAllMetaData = (datasetId: string) => { const useInvalidAllMetaData = (datasetId: string) => {
const invalidDatasetMetaData = useInvalidDatasetMetaData(datasetId) const invalidDatasetMetaData = useInvalidDatasetMetaData(datasetId)
const invalidDocumentList = useInvalidDocumentList(datasetId)
const invalidateAllDocumentMetaData = useInvalidAllDocumentMetaData(datasetId) const invalidateAllDocumentMetaData = useInvalidAllDocumentMetaData(datasetId)
return async () => { return async () => {
// meta data in dataset // meta data in dataset
await invalidDatasetMetaData() await invalidDatasetMetaData()
// meta data in document list // meta data in document list
mutate( invalidDocumentList()
(key: any) => typeof key === 'object' && key.action === 'fetchDocuments' && key.datasetId === datasetId,
)
// meta data in single document // meta data in single document
await invalidateAllDocumentMetaData() // meta data in document await invalidateAllDocumentMetaData() // meta data in document
} }
@ -118,9 +118,13 @@ export const useBatchUpdateDocMetadata = () => {
queryKey: [NAME_SPACE, 'dataset', payload.dataset_id], queryKey: [NAME_SPACE, 'dataset', payload.dataset_id],
}) })
// meta data in document list // meta data in document list
mutate( await queryClient.invalidateQueries({
(key: any) => typeof key === 'object' && key.action === 'fetchDocuments' && key.datasetId === payload.dataset_id, queryKey: [NAME_SPACE, 'dataset', payload.dataset_id],
) })
await queryClient.invalidateQueries({
queryKey: [...useDocumentListKey, payload.dataset_id],
})
// meta data in single document // meta data in single document
await Promise.all(documentIds.map(documentId => queryClient.invalidateQueries( await Promise.all(documentIds.map(documentId => queryClient.invalidateQueries(
{ {