feat: Allow processing full folders in the File Input#10208
feat: Allow processing full folders in the File Input#10208
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the
WalkthroughAdds optional folder selection across the frontend file upload flow. Introduces new props (allowFolderSelection, webkitdirectory), updates UI to toggle File/Folder modes, filters folder contents client-side, adjusts hook/queries to handle directory uploads, adds an example and customization usage, and marks a backend DirectoryComponent as legacy with a replacement. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant InputFileComponent
participant FileManagerModal
participant DragFilesComponent
participant useUploadFile
participant createFileUpload
participant usePostUploadFile as API: usePostUploadFile
participant Server
User->>InputFileComponent: Open file picker
InputFileComponent->>FileManagerModal: open(allowFolderSelection)
FileManagerModal->>DragFilesComponent: render(allowFolderSelection)
alt Folder mode ON
DragFilesComponent->>useUploadFile: upload({ types, multiple, webkitdirectory: true })
useUploadFile->>createFileUpload: getFiles({ accept, multiple, webkitdirectory: true })
createFileUpload-->>useUploadFile: File[] (filtered hidden/ignored)
useUploadFile->>usePostUploadFile: mutate for each valid File
usePostUploadFile->>usePostUploadFile: normalize File if webkitRelativePath
usePostUploadFile->>Server: POST FormData(file)
Server-->>usePostUploadFile: 200/response
else File mode
DragFilesComponent->>useUploadFile: upload({ types, multiple, webkitdirectory: false })
useUploadFile->>createFileUpload: getFiles({ accept, multiple })
createFileUpload-->>useUploadFile: File[]
useUploadFile->>usePostUploadFile: mutate per File
usePostUploadFile->>Server: POST FormData(file)
Server-->>usePostUploadFile: 200/response
end
usePostUploadFile-->>DragFilesComponent: results
DragFilesComponent-->>User: Selected/uploaded items
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 error, 3 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
src/frontend/src/modals/fileManagerModal/components/dragFilesComponent/index.tsx (1)
22-114: Reset folder mode when the flag is disabled
isFolderModecan stay true if the parent flipsallowFolderSelectionto false later, leaving the dropzone in folder mode while the toggle is hidden. Add an effect to clear the state when folder selection is disabled:const [isDragging, setIsDragging] = useState(false); const [isFolderMode, setIsFolderMode] = useState(false); +useEffect(() => { + if (!allowFolderSelection && isFolderMode) { + setIsFolderMode(false); + } +}, [allowFolderSelection, isFolderMode]);This keeps the UI and behavior aligned if the prop changes dynamically.
src/frontend/src/helpers/create-file-upload.ts (4)
6-6: LGTM! Folder selection parameter added correctly.The
webkitdirectoryparameter is properly typed and correctly sets the input element properties. The requirement thatmultiplemust betruewhen usingwebkitdirectoryis correctly enforced.Minor suggestion: Consider adding a brief comment explaining that
webkitdirectoryis a non-standard but widely-supported browser API, which justifies the type assertion on line 22.Also applies to: 20-24
77-122: Reduce redundancy in filtering logic.The filtering logic has significant redundancy that reduces maintainability:
- Lines 84-87 check for
.mypy_cachespecifically- Lines 90-101 check if any path part starts with
.(which already catches.mypy_cache)- Lines 104-119 check for common hidden patterns including
.git,.vscode, etc. (which are also caught by the dot-prefix check)The check on lines 90-101 for parts starting with
.will catch all the patterns in thehiddenPatternsarray (lines 104-111) except__pycache__and potentially.DS_Storeif it's not a folder.Consider consolidating to:
files = files.filter((file) => { const path = file.webkitRelativePath; const pathParts = path.split("/"); - // Multiple approaches to catch hidden files/folders: - - // 1. Check if path contains .mypy_cache specifically - if (path.includes(".mypy_cache")) { - console.log("Filtering out .mypy_cache file:", path); - return false; - } - - // 2. Check if any path part starts with '.' + // Check if any path part starts with '.' (catches .git, .vscode, .mypy_cache, etc.) const hasHiddenPath = pathParts.some((part) => { - const startsWithDot = part.startsWith(".") && part.length > 0; - if (startsWithDot) { - console.log(`Found hidden part "${part}" in path: ${path}`); - } - return startsWithDot; + return part.startsWith(".") && part.length > 0; }); if (hasHiddenPath) { - console.log("Filtering out hidden path:", path); return false; } - // 3. Additional check for common hidden patterns - const hiddenPatterns = [ - ".DS_Store", - ".git", - ".vscode", - ".idea", - "__pycache__", - ".pytest_cache", - ]; - const hasHiddenPattern = hiddenPatterns.some((pattern) => - path.includes(pattern), - ); - - if (hasHiddenPattern) { - console.log("Filtering out file with hidden pattern:", path); + // Check for __pycache__ separately since it doesn't start with '.' + if (path.includes("__pycache__")) { return false; } return true; });
60-75: Reduce console logging verbosity for production.The current implementation logs extensively during folder filtering, which could clutter the console in production environments:
- Lines 60-75: Pre-filtering diagnostics
- Lines 85, 93, 99, 117: Per-file filtering logs
- Lines 124-138: Post-filtering diagnostics
For a folder with hundreds of files and many hidden files, this could generate thousands of console messages.
Consider one of these approaches:
- Remove detailed per-file logging and keep only summary logs:
- // First, let's see what we're dealing with - console.log("Before filtering - total files:", originalCount); - console.log( - "Sample paths before filtering:", - files.slice(0, 10).map((f) => f.webkitRelativePath), - ); - - // Show a few .mypy_cache examples if they exist - const mypyCacheFiles = files - .filter((f) => f.webkitRelativePath.includes(".mypy_cache")) - .slice(0, 3); - if (mypyCacheFiles.length > 0) { - console.log( - "Found .mypy_cache files (sample):", - mypyCacheFiles.map((f) => f.webkitRelativePath), - ); - } files = files.filter((file) => { const path = file.webkitRelativePath; const pathParts = path.split("/"); if (path.includes(".mypy_cache")) { - console.log("Filtering out .mypy_cache file:", path); return false; } const hasHiddenPath = pathParts.some((part) => { const startsWithDot = part.startsWith(".") && part.length > 0; - if (startsWithDot) { - console.log(`Found hidden part "${part}" in path: ${path}`); - } return startsWithDot; }); if (hasHiddenPath) { - console.log("Filtering out hidden path:", path); return false; } const hiddenPatterns = [ ".DS_Store", ".git", ".vscode", ".idea", "__pycache__", ".pytest_cache", ]; const hasHiddenPattern = hiddenPatterns.some((pattern) => path.includes(pattern), ); if (hasHiddenPattern) { - console.log("Filtering out file with hidden pattern:", path); return false; } return true; }); - // Debug logging for folder selection console.log("Folder selection results:"); console.log( `Total files found: ${originalCount}, after filtering hidden files/folders: ${files.length}`, ); - if (files.length > 0) { - console.log( - "Remaining files (first 5):", - files.slice(0, 5).map((f) => ({ - name: f.name, - webkitRelativePath: f.webkitRelativePath, - size: f.size, - })), - ); - }
- Use a debug flag to conditionally enable verbose logging only in development.
Also applies to: 85-85, 93-93, 99-99, 117-117, 124-138
49-56: Consider making the file limit configurable.The hard-coded limit of 1000 files (line 49) may be too restrictive for legitimate large project folders that don't contain problematic hidden directories.
Consider either:
- Making this limit a parameter in the function signature with a sensible default
- Increasing the limit to a higher value (e.g., 5000)
- Providing clearer guidance in the error message about which specific hidden directories were detected
src/frontend/src/hooks/files/use-upload-file.ts (1)
69-71: Move multiple file check outside the loop.The check for multiple files (lines 69-71) is currently inside the
forloop and usesfilesToUpload.length. While this is safe because it's within theif (!webkitdirectory)block, it's inefficient because:
- The check will be executed on every iteration of the loop
- The error will be thrown on the first file, but after
validateFileSizehas already been calledMove this check before the loop:
+ // Check multiple file constraint for non-folder selection + if (!webkitdirectory && !multiple && filesToUpload.length !== 1) { + throw new Error("Multiple files are not allowed"); + } + for (const file of validFiles) { validateFileSize(file); // Check if file extension is allowed (for non-folder selection) if (!webkitdirectory) { const fileExtension = file.name.split(".").pop()?.toLowerCase(); if (!fileExtension || (types && !types.includes(fileExtension))) { throw new Error( `File type ${fileExtension} not allowed. Allowed types: ${types?.join(", ")}`, ); } - if (!multiple && filesToUpload.length !== 1) { - throw new Error("Multiple files are not allowed"); - } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
src/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx(4 hunks)src/frontend/src/components/examples/folder-selection-example.tsx(1 hunks)src/frontend/src/controllers/API/queries/file-management/use-post-upload-file.ts(1 hunks)src/frontend/src/customization/components/custom-input-file.tsx(1 hunks)src/frontend/src/helpers/create-file-upload.ts(3 hunks)src/frontend/src/hooks/files/use-upload-file.ts(3 hunks)src/frontend/src/modals/fileManagerModal/components/dragFilesComponent/index.tsx(4 hunks)src/frontend/src/modals/fileManagerModal/index.tsx(3 hunks)src/lfx/src/lfx/components/data/directory.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
src/frontend/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)
src/frontend/src/**/*.{ts,tsx,js,jsx}: All frontend TypeScript and JavaScript code should be located under src/frontend/src/ and organized into components, pages, icons, stores, types, utils, hooks, services, and assets directories as per the specified directory layout.
Use React 18 with TypeScript for all UI components in the frontend.
Format all TypeScript and JavaScript code using the make format_frontend command.
Lint all TypeScript and JavaScript code using the make lint command.
Files:
src/frontend/src/components/examples/folder-selection-example.tsxsrc/frontend/src/hooks/files/use-upload-file.tssrc/frontend/src/modals/fileManagerModal/components/dragFilesComponent/index.tsxsrc/frontend/src/controllers/API/queries/file-management/use-post-upload-file.tssrc/frontend/src/modals/fileManagerModal/index.tsxsrc/frontend/src/helpers/create-file-upload.tssrc/frontend/src/customization/components/custom-input-file.tsxsrc/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx
src/frontend/src/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)
All components should be styled using Tailwind CSS utility classes.
Files:
src/frontend/src/components/examples/folder-selection-example.tsxsrc/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx
src/frontend/src/@(components|hooks)/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)
Implement dark mode support in components and hooks where needed.
Files:
src/frontend/src/components/examples/folder-selection-example.tsxsrc/frontend/src/hooks/files/use-upload-file.tssrc/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx
src/frontend/src/@(hooks|services)/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)
All API calls must implement proper error handling, such as using try/catch and setting error state.
Files:
src/frontend/src/hooks/files/use-upload-file.ts
src/frontend/src/hooks/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)
All custom React hooks should be placed in the hooks directory.
Files:
src/frontend/src/hooks/files/use-upload-file.ts
🧬 Code graph analysis (4)
src/frontend/src/components/examples/folder-selection-example.tsx (1)
src/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx (1)
InputFileComponent(23-333)
src/frontend/src/modals/fileManagerModal/components/dragFilesComponent/index.tsx (2)
src/frontend/tests/utils/upload-file.ts (1)
uploadFile(34-90)src/frontend/src/components/common/genericIconComponent/index.tsx (1)
ForwardedIconComponent(15-146)
src/frontend/src/controllers/API/queries/file-management/use-post-upload-file.ts (1)
src/backend/base/langflow/services/database/models/file/model.py (1)
File(9-19)
src/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx (3)
src/frontend/src/components/core/parameterRenderComponent/types.ts (1)
FileComponentType(74-79)src/frontend/src/helpers/create-file-upload.ts (1)
createFileUpload(3-174)src/frontend/src/constants/alerts_constants.tsx (2)
INVALID_FILE_ALERT(5-6)CONSOLE_ERROR_MSG(7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run Frontend Tests / Determine Test Suites and Shard Distribution
- GitHub Check: Run Frontend Unit Tests / Frontend Jest Unit Tests
- GitHub Check: Test Starter Templates
- GitHub Check: Update Starter Projects
🔇 Additional comments (3)
src/frontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx (1)
33-36: LGTM! Folder selection prop correctly threaded through.The
allowFolderSelectionprop is properly added to the component's type signature and correctly passed toFileManagerModal. This follows the expected pattern for propagating feature flags through the component hierarchy.Also applies to: 251-251
src/frontend/src/hooks/files/use-upload-file.ts (2)
8-8: LGTM! Parameter correctly threaded through.The
webkitdirectoryparameter is properly added to the hook signature and correctly passed tocreateFileUpload.Also applies to: 12-12, 26-26
41-54: LGTM! Extension filtering for folders is correct.This filtering is necessary because
createFileUploadonly filters hidden files/folders in folder mode, not by file extension. The logic correctly filters files to match the allowed types and provides a clear error message when no valid files are found.
...rontend/src/components/core/parameterRenderComponent/components/inputFileComponent/index.tsx
Outdated
Show resolved
Hide resolved
src/frontend/src/customization/components/custom-input-file.tsx
Outdated
Show resolved
Hide resolved
…onents/inputFileComponent/index.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
Removed the change associated with this PR, because of the changes requested in this Jira ticket |
Summary by CodeRabbit
New Features
Improvements
Deprecations