refactor: Add loading state and bucket handling to Online Drive components

This commit is contained in:
twwu 2025-07-04 15:14:19 +08:00
parent d3b17ea567
commit 2ecbcd6a7f
5 changed files with 63 additions and 6 deletions

View File

@ -1,21 +1,34 @@
import React from 'react'
import { BucketsGray } from '@/app/components/base/icons/src/public/knowledge/online-drive'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useDataSourceStore } from '../../../store'
import Tooltip from '@/app/components/base/tooltip'
type BreadcrumbsProps = {
prefix: string[]
keywords: string
bucket: string
searchResultsLength: number
}
const Breadcrumbs = ({
prefix,
keywords,
bucket,
searchResultsLength,
}: BreadcrumbsProps) => {
const { t } = useTranslation()
const isRoot = prefix.length === 0
const { setFileList, setSelectedFileList, setPrefix, setBucket } = useDataSourceStore().getState()
const isRoot = prefix.length === 0 && bucket === ''
const isSearching = !!keywords
const handleBackToBucketList = useCallback(() => {
setFileList([])
setSelectedFileList([])
setBucket('')
setPrefix([])
}, [setBucket, setFileList, setPrefix, setSelectedFileList])
return (
<div className='flex grow items-center py-1'>
{isRoot && (
@ -24,7 +37,18 @@ const Breadcrumbs = ({
</div>
)}
{!isRoot && (
<div></div>
<div className='flex items-center gap-x-0.5'>
<Tooltip
popupContent={t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
>
<div
className='flex size-5 cursor-pointer items-center justify-center'
onClick={handleBackToBucketList}
>
<BucketsGray />
</div>
</Tooltip>
</div>
)}
</div>
)

View File

@ -7,6 +7,7 @@ type HeaderProps = {
prefix: string[]
inputValue: string
keywords: string
bucket: string
searchResultsLength: number
handleInputChange: React.ChangeEventHandler<HTMLInputElement>
handleResetKeywords: () => void
@ -16,6 +17,7 @@ const Header = ({
prefix,
inputValue,
keywords,
bucket,
searchResultsLength,
handleInputChange,
handleResetKeywords,
@ -27,6 +29,7 @@ const Header = ({
<Breadcrumbs
prefix={prefix}
keywords={keywords}
bucket={bucket}
searchResultsLength={searchResultsLength}
/>
<Input

View File

@ -9,12 +9,14 @@ type FileListProps = {
selectedFileList: string[]
prefix: string[]
keywords: string
bucket: string
isInPipeline: boolean
resetKeywords: () => void
updateKeywords: (keywords: string) => void
searchResultsLength: number
handleSelectFile: (file: OnlineDriveFile) => void
handleOpenFolder: (file: OnlineDriveFile) => void
isLoading: boolean
}
const FileList = ({
@ -22,12 +24,14 @@ const FileList = ({
selectedFileList,
prefix,
keywords,
bucket,
resetKeywords,
updateKeywords,
searchResultsLength,
handleSelectFile,
handleOpenFolder,
isInPipeline,
isLoading,
}: FileListProps) => {
const [inputValue, setInputValue] = useState(keywords)
@ -55,6 +59,7 @@ const FileList = ({
prefix={prefix}
inputValue={inputValue}
keywords={keywords}
bucket={bucket}
handleInputChange={handleInputChange}
searchResultsLength={searchResultsLength}
handleResetKeywords={handleResetKeywords}
@ -67,6 +72,7 @@ const FileList = ({
handleOpenFolder={handleOpenFolder}
handleSelectFile={handleSelectFile}
isInPipeline={isInPipeline}
isLoading={isLoading}
/>
</div>
)

View File

@ -2,12 +2,15 @@ import type { OnlineDriveFile } from '@/models/pipeline'
import Item from './item'
import EmptyFolder from './empty-folder'
import EmptySearchResult from './empty-search-result'
import Loading from '@/app/components/base/loading'
import { RiLoader2Line } from '@remixicon/react'
type FileListProps = {
fileList: OnlineDriveFile[]
selectedFileList: string[]
keywords: string
isInPipeline: boolean
isLoading: boolean
handleResetKeywords: () => void
handleSelectFile: (file: OnlineDriveFile) => void
handleOpenFolder: (file: OnlineDriveFile) => void
@ -21,12 +24,20 @@ const List = ({
handleSelectFile,
handleOpenFolder,
isInPipeline,
isLoading,
}: FileListProps) => {
const isEmptyFolder = fileList.length === 0 && keywords.length === 0
const isSearchResultEmpty = fileList.length === 0 && keywords.length > 0
const isAllLoading = isLoading && fileList.length === 0 && keywords.length === 0
const isPartLoading = isLoading && fileList.length > 0
const isEmptyFolder = !isLoading && fileList.length === 0 && keywords.length === 0
const isSearchResultEmpty = !isLoading && fileList.length === 0 && keywords.length > 0
return (
<div className='grow overflow-hidden p-1 pt-0'>
{
isAllLoading && (
<Loading type='app' />
)
}
{
isEmptyFolder && (
<EmptyFolder />
@ -54,6 +65,13 @@ const List = ({
)
})
}
{
isPartLoading && (
<div className='flex items-center justify-center py-2'>
<RiLoader2Line className='animation-spin size-4 text-text-tertiary' />
</div>
)
}
</div>
)}
</div>

View File

@ -1,6 +1,6 @@
import type { DataSourceNodeType } from '@/app/components/workflow/nodes/data-source/types'
import Header from './header'
import { useCallback, useEffect } from 'react'
import { useCallback, useEffect, useState } from 'react'
import FileList from './file-list'
import type { OnlineDriveFile } from '@/models/pipeline'
import { DatasourceType, OnlineDriveFileType } from '@/models/pipeline'
@ -36,12 +36,14 @@ const OnlineDrive = ({
const setSelectedFileList = useDataSourceStoreWithSelector(state => state.setSelectedFileList)
const fileList = useDataSourceStoreWithSelector(state => state.fileList)
const setFileList = useDataSourceStoreWithSelector(state => state.setFileList)
const [isLoading, setIsLoading] = useState(false)
const datasourceNodeRunURL = !isInPipeline
? `/rag/pipelines/${pipelineId}/workflows/published/datasource/nodes/${nodeId}/run`
: `/rag/pipelines/${pipelineId}/workflows/draft/datasource/nodes/${nodeId}/run`
const getOnlineDrive = useCallback(async () => {
setIsLoading(true)
ssePost(
datasourceNodeRunURL,
{
@ -59,12 +61,14 @@ const OnlineDrive = ({
onDataSourceNodeCompleted: (documentsData: DataSourceNodeCompletedResponse) => {
const newFileList = convertOnlineDriveDataToFileList(documentsData.data)
setFileList([...fileList, ...newFileList])
setIsLoading(false)
},
onDataSourceNodeError: (error: DataSourceNodeErrorResponse) => {
Toast.notify({
type: 'error',
message: error.error,
})
setIsLoading(false)
},
},
)
@ -123,12 +127,14 @@ const OnlineDrive = ({
selectedFileList={selectedFileList}
prefix={prefix}
keywords={keywords}
bucket={bucket}
resetKeywords={resetPrefix}
updateKeywords={updateKeywords}
searchResultsLength={fileList.length}
handleSelectFile={handleSelectFile}
handleOpenFolder={handleOpenFolder}
isInPipeline={isInPipeline}
isLoading={isLoading}
/>
</div>
)