From 2ecbcd6a7f2b9df5d9bb4c4bff71217804419968 Mon Sep 17 00:00:00 2001 From: twwu Date: Fri, 4 Jul 2025 15:14:19 +0800 Subject: [PATCH] refactor: Add loading state and bucket handling to Online Drive components --- .../file-list/header/breadcrumbs.tsx | 30 +++++++++++++++++-- .../online-drive/file-list/header/index.tsx | 3 ++ .../online-drive/file-list/index.tsx | 6 ++++ .../online-drive/file-list/list/index.tsx | 22 ++++++++++++-- .../data-source/online-drive/index.tsx | 8 ++++- 5 files changed, 63 insertions(+), 6 deletions(-) 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 index 47df7316f8..56fd9b62aa 100644 --- 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 @@ -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 (
{isRoot && ( @@ -24,7 +37,18 @@ const Breadcrumbs = ({
)} {!isRoot && ( -
+
+ +
+ +
+
+
)} ) 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 e0929a6ae6..1acb5b64e6 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 @@ -7,6 +7,7 @@ type HeaderProps = { prefix: string[] inputValue: string keywords: string + bucket: string searchResultsLength: number handleInputChange: React.ChangeEventHandler handleResetKeywords: () => void @@ -16,6 +17,7 @@ const Header = ({ prefix, inputValue, keywords, + bucket, searchResultsLength, handleInputChange, handleResetKeywords, @@ -27,6 +29,7 @@ const Header = ({ 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} /> ) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx index 240a9f5f61..f99d311807 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx @@ -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 (
+ { + isAllLoading && ( + + ) + } { isEmptyFolder && ( @@ -54,6 +65,13 @@ const List = ({ ) }) } + { + isPartLoading && ( +
+ +
+ ) + }
)} 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 3890e8a21c..548455a488 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 @@ -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} /> )