diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs.tsx
deleted file mode 100644
index 56fd9b62aa..0000000000
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-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 { 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 (
-
- {isRoot && (
-
- {t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
-
- )}
- {!isRoot && (
-
- )}
-
- )
-}
-
-export default React.memo(Breadcrumbs)
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/bucket.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/bucket.tsx
new file mode 100644
index 0000000000..c7ff203f2a
--- /dev/null
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/bucket.tsx
@@ -0,0 +1,33 @@
+import React from 'react'
+import { BucketsGray } from '@/app/components/base/icons/src/public/knowledge/online-drive'
+import Tooltip from '@/app/components/base/tooltip'
+import { useTranslation } from 'react-i18next'
+
+type BucketProps = {
+ handleBackToBucketList: () => void
+}
+
+const Bucket = ({
+ handleBackToBucketList,
+}: BucketProps) => {
+ const { t } = useTranslation()
+
+ return (
+ <>
+
+
+
+ /
+ >
+ )
+}
+
+export default React.memo(Bucket)
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx
new file mode 100644
index 0000000000..1e9de5d464
--- /dev/null
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx
@@ -0,0 +1,98 @@
+import React, { useCallback, useMemo } from 'react'
+import { useTranslation } from 'react-i18next'
+import { useDataSourceStore } from '../../../../store'
+import Bucket from './bucket'
+import BreadcrumbItem from './item'
+
+type BreadcrumbsProps = {
+ prefix: string[]
+ keywords: string
+ bucket: string
+ searchResultsLength: number
+ isInPipeline: boolean
+}
+
+const Breadcrumbs = ({
+ prefix,
+ keywords,
+ bucket,
+ searchResultsLength,
+ isInPipeline,
+}: BreadcrumbsProps) => {
+ const { t } = useTranslation()
+ const { setFileList, setSelectedFileList, setPrefix, setBucket } = useDataSourceStore().getState()
+ const showSearchResult = !!keywords && searchResultsLength > 0
+ const isRoot = prefix.length === 0 && bucket === ''
+
+ const breadcrumbs = useMemo(() => {
+ const displayBreadcrumbNum = isInPipeline ? 2 : 3
+ const prefixToDisplay = prefix.slice(0, displayBreadcrumbNum - 1)
+ const collapsedBreadcrumbs = prefix.slice(displayBreadcrumbNum - 1, prefix.length - 1)
+ return {
+ original: prefix,
+ needCollapsed: prefix.length > displayBreadcrumbNum,
+ prefixBreadcrumbs: prefixToDisplay,
+ collapsedBreadcrumbs,
+ lastBreadcrumb: prefix[prefix.length - 1],
+ }
+ }, [isInPipeline, prefix])
+
+ const handleBackToBucketList = useCallback(() => {
+ setFileList([])
+ setSelectedFileList([])
+ setBucket('')
+ setPrefix([])
+ }, [setBucket, setFileList, setPrefix, setSelectedFileList])
+
+ const handleClickBreadcrumb = useCallback((index: number) => {
+ const newPrefix = breadcrumbs.prefixBreadcrumbs.slice(0, index - 1)
+ setFileList([])
+ setSelectedFileList([])
+ setPrefix(newPrefix)
+ }, [breadcrumbs.prefixBreadcrumbs, setFileList, setPrefix, setSelectedFileList])
+
+ return (
+
+ {showSearchResult && (
+
+ {t('datasetPipeline.onlineDrive.breadcrumbs.searchResult', {
+ searchResultsLength,
+ folderName: prefix.length > 0 ? prefix[prefix.length - 1] : bucket,
+ })}
+
+ )}
+ {!showSearchResult && isRoot && (
+
+ {t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
+
+ )}
+ {!showSearchResult && !isRoot && (
+
+ {bucket && (
+
+ )}
+ {!breadcrumbs.needCollapsed && (
+ <>
+ {breadcrumbs.original.map((breadcrumb, index) => {
+ const isLast = index === breadcrumbs.original.length - 1
+ return (
+
+ )
+ })}
+ >
+ )}
+
+ )}
+
+ )
+}
+
+export default React.memo(Breadcrumbs)
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/item.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/item.tsx
new file mode 100644
index 0000000000..92e98b30b3
--- /dev/null
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/item.tsx
@@ -0,0 +1,47 @@
+import React, { useCallback } from 'react'
+import cn from '@/utils/classnames'
+
+type BreadcrumbItemProps = {
+ name: string
+ index: number
+ handleClick: (index: number) => void
+ disabled?: boolean
+ isActive?: boolean
+ showSeparator?: boolean
+}
+
+const BreadcrumbItem = ({
+ name,
+ index,
+ handleClick,
+ disabled = false,
+ isActive = false,
+ showSeparator = true,
+}: BreadcrumbItemProps) => {
+ const handleClickItem = useCallback(() => {
+ if (!disabled)
+ handleClick(index)
+ }, [disabled, handleClick, index])
+
+ return (
+ <>
+
+ {showSeparator && /}
+ >
+ )
+}
+
+BreadcrumbItem.displayName = 'BreadcrumbItem'
+
+export default React.memo(BreadcrumbItem)
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/index.tsx
index 1acb5b64e6..5cdeb5faaa 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/index.tsx
@@ -11,6 +11,7 @@ type HeaderProps = {
searchResultsLength: number
handleInputChange: React.ChangeEventHandler
handleResetKeywords: () => void
+ isInPipeline: boolean
}
const Header = ({
@@ -18,6 +19,7 @@ const Header = ({
inputValue,
keywords,
bucket,
+ isInPipeline,
searchResultsLength,
handleInputChange,
handleResetKeywords,
@@ -31,6 +33,7 @@ const Header = ({
keywords={keywords}
bucket={bucket}
searchResultsLength={searchResultsLength}
+ isInPipeline={isInPipeline}
/>
-
+
- {file.key}
+ {file.displayName}
{!isFolder && file.size && (
{formatFileSize(file.size)}
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/index.tsx
index e3a2ea6517..b670d9a3d4 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/index.tsx
@@ -43,13 +43,14 @@ const OnlineDrive = ({
: `/rag/pipelines/${pipelineId}/workflows/draft/datasource/nodes/${nodeId}/run`
const getOnlineDrive = useCallback(async () => {
+ const prefixString = prefix.length > 0 ? `${prefix.join('/')}/` : ''
setIsLoading(true)
ssePost(
datasourceNodeRunURL,
{
body: {
inputs: {
- prefix: prefix.join('/'),
+ prefix: prefixString,
bucket,
start_after: startAfter,
max_keys: 30, // Adjust as needed
@@ -111,11 +112,12 @@ const OnlineDrive = ({
if (file.type === OnlineDriveFileType.file) return
setFileList([])
if (file.type === OnlineDriveFileType.bucket) {
- setBucket(file.key)
+ setBucket(file.displayName)
}
else {
+ const key = file.displayName.endsWith('/') ? file.displayName.slice(0, -1) : file.displayName
const newPrefix = produce(prefix, (draft) => {
- const newList = file.key.split('/')
+ const newList = key.split('/')
draft.push(...newList)
})
setPrefix(newPrefix)
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts
index e608b50b64..47286850f7 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts
@@ -18,16 +18,20 @@ export const convertOnlineDriveDataToFileList = (data: OnlineDriveData[]): Onlin
data.forEach((item) => {
fileList.push({
key: item.bucket,
+ displayName: item.bucket,
type: OnlineDriveFileType.bucket,
})
})
}
else {
data[0].files.forEach((file) => {
+ const isFileType = isFile(file.key)
+ const filePathList = file.key.split('/')
fileList.push({
key: file.key,
- size: isFile(file.key) ? file.size : undefined,
- type: isFile(file.key) ? OnlineDriveFileType.file : OnlineDriveFileType.folder,
+ displayName: `${isFileType ? filePathList.pop() : filePathList[filePathList.length - 2]}${isFileType ? '' : '/'}`,
+ size: isFileType ? file.size : undefined,
+ type: isFileType ? OnlineDriveFileType.file : OnlineDriveFileType.folder,
})
})
}
diff --git a/web/models/pipeline.ts b/web/models/pipeline.ts
index eb0b7b36fe..93304c9a0c 100644
--- a/web/models/pipeline.ts
+++ b/web/models/pipeline.ts
@@ -276,6 +276,7 @@ export enum OnlineDriveFileType {
export type OnlineDriveFile = {
key: string
+ displayName: string
size?: number
type: OnlineDriveFileType
}