package main import "fmt" type InboxNodeDTO struct { NodeDTO CaptureKind string `json:"captureKind"` CaptureSource string `json:"captureSource"` CaptureStatus string `json:"captureStatus"` CaptureContextType string `json:"captureContextType"` CaptureContextNodeID string `json:"captureContextNodeId"` CaptureContextSection string `json:"captureContextSection"` SuggestedTargetNodeID string `json:"suggestedTargetNodeId"` CaptureContextLabel string `json:"captureContextLabel"` SuggestedTargetLabel string `json:"suggestedTargetLabel"` CapturedAt string `json:"capturedAt"` SourceKind string `json:"sourceKind"` URL string `json:"url,omitempty"` Hostname string `json:"hostname,omitempty"` } func (a *App) ListInboxNodes() ([]InboxNodeDTO, error) { if err := a.requireVault(); err != nil { return nil, err } list, err := a.nodes.ListInboxRoots(false) if err != nil { return nil, err } dtos := make([]InboxNodeDTO, 0, len(list)) for _, n := range list { dto, err := a.inboxNodeDTO(&n) if err != nil { return nil, err } dtos = append(dtos, *dto) } for i := range dtos { n, err := a.nodes.CountChildren(dtos[i].ID, "case", "client", "project", "folder", "document", "recipe") if err != nil { return nil, err } dtos[i].HasChildren = n > 0 } return dtos, nil } func (a *App) ListInboxNodesForTarget(nodeID string) ([]InboxNodeDTO, error) { if err := a.requireVault(); err != nil { return nil, err } if nodeID == "" { return []InboxNodeDTO{}, nil } list, err := a.ListInboxNodes() if err != nil { return nil, err } out := make([]InboxNodeDTO, 0, len(list)) for _, item := range list { if item.CaptureContextNodeID == nodeID || item.SuggestedTargetNodeID == nodeID { out = append(out, item) } } return out, nil } func (a *App) AssignInboxNode(nodeID, targetParentID string) (*NodeDTO, error) { if err := a.requireVault(); err != nil { return nil, err } if !a.isInboxCaptureNode(nodeID) { return nil, fmt.Errorf("node is not an inbox artifact") } if targetParentID == "" { return nil, fmt.Errorf("target parent is required") } if err := a.MoveNode(nodeID, targetParentID); err != nil { return nil, err } if err := a.clearCaptureMeta(nodeID); err != nil { return nil, err } dto, err := a.GetNodeDetail(nodeID) if err != nil { return nil, err } return dto, nil } func (a *App) DeleteInboxNode(nodeID string) error { if err := a.requireVault(); err != nil { return err } if !a.isInboxCaptureNode(nodeID) { return fmt.Errorf("node is not an inbox artifact") } if err := a.DeleteNode(nodeID); err != nil { return err } return a.clearCaptureMeta(nodeID) } func (a *App) filterInboxCaptureNodes(list []NodeDTO) []NodeDTO { out := make([]NodeDTO, 0, len(list)) for _, item := range list { if !a.isInboxCaptureNode(item.ID) { out = append(out, item) } } return out } func (a *App) isInboxCaptureNode(nodeID string) bool { v, ok, err := a.nodes.MetaGet(nodeID, "capture.inbox") if err != nil || !ok || v != "true" { return false } status, ok, err := a.nodes.MetaGet(nodeID, "capture.status") if err != nil { return false } return !ok || status == "" || status == "unresolved" } func (a *App) clearCaptureMeta(nodeID string) error { _, err := a.db.Exec(`DELETE FROM node_meta WHERE node_id = ? AND key LIKE 'capture.%'`, nodeID) return err }