diff --git a/ui/client-app/src/components/FileSystemNavigator.js b/ui/client-app/src/components/FileSystemNavigator.js index cadbbbe..c01bf20 100644 --- a/ui/client-app/src/components/FileSystemNavigator.js +++ b/ui/client-app/src/components/FileSystemNavigator.js @@ -60,12 +60,18 @@ const isExpanded = expanded[path]; if (!isExpanded) { // Loading child depth... - const children = await fetchLevel(path); - setExpanded(prev => ({ ...prev, [path]: true })); - // We'll update the tree to include these children - // For a flat list manifest, we might need a more sophisticated tree mapper. - // But if the server returns EVERYTHING for the root, we don't need this. - // Currently, ls returns all files in the root_path. + try { + const children = await fetchLevel(path); + setExpanded(prev => ({ ...prev, [path]: true })); + // Merge children into tree (prevent duplicates) + setTree(prev => { + const existingPaths = new Set(prev.map(f => f.path)); + const newOnes = children.filter(c => !existingPaths.has(c.path)); + return [...prev, ...newOnes]; + }); + } catch (err) { + setError(`Failed to open folder: ${err.message}`); + } } else { setExpanded(prev => ({ ...prev, [path]: false })); } @@ -140,20 +146,33 @@ }; // Helper to render tree recursively - const renderNode = (nodes, depth = 0) => { + // Helper to render tree recursively + const renderSubTree = (currentPath, depth = 0) => { + // Find children of this path + const children = tree.filter(node => { + if (currentPath === initialPath || currentPath === "." || currentPath === "") { + const prefix = initialPath === "." || initialPath === "" ? "" : (initialPath.endsWith("/") ? initialPath : initialPath + "/"); + if (!node.path.startsWith(prefix)) return false; + if (node.path === initialPath) return false; + const sub = node.path.slice(prefix.length); + return !sub.includes("/"); + } else { + const prefix = currentPath.endsWith("/") ? currentPath : currentPath + "/"; + if (!node.path.startsWith(prefix)) return false; + const sub = node.path.slice(prefix.length); + return !sub.includes("/"); + } + }); + // Sort: Folders first, then Alphabetical - const sorted = [...nodes].sort((a, b) => { - if (a.is_dir !== b.is_dir) return b.is_dir ? 1 : -1; + const sorted = [...children].sort((a, b) => { + if (a.is_dir !== b.is_dir) return b.is_dir ? -1 : 1; return a.name.localeCompare(b.name); }); - // Filter for hierarchical view (if needed) - // Since we currently get a flat list from ls for the specific root, - // we can just render them directly if we are browsing one level at a time. - return sorted.map(node => ( -
-
+
+
node.is_dir ? toggleFolder(node.path) : handleView(node.path)} @@ -178,7 +197,7 @@ {node.name} -
+
{node.is_dir && ( <>
- {/* Hierarchical expansion would go here if we fetch deeper levels */} + {node.is_dir && expanded[node.path] && ( +
+ {renderSubTree(node.path, depth + 1)} +
+ )}
)); }; @@ -229,7 +252,7 @@

No files found or node offline

)} - {renderNode(tree)} + {renderSubTree(initialPath)}
{/* Create Item Modal */}