mirror of https://github.com/langgenius/dify.git
refactor: Add loading state and bucket handling to Online Drive components
This commit is contained in:
parent
d3b17ea567
commit
2ecbcd6a7f
|
|
@ -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>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue