Skip to content

fix(web): replace broken Browse-for-folder with server-side directory picker#1850

Open
magyargergo wants to merge 10 commits into
mainfrom
fix/issue-1518-docker-local-path
Open

fix(web): replace broken Browse-for-folder with server-side directory picker#1850
magyargergo wants to merge 10 commits into
mainfrom
fix/issue-1518-docker-local-path

Conversation

@magyargergo
Copy link
Copy Markdown
Collaborator

Summary

Fixes the "Browse for folder" button in the local path analysis UI, which was completely broken on all platforms (Docker, local Windows, local Linux). The button used <input type="file" webkitdirectory> which only exposes relative paths via webkitRelativePath — the code extracted just the folder name (e.g. myproject), causing the server to reject it with "path must be an absolute path". No browser API can expose absolute filesystem paths, so the approach was fundamentally unfixable.

This PR replaces the broken browser-side directory picker with a server-side directory listing endpoint + a new DirectoryPicker modal component. Docker users can now browse /workspace/ and other container paths directly from the UI.

Changes

  • GET /api/fs/list endpoint in api.ts — lists subdirectories at a given absolute server-side path (rate-limited via createRouteLimiter, validates absolute path + rejects traversal)
  • listDirectories() client function in backend-client.ts
  • DirectoryPicker modal component — breadcrumb navigation, sorted directory listing, folder selection, loading/error/empty states
  • RepoAnalyzer.tsx — removed broken webkitdirectory file input, wired in DirectoryPicker
  • i18n — updated en + zh-CN locale files with new strings
  • Unit tests — 9 tests covering happy paths, validation, error handling, and rate-limit wiring

Before / After

Before After
"Browse for folder" sends only folder name → server rejects with "path must be an absolute path" "Browse server directories" opens a modal that navigates real server-side directories and returns the full absolute path
Docker users have no way to discover container paths Docker users can browse /workspace/, /data/gitnexus/, etc. directly
Manual path typing works (unchanged) Manual path typing still works (unchanged)

Test plan

  • npx vitest run test/unit/api-fs-list.test.ts — 9 tests passing
  • Existing API tests unaffected (api-file-route, server-validation, rate-limit — 51 tests passing)
  • TypeScript type check passes (tsc --noEmit for both gitnexus and gitnexus-web)
  • Pre-commit hooks pass (eslint, prettier, tsc)
  • Manual test: start server, open web UI, click "Browse server directories", navigate to a folder, select → path appears in input field
  • Manual test: Docker compose up, browse to /workspace/<repo>, analyze

Closes #1518

… picker

The "Browse for folder" button used `<input type="file" webkitdirectory>`
which only exposes relative paths via `webkitRelativePath`. The code
extracted just the folder name (e.g. `myproject`), causing the server to
reject it with "path must be an absolute path". No browser API can
expose absolute filesystem paths, so the approach was fundamentally
broken on all platforms.

- Add `GET /api/fs/list` endpoint that lists subdirectories at a given
  absolute server-side path (rate-limited, validated)
- Add `listDirectories()` client function in backend-client.ts
- Add `DirectoryPicker` modal component with breadcrumb navigation
- Replace broken `webkitdirectory` input in RepoAnalyzer with the new
  server-side directory picker
- Update i18n strings (en + zh-CN)
- Add unit tests for the new endpoint (9 tests)

Docker users can now browse `/workspace/` and other container paths
directly from the UI. Manual path entry continues to work unchanged.

Closes #1518
@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gitnexus Ready Ready Preview, Comment May 29, 2026 8:39pm

Request Review


let dirents;
try {
dirents = await fs.readdir(dir, { withFileTypes: true });
13 Playwright e2e tests covering the full DirectoryPicker flow:
- Open/display: modal opens, shows root dirs, displays current path
- Navigation: click into dirs, breadcrumb back-nav, home button
- Selection: populates path input, returns absolute path, close without selecting
- Edge cases: empty dir, API error, manual typing still works

Also updates existing onboarding.spec.ts to match the renamed
"Browse server directories" button, and adds data-testid attributes
to DirectoryPicker and RepoAnalyzer for reliable e2e targeting.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

✨ PR Autofix

Found fixable formatting / unused-import issues across 72 changed lines. Comment /autofix on this PR to apply them, or run npm run lint:fix && npm run format locally.

{"schema":"gitnexus.pr-autofix/v2","state":"fixes-available","pr_number":1850,"changed_lines":72,"head_sha":"deabb339f692ca51b64c807fe74202cd10bbdd0c","run_id":"26506716854","apply_command":"/autofix"}

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

CI Report

All checks passed

Pipeline Status

Stage Status Details
✅ Typecheck success tsc --noEmit
✅ Tests success unit tests, 3 platforms
✅ E2E success gitnexus-web changes only

Test Results

Tests Passed Failed Skipped Duration
10190 10183 0 7 612s

✅ All 10183 tests passed

7 test(s) skipped — expand for details
  • COBOL pipeline benchmark > scales with file count
  • C# pipeline benchmark > scales with file count — namespaces spread across the solution
  • C# pipeline benchmark > scales with file count — all types in one (global) namespace bucket
  • PHP pipeline benchmark > scales with file count (workers enabled)
  • Ruby pipeline benchmark > scales with file count (workers enabled)
  • Rust pipeline benchmark > scales with file count (workers enabled)
  • buildTypeEnv > known limitations (documented skip tests) > Ruby block parameter: users.each { |user| } — closure param inference, different feature

Code Coverage

Tests

Metric Coverage Covered Base Delta Status
Statements 79.96% 35787/44755 79.48% 📈 +0.5 🟢 ███████████████░░░░░
Branches 68.61% 22859/33316 68% 📈 +0.6 🟢 █████████████░░░░░░░
Functions 84.94% 3680/4332 84.56% 📈 +0.4 🟢 ████████████████░░░░
Lines 83.51% 32229/38591 82.97% 📈 +0.5 🟢 ████████████████░░░░

📋 View full run · Generated by CI

- Add role="dialog", aria-modal, aria-label to the modal panel
- Add aria-label to close button, home button
- Add aria-hidden to decorative icons (chevrons, backdrop)
- Add role="status" to loading spinner with sr-only label
- Add role="alert" to error state
- Add aria-current="location" to active breadcrumb segment
- Wrap breadcrumb in nav landmark with aria-label
- Add Escape key handler to dismiss the modal
- Auto-focus the modal panel on open
- Add focus-visible ring styles to all interactive elements
  (matches existing focus-visible:ring-2 ring-accent/40 pattern)
- Increase breadcrumb button padding (px-1.5 py-1) for better
  touch targets
- Increase directory entry padding (py-2.5) for touch comfort
- Add active:bg-hover/70 pressed state on directory entries
- Add active:bg-accent/80 pressed state on select button
@magyargergo
Copy link
Copy Markdown
Collaborator Author

/autofix

@github-actions
Copy link
Copy Markdown
Contributor

✅ Applied autofix and pushed a commit. (apply run)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Local path analysis not working in Docker version - always throws "path must be an absolute path" error

2 participants