feat(webapp): [phase 1] shell, session, projects, routing

- URL as source of truth: parseRoute/urlForPath/urlForView ported verbatim
  (src/router.ts), single catch-all route so encoded slashes survive
- hub shell: project nav with color chips, org bar, admin bar with pending
  count, sign-out per session flags; volume shell renders too
- empty-state onboarding (invite paste + create project), /join/<token>
  invite accept that survives the login redirect
- toast + modal prompt/confirm primitives (imperative promise API over a
  React host, matching the classic behavior)
- e2e: 7 new hub specs (11 total green); harness gains a no-org 'solo'
  account to reach the empty state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P5cxPQdSGJnjXCYY9GeWXt
This commit is contained in:
Snow Lee
2026-07-13 10:07:30 -07:00
co-authored by Claude Fable 5
parent e701555257
commit 1c4e178b39
19 changed files with 947 additions and 46 deletions
+15 -6
View File
@@ -121,11 +121,20 @@ refresh; invalidate after uploads/renames/admin actions — mirror today's
- [x] `go build ./...`, `go vet ./...`, `go test ./...` green.
### Phase 1 — shell: boot, session, projects, routing
- [ ] Boot from `/api/config`; volume vs hub mode both render.
- [ ] Project list + selection; project color chips (port `projColor`).
- [ ] Empty state + create project; `/join/<token>` invite accept.
- [ ] Deep link + refresh on every route resolves (SPA fallback).
- [ ] Sign-out link, admin bar, org bar render per session flags.
- [x] Boot from `/api/config`; volume vs hub mode both render (hub via the
e2e suite; volume verified against a live `bdrive web <dir>`).
- [x] Project list + selection; project color chips (port `projColor`).
- [x] Empty state + create project; `/join/<token>` invite accept (token
survives the login redirect — covered by e2e).
- [x] Deep link + refresh on every route resolves (SPA fallback); unknown
project ids fall back to a real project.
- [x] Sign-out link, admin bar (with pending count), org bar render per
session flags (admin vs member covered by e2e).
Architecture note: the URL is the source of truth — `parseRoute`
ported verbatim into `src/router.ts`, a single catch-all route, no
route-matching library (encoded slashes must survive). Mutations
must `await useHubRefresh()` before navigating to a new project id,
or the unknown-id fallback bounces off the stale list.
### Phase 2 — file browsing (long pole)
- [ ] Tree with expansion persistence, active marking, reveal-in-tree.
@@ -216,7 +225,7 @@ file path; reload on `/insights`.
## Status
- [x] Phase 0
- [ ] Phase 1
- [x] Phase 1
- [ ] Phase 2
- [ ] Phase 3
- [ ] Phase 4