diff --git a/server/index.js b/server/index.js index 25b25fd..44ebb95 100755 --- a/server/index.js +++ b/server/index.js @@ -496,7 +496,13 @@ app.get('/api/browse-filesystem', authenticateToken, async (req, res) => { name: item.name, type: 'directory' })) - .slice(0, 20); // Limit results + .sort((a, b) => { + const aHidden = a.name.startsWith('.'); + const bHidden = b.name.startsWith('.'); + if (aHidden && !bHidden) return 1; + if (!aHidden && bHidden) return -1; + return a.name.localeCompare(b.name); + }); // Add common directories if browsing home directory const suggestions = []; diff --git a/src/components/ProjectCreationWizard.jsx b/src/components/ProjectCreationWizard.jsx index 38564dc..24bda03 100644 --- a/src/components/ProjectCreationWizard.jsx +++ b/src/components/ProjectCreationWizard.jsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { X, FolderPlus, GitBranch, Key, ChevronRight, ChevronLeft, Check, Loader2, AlertCircle } from 'lucide-react'; +import { X, FolderPlus, GitBranch, Key, ChevronRight, ChevronLeft, Check, Loader2, AlertCircle, FolderOpen, Eye, EyeOff } from 'lucide-react'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { api } from '../utils/api'; @@ -7,7 +7,7 @@ import { api } from '../utils/api'; const ProjectCreationWizard = ({ onClose, onProjectCreated }) => { // Wizard state const [step, setStep] = useState(1); // 1: Choose type, 2: Configure, 3: Confirm - const [workspaceType, setWorkspaceType] = useState(null); // 'existing' or 'new' + const [workspaceType, setWorkspaceType] = useState('existing'); // 'existing' or 'new' - default to 'existing' // Form state const [workspacePath, setWorkspacePath] = useState(''); @@ -23,6 +23,11 @@ const ProjectCreationWizard = ({ onClose, onProjectCreated }) => { const [loadingTokens, setLoadingTokens] = useState(false); const [pathSuggestions, setPathSuggestions] = useState([]); const [showPathDropdown, setShowPathDropdown] = useState(false); + const [showFolderBrowser, setShowFolderBrowser] = useState(false); + const [browserCurrentPath, setBrowserCurrentPath] = useState('~'); + const [browserFolders, setBrowserFolders] = useState([]); + const [loadingFolders, setLoadingFolders] = useState(false); + const [showHiddenFolders, setShowHiddenFolders] = useState(false); // Load available GitHub tokens when needed useEffect(() => { @@ -155,6 +160,37 @@ const ProjectCreationWizard = ({ onClose, onProjectCreated }) => { setShowPathDropdown(false); }; + const openFolderBrowser = async () => { + setShowFolderBrowser(true); + await loadBrowserFolders('~'); + }; + + const loadBrowserFolders = async (path) => { + try { + setLoadingFolders(true); + setBrowserCurrentPath(path); + const response = await api.browseFilesystem(path); + const data = await response.json(); + setBrowserFolders(data.suggestions || []); + } catch (error) { + console.error('Error loading folders:', error); + } finally { + setLoadingFolders(false); + } + }; + + const selectFolder = (folderPath, advanceToConfirm = false) => { + setWorkspacePath(folderPath); + setShowFolderBrowser(false); + if (advanceToConfirm) { + setStep(3); + } + }; + + const navigateToFolder = async (folderPath) => { + await loadBrowserFolders(folderPath); + }; + return (
@@ -290,28 +326,39 @@ const ProjectCreationWizard = ({ onClose, onProjectCreated }) => { -
- setWorkspacePath(e.target.value)} - placeholder={workspaceType === 'existing' ? '/path/to/existing/workspace' : '/path/to/new/workspace'} - className="w-full" - /> - {showPathDropdown && pathSuggestions.length > 0 && ( -
- {pathSuggestions.map((suggestion, index) => ( - - ))} -
- )} +
+
+ setWorkspacePath(e.target.value)} + placeholder={workspaceType === 'existing' ? '/path/to/existing/workspace' : '/path/to/new/workspace'} + className="w-full" + /> + {showPathDropdown && pathSuggestions.length > 0 && ( +
+ {pathSuggestions.map((suggestion, index) => ( + + ))} +
+ )} +
+

{workspaceType === 'existing' @@ -563,6 +610,121 @@ const ProjectCreationWizard = ({ onClose, onProjectCreated }) => {

+ + {/* Folder Browser Modal */} + {showFolderBrowser && ( +
+
+ {/* Browser Header */} +
+
+
+ +
+

+ Select Folder +

+
+
+ + +
+
+ + {/* Folder List */} +
+ {loadingFolders ? ( +
+ +
+ ) : browserFolders.length === 0 ? ( +
+ No folders found +
+ ) : ( +
+ {/* Parent Directory */} + {browserCurrentPath !== '~' && browserCurrentPath !== '/' && ( + + )} + + {/* Folders */} + {browserFolders + .filter(folder => showHiddenFolders || !folder.name.startsWith('.')) + .sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())) + .map((folder, index) => ( +
+ + +
+ ))} +
+ )} +
+ + {/* Browser Footer with Current Path */} +
+
+ Path: + + {browserCurrentPath} + +
+
+ + +
+
+
+
+ )}
); };