mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-23 02:53:31 +00:00
f6aa70efb3
* fix(web): schema-driven trigger+scope options in create forms (IDEA-619) Follow-up to PLAN-609. Non-software templates (hiring, interviewing) ship their own convention + playbook trigger vocabularies via the Conventions and Playbooks collection schemas, but the web UI's CREATE forms on both pages were still iterating hardcoded software- only constants. Users in a non-software workspace could see seeded items (thanks to the display tolerance added in PR #146) but could not CREATE new items with the workspace's own vocabulary via the web UI — only via the CLI. Both conventions and playbooks pages now: - Load their collection schema alongside items (non-blocking — a failed schema load falls back to the hardcoded software constants so the page stays functional offline or against an older server). - Derive `createTriggers` and `createSurfaces`/`createScopes` from the schema's `trigger`/`scope` field `options`, with the hardcoded lists as the backstop. - Drive the create-form `<select>` dropdowns from the derived lists instead of the hardcoded constants. - Snap `newTrigger` / `newSurface` / `newScope` state into the effective list when the schema changes so the select never shows a phantom value. - Use the schema-derived lists as the "known" baseline for the filter dropdowns (`allSurfaces` / `allTriggers` / `allScopes`), still unioned with any trigger/scope values discovered on loaded items (preserves the display tolerance from PR #146). Net effect: in a hiring workspace, the New Convention form's trigger dropdown shows `on-candidate-advance`, `on-offer-extended`, etc.; the scope dropdown shows `sourcing`, `screening`, `interviewing`, `offers`. Interviewing workspace gets its own vocabulary. Software workspaces are unchanged. Closes IDEA-619. * fix(web): guard schema loads against workspace-switch stale responses Per Codex review on PR #151. When a user navigates between workspaces quickly, an earlier api.collections.get(...) call for workspace A might resolve AFTER the user is on workspace B, overwriting the current schema state with A's schema. The create/filter dropdowns would then reflect the wrong workspace's trigger/scope vocabulary. Fix: capture the workspace slug at call time; skip the state assignment if the current workspace has changed by the time the response resolves. Symmetrical guard on the catch branch so a failed call from the previous workspace doesn't null out the current one. Applied to both conventions and playbooks pages. * fix(web): clear schema state before workspace-schema fetch Per Codex review iteration 2 on PR #151. The previous guard only dropped stale responses AFTER they resolved — but while a new workspace's fetch was in flight, the old workspace's schema was still present in state. In that window the create/filter dropdowns showed the previous workspace's vocabulary on the new page, so a user could submit a convention with stale trigger/scope values. Fix: clear conventionsCollection / playbooksCollection to null at the START of loadXCollection, before awaiting the fetch. During the in-flight window, createTriggers/createSurfaces fall back to the hardcoded software defaults — the correct conservative state for a workspace whose schema we haven't observed yet. The existing resolved-response stale guard remains.
Pad Web UI
SvelteKit 2 + Svelte 5 frontend for Pad, compiled to static files and embedded into the Go binary.
Development
npm install
npm run dev # Dev server at localhost:5173 (proxies API to localhost:7777)
npm run build # Production build to build/
npm run check # Type checking with svelte-check
When developing, run the Go backend separately with make dev from the project root.
Building for Production
Do not build in isolation. Always use make build from the project root — this builds the web frontend, then compiles the Go binary with the build output embedded via //go:embed.
Stack
- Svelte 5 with runes (
$state,$derived,$effect) - SvelteKit 2 with
adapter-static(SPA mode) - Tiptap block editor with markdown round-trip
- svelte-dnd-action for drag-and-drop in board/list views
- SSE for real-time updates
- TypeScript throughout
Structure
src/
routes/ SvelteKit pages
+layout.svelte App shell (sidebar + main)
+page.svelte Landing/redirect
[workspace]/
+page.svelte Dashboard (collections, phases, activity)
+layout.svelte SSE connection per workspace
[collection]/
+page.svelte Collection view (board/list)
[collection]/[item]/
+page.svelte Item detail + editor
conventions/ Purpose-built conventions page
playbooks/ Purpose-built playbooks page
settings/ Workspace settings
lib/
api/client.ts HTTP API client
components/
layout/ Sidebar, navigation
editor/ Tiptap editor, raw markdown editor
fields/ FieldEditor, relation picker
items/ ItemCard, ItemDetail
collections/ BoardView, ListView
common/ StatusBadge, badges, modals
search/ CommandPalette
activity/ ActivityFeed
stores/ Svelte 5 reactive stores
workspace.svelte.ts Workspace state
collections.svelte.ts Collection + item state
ui.svelte.ts Sidebar, mobile state
types/index.ts TypeScript types and constants
app.css Global styles and design tokens