feat: initial scaffold of kanban_cpp v2 (issue 0130)
Frontend C++ ImGui (main.cpp + 4 paneles) + backend Go (HTTP + SQLite + fsnotify + SSE). Reusa parse/scan/watch funcs del registry (issue 0130a).
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"fn-registry/functions/infra"
|
||||
)
|
||||
|
||||
func (s *Server) watchLoop(ctx context.Context, root, kind string) {
|
||||
ch, err := infra.WatchDirFsnotify(ctx, root)
|
||||
if err != nil {
|
||||
log.Printf("watcher %s: %v", root, err)
|
||||
return
|
||||
}
|
||||
for ev := range ch {
|
||||
if !strings.HasSuffix(ev.Path, ".md") {
|
||||
continue
|
||||
}
|
||||
s.handleFsEvent(kind, ev)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleFsEvent(kind string, ev infra.FsEvent) {
|
||||
switch kind {
|
||||
case "issue":
|
||||
s.handleIssueEvent(ev)
|
||||
case "flow":
|
||||
s.handleFlowEvent(ev)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleIssueEvent(ev infra.FsEvent) {
|
||||
id := issueIDFromPath(ev.Path, s.issuesDir)
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
if ev.Op == "remove" || ev.Op == "rename" {
|
||||
s.deleteIssue(id)
|
||||
s.hub.broadcast(SSEEvent{Type: "removed", ID: id, Path: ev.Path})
|
||||
return
|
||||
}
|
||||
iss, _, err := infra.ParseIssueMd(ev.Path)
|
||||
if err != nil {
|
||||
log.Printf("parse %s: %v", ev.Path, err)
|
||||
return
|
||||
}
|
||||
if err := s.upsertIssueRow(iss); err != nil {
|
||||
log.Printf("upsert %s: %v", iss.ID, err)
|
||||
return
|
||||
}
|
||||
s.hub.broadcast(SSEEvent{Type: "updated", ID: iss.ID, Path: ev.Path})
|
||||
}
|
||||
|
||||
func (s *Server) handleFlowEvent(ev infra.FsEvent) {
|
||||
id := issueIDFromPath(ev.Path, s.flowsDir)
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
if ev.Op == "remove" || ev.Op == "rename" {
|
||||
s.deleteFlow(id)
|
||||
s.hub.broadcast(SSEEvent{Type: "flow_removed", ID: id, Path: ev.Path})
|
||||
return
|
||||
}
|
||||
flows, err := infra.ScanFlowsDir(s.flowsDir)
|
||||
if err != nil {
|
||||
log.Printf("scan flows: %v", err)
|
||||
return
|
||||
}
|
||||
for _, fl := range flows {
|
||||
if fl.ID == id {
|
||||
if err := s.upsertFlowRow(fl); err != nil {
|
||||
log.Printf("upsert flow %s: %v", id, err)
|
||||
}
|
||||
s.hub.broadcast(SSEEvent{Type: "flow_updated", ID: id, Path: ev.Path})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user