Commit 80a3d577 authored by StyleZhang's avatar StyleZhang

add progress-bar

parent 779312a3
type ProgressBarProps = {
percent: number
}
const ProgressBar = ({
percent = 0,
}: ProgressBarProps) => {
return (
<div className='flex items-center'>
<div className='mr-2 w-[100px] bg-gray-100 rounded-lg'>
<div
className='h-1 bg-[#2970FF] rounded-lg'
style={{ width: `${percent}%` }}
/>
</div>
<div className='text-xs font-medium text-gray-500'>{percent}%</div>
</div>
)
}
export default ProgressBar
......@@ -14,11 +14,11 @@ import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import Pagination from '@/app/components/base/pagination'
import { get } from '@/service/base'
import { createDocument, fetchDocuments } from '@/service/datasets'
import { createDocument, fetchDocuments, getDatasetIndexingStatus } from '@/service/datasets'
import { useDatasetDetailContext } from '@/context/dataset-detail'
import { NotionPageSelectorModal } from '@/app/components/base/notion-page-selector'
import type { DataSourceNotionPage } from '@/models/common'
import type { CreateDocumentReq } from '@/models/datasets'
import type { CreateDocumentReq, IndexingStatusResponse } from '@/models/datasets'
import { DataSourceType } from '@/models/datasets'
// Custom page count is not currently supported.
......@@ -82,6 +82,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
const router = useRouter()
const { dataset } = useDatasetDetailContext()
const [notionPageSelectorModalVisible, setNotionPageSelectorModalVisible] = useState(false)
const [timerCanRun, setTimerCanRun] = useState(false)
const query = useMemo(() => {
return { page: currPage + 1, limit, keyword: searchValue }
......@@ -92,7 +93,45 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
datasetId,
params: query,
}, apiParams => fetchDocuments(omit(apiParams, 'action')))
const { data: datasetIndexingStatus } = useSWR(timerCanRun ? datasetId : null, getDatasetIndexingStatus, { refreshInterval: 2500 })
const datasetDocumentProgress: [Record<string, number>, boolean] = useMemo(() => {
let completedNum = 0
const progressPercentMap = datasetIndexingStatus?.data.reduce((prev: Record<string, number>, next: IndexingStatusResponse) => {
const { id, completed_segments, total_segments, indexing_status } = next
if (indexing_status === 'completed')
completedNum++
const completedCount = completed_segments || 0
const totalCount = total_segments || 0
if (totalCount === 0 && completedCount === 0) {
prev[id] = indexing_status === 'completed' ? 100 : 0
}
else {
const percent = Math.round(completedCount * 100 / totalCount)
prev[id] = percent > 100 ? 100 : percent
}
return prev
}, {}) || {}
return [progressPercentMap, completedNum === datasetIndexingStatus?.data.length]
}, [datasetIndexingStatus?.data])
if (datasetDocumentProgress[1])
setTimerCanRun(false)
const documentsWithProgress = useMemo(() => {
return {
...documentsRes,
data: documentsRes?.data.map((documentItem) => {
return {
...documentItem,
percent: datasetDocumentProgress[0][documentItem.id],
}
}),
}
}, [documentsRes, datasetDocumentProgress])
const total = documentsRes?.total || 0
const routeToDocCreate = () => {
......@@ -149,6 +188,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
})
mutate()
setNotionPageSelectorModalVisible(false)
setTimerCanRun(true)
}
const handleSync = async () => {
......@@ -183,7 +223,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
{isLoading
? <Loading type='app' />
: total > 0
? <List documents={documentsRes?.data || []} datasetId={datasetId} onUpdate={mutate} onSync={handleSync} />
? <List documents={documentsWithProgress?.data || []} datasetId={datasetId} onUpdate={mutate} onSync={handleSync} />
: <EmptyElement onClick={routeToDocCreate} />
}
{/* Show Pagination only if the total is more than the limit */}
......
......@@ -24,7 +24,8 @@ import { asyncRunSafe } from '@/utils'
import { formatNumber } from '@/utils/format'
import { archiveDocument, deleteDocument, disableDocument, enableDocument, syncDocument } from '@/service/datasets'
import NotionIcon from '@/app/components/base/notion-icon'
import { DataSourceType, type DocumentDisplayStatus, type DocumentListResponse } from '@/models/datasets'
import ProgressBar from '@/app/components/base/progress-bar'
import { DataSourceType, type DocumentDisplayStatus, type SimpleDocumentDetail } from '@/models/datasets'
import type { CommonResponse } from '@/models/common'
export const SettingsIcon: FC<{ className?: string }> = ({ className }) => {
......@@ -252,7 +253,7 @@ const renderCount = (count: number | undefined) => {
}
type IDocumentListProps = {
documents: DocumentListResponse['data']
documents: (SimpleDocumentDetail & { percent: number })[]
datasetId: string
onUpdate: () => void
onSync: () => void
......@@ -264,7 +265,7 @@ type IDocumentListProps = {
const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpdate }) => {
const { t } = useTranslation()
const router = useRouter()
const [localDocs, setLocalDocs] = useState<DocumentListResponse['data']>(documents)
const [localDocs, setLocalDocs] = useState<(SimpleDocumentDetail & { percent: number })[]>(documents)
const [enableSort, setEnableSort] = useState(false)
useEffect(() => {
......@@ -317,7 +318,11 @@ const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpd
? <NotionIcon className='inline-flex -mt-[3px] mr-1.5 align-middle' type='page' src={doc.data_source_info.notion_page_icon} />
: <div className={cn(s[`${doc?.data_source_info?.upload_file?.extension ?? suffix}Icon`], s.commonIcon, 'mr-1.5')}></div>
}
<span>{doc?.name?.replace(/\.[^/.]+$/, '')}<span className='text-gray-500'>.{suffix}</span></span>
{
doc.data_source_type === DataSourceType.NOTION
? <span>{doc.name}</span>
: <span>{doc?.name?.replace(/\.[^/.]+$/, '')}<span className='text-gray-500'>.{suffix}</span></span>
}
</td>
<td>{renderCount(doc.word_count)}</td>
<td>{renderCount(doc.hit_count)}</td>
......@@ -325,7 +330,11 @@ const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpd
{dayjs.unix(doc.created_at).format(t('datasetHitTesting.dateTimeFormat') as string)}
</td>
<td>
<StatusItem status={doc.display_status} />
{
['indexing', 'splitting', 'parsing', 'cleaning'].includes(doc.indexing_status)
? <ProgressBar percent={doc.percent} />
: <StatusItem status={doc.display_status} />
}
</td>
<td>
<OperationAction
......
......@@ -71,7 +71,7 @@ const DataSourceNotion = ({
<div className={cn(s['workspace-item'], 'flex items-center mb-1 py-1 pr-1 bg-white rounded-lg')} key={workspace.id}>
<NotionIcon
className='ml-3 mr-[6px]'
src={workspace.source_info.workspace_icon || ''}
src={workspace.source_info.workspace_icon}
name={workspace.source_info.workspace_name}
/>
<div className='grow py-[7px] leading-[18px] text-[13px] font-medium text-gray-700'>{workspace.source_info.workspace_name}</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment