gui: Wails v2 vertical MVP — bindings + UI

Go bindings (cmd/verstak-gui/app.go):
- Wire notes.Service, files.Service, actions.Service, worklog.Service
- CreateNote, ListNotes, ReadNote, SaveNote
- ListFiles, ListActions, RunAction
- ListWorklog, CreateWorklog
- Fix DTO mappings for core types

Frontend (frontend/src/):
- api/verstak.js: Wails v2 API wrapper (window.go.main.App)
- App.svelte: full rewrite with sidebar + 6 tabs + notes editor
- Section filtering → nodes by section
- Notes: create, open textarea editor, save, dirty tracking
- Quick actions, worklog entries, empty states
- Node creation modal with section select

Build:
  cd frontend && npm run build
  rm -rf cmd/verstak-gui/frontend-dist && cp -r frontend/dist cmd/verstak-gui/frontend-dist
  go build -tags 'gui production webkit2_41' -o verstak-gui ./cmd/verstak-gui
  ./verstak-gui
This commit is contained in:
2026-05-31 20:37:46 +08:00
parent 4a8f4e3319
commit b4010a5a24
5 changed files with 509 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
// Wails v2 API wrapper — single frontend access point to Go backend
function wailsCall(method, ...args) {
if (window.go && window.go.main && window.go.main.App) {
return window.go.main.App[method](...args)
}
return Promise.reject(new Error('Wails bindings not loaded'))
}
// Sections
export const listSections = () => wailsCall('ListSections')
// Nodes
export const listNodesBySection = (section) => wailsCall('ListNodesBySection', section)
export const listChildren = (parentID) => wailsCall('ListChildren', parentID)
export const getNodeDetail = (id) => wailsCall('GetNodeDetail', id)
export const createNode = (parentID, type, title, section) =>
wailsCall('CreateNode', parentID, type, title, section)
export const deleteNode = (id) => wailsCall('DeleteNode', id)
// Notes
export const listNotes = (nodeID) => wailsCall('ListNotes', nodeID)
export const createNote = (parentID, title) => wailsCall('CreateNote', parentID, title)
export const readNote = (noteID) => wailsCall('ReadNote', noteID)
export const saveNote = (noteID, content) => wailsCall('SaveNote', noteID, content)
// Files
export const listFiles = (nodeID) => wailsCall('ListFiles', nodeID)
// Actions
export const listActions = (nodeID) => wailsCall('ListActions', nodeID)
export const runAction = (id) => wailsCall('RunAction', id)
// Worklog
export const listWorklog = (nodeID) => wailsCall('ListWorklog', nodeID)
export const createWorklog = (nodeID, summary, minutes) =>
wailsCall('CreateWorklog', nodeID, summary, minutes)
// Search
export const search = (query) => wailsCall('Search', query)
// System
export const verstakVersion = () => wailsCall('VerstakVersion')