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' ...@@ -14,11 +14,11 @@ import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input' import Input from '@/app/components/base/input'
import Pagination from '@/app/components/base/pagination' import Pagination from '@/app/components/base/pagination'
import { get } from '@/service/base' 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 { 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 { DataSourceNotionPage } from '@/models/common' import type { DataSourceNotionPage } from '@/models/common'
import type { CreateDocumentReq } from '@/models/datasets' import type { CreateDocumentReq, IndexingStatusResponse } from '@/models/datasets'
import { DataSourceType } from '@/models/datasets' import { DataSourceType } from '@/models/datasets'
// Custom page count is not currently supported. // Custom page count is not currently supported.
...@@ -82,6 +82,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => { ...@@ -82,6 +82,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
const router = useRouter() const router = useRouter()
const { dataset } = useDatasetDetailContext() const { dataset } = useDatasetDetailContext()
const [notionPageSelectorModalVisible, setNotionPageSelectorModalVisible] = useState(false) const [notionPageSelectorModalVisible, setNotionPageSelectorModalVisible] = useState(false)
const [timerCanRun, setTimerCanRun] = useState(false)
const query = useMemo(() => { const query = useMemo(() => {
return { page: currPage + 1, limit, keyword: searchValue } return { page: currPage + 1, limit, keyword: searchValue }
...@@ -92,7 +93,45 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => { ...@@ -92,7 +93,45 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
datasetId, datasetId,
params: query, params: query,
}, apiParams => fetchDocuments(omit(apiParams, 'action'))) }, 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 total = documentsRes?.total || 0
const routeToDocCreate = () => { const routeToDocCreate = () => {
...@@ -149,6 +188,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => { ...@@ -149,6 +188,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
}) })
mutate() mutate()
setNotionPageSelectorModalVisible(false) setNotionPageSelectorModalVisible(false)
setTimerCanRun(true)
} }
const handleSync = async () => { const handleSync = async () => {
...@@ -183,7 +223,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => { ...@@ -183,7 +223,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
{isLoading {isLoading
? <Loading type='app' /> ? <Loading type='app' />
: total > 0 : 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} /> : <EmptyElement onClick={routeToDocCreate} />
} }
{/* Show Pagination only if the total is more than the limit */} {/* Show Pagination only if the total is more than the limit */}
......
...@@ -24,7 +24,8 @@ import { asyncRunSafe } from '@/utils' ...@@ -24,7 +24,8 @@ import { asyncRunSafe } from '@/utils'
import { formatNumber } from '@/utils/format' import { formatNumber } from '@/utils/format'
import { archiveDocument, deleteDocument, disableDocument, enableDocument, syncDocument } from '@/service/datasets' import { archiveDocument, deleteDocument, disableDocument, enableDocument, syncDocument } from '@/service/datasets'
import NotionIcon from '@/app/components/base/notion-icon' 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' import type { CommonResponse } from '@/models/common'
export const SettingsIcon: FC<{ className?: string }> = ({ className }) => { export const SettingsIcon: FC<{ className?: string }> = ({ className }) => {
...@@ -252,7 +253,7 @@ const renderCount = (count: number | undefined) => { ...@@ -252,7 +253,7 @@ const renderCount = (count: number | undefined) => {
} }
type IDocumentListProps = { type IDocumentListProps = {
documents: DocumentListResponse['data'] documents: (SimpleDocumentDetail & { percent: number })[]
datasetId: string datasetId: string
onUpdate: () => void onUpdate: () => void
onSync: () => void onSync: () => void
...@@ -264,7 +265,7 @@ type IDocumentListProps = { ...@@ -264,7 +265,7 @@ type IDocumentListProps = {
const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpdate }) => { const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpdate }) => {
const { t } = useTranslation() const { t } = useTranslation()
const router = useRouter() const router = useRouter()
const [localDocs, setLocalDocs] = useState<DocumentListResponse['data']>(documents) const [localDocs, setLocalDocs] = useState<(SimpleDocumentDetail & { percent: number })[]>(documents)
const [enableSort, setEnableSort] = useState(false) const [enableSort, setEnableSort] = useState(false)
useEffect(() => { useEffect(() => {
...@@ -317,7 +318,11 @@ const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpd ...@@ -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} /> ? <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> : <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>
<td>{renderCount(doc.word_count)}</td> <td>{renderCount(doc.word_count)}</td>
<td>{renderCount(doc.hit_count)}</td> <td>{renderCount(doc.hit_count)}</td>
...@@ -325,7 +330,11 @@ const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpd ...@@ -325,7 +330,11 @@ const DocumentList: FC<IDocumentListProps> = ({ documents = [], datasetId, onUpd
{dayjs.unix(doc.created_at).format(t('datasetHitTesting.dateTimeFormat') as string)} {dayjs.unix(doc.created_at).format(t('datasetHitTesting.dateTimeFormat') as string)}
</td> </td>
<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>
<td> <td>
<OperationAction <OperationAction
......
...@@ -71,7 +71,7 @@ const DataSourceNotion = ({ ...@@ -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}> <div className={cn(s['workspace-item'], 'flex items-center mb-1 py-1 pr-1 bg-white rounded-lg')} key={workspace.id}>
<NotionIcon <NotionIcon
className='ml-3 mr-[6px]' className='ml-3 mr-[6px]'
src={workspace.source_info.workspace_icon || ''} src={workspace.source_info.workspace_icon}
name={workspace.source_info.workspace_name} 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> <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