From 043dd4871c465b7f50bd85d36ab009906b55072a Mon Sep 17 00:00:00 2001 From: bruno Date: Thu, 16 Jul 2026 12:42:48 -0400 Subject: [PATCH] feat: gitea-workspace now has file tree browser like local-workspace - Main content area now shows file/folder tree with breadcrumb navigation - Click folders to drill down, click files to open - Breadcrumb shows current path with clickable segments - Sorted tree: folders first, then files alphabetically - refreshTree() now reloads without full page reload - Empty state with 'New file' button when folder is empty --- app/templates/gitea_workspace.html | 103 +++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 13 deletions(-) diff --git a/app/templates/gitea_workspace.html b/app/templates/gitea_workspace.html index d3b455c..c34c68e 100644 --- a/app/templates/gitea_workspace.html +++ b/app/templates/gitea_workspace.html @@ -88,20 +88,51 @@ - + @@ -171,16 +202,61 @@ function giteaWorkspace() { editContent: '', commitMessage: 'Update via FlowDeck', commitHistory: JSON.parse(localStorage.getItem('fd_commit_msgs') || '[]'), + // File tree browser + treeItems: [], + treeLoading: false, + folderStack: [], + currentPath: '', + + get sortedTreeItems() { + return [...this.treeItems].sort(function(a, b) { + if (a.type === b.type) return a.name.localeCompare(b.name); + return a.type === 'folder' ? -1 : 1; + }); + }, init() { // Set cookie for sidebar document.cookie = 'flowdeck_workspace=gitea:' + this.owner + ':' + this.repo + ';path=/;SameSite=Lax'; - // Load root tree into sidebar + // Load sidebar tree this.loadSidebarTree(); + // Load main content tree + this.loadMainTree(''); // Listen for sidebar clicks on Gitea items this.setupSidebarClicks(); }, + async loadMainTree(path) { + this.treeLoading = true; + this.currentPath = path; + try { + var url = '/api/gitea/projects/' + this.owner + '/' + this.repo + '/tree'; + if (path) url += '?path=' + encodeURIComponent(path); + var r = await fetch(url); + if (!r.ok) { this.treeItems = []; return; } + var d = await r.json(); + this.treeItems = d.tree || []; + } catch(e) { this.treeItems = []; } + finally { this.treeLoading = false; } + }, + + drillDown(path) { + this.folderStack.push(path.split('/').pop()); + this.loadMainTree(path); + }, + + navigateToFolder(idx) { + // Truncate stack and rebuild path + this.folderStack = this.folderStack.slice(0, idx + 1); + var path = this.folderStack.join('/'); + this.loadMainTree(path); + }, + + navigateToRoot() { + this.folderStack = []; + this.loadMainTree(''); + }, + async loadSidebarTree() { try { var r = await fetch('/api/gitea/projects/' + this.owner + '/' + this.repo + '/tree'); @@ -444,8 +520,9 @@ function giteaWorkspace() { }, async refreshTree() { - // Reload page to refresh sidebar tree - window.location.reload(); + // Reload main tree and sidebar tree without full page reload + this.loadMainTree(this.currentPath); + this.loadSidebarTree(); }, formatSize(bytes) {