diff --git a/internal/api/graph_handlers.go b/internal/api/graph_handlers.go index 6f5aa28..7151d3e 100644 --- a/internal/api/graph_handlers.go +++ b/internal/api/graph_handlers.go @@ -2,19 +2,35 @@ package api import ( "encoding/json" + "log" "net/http" + + "github.com/oolong-sh/oolong/internal/graph" + "github.com/oolong-sh/oolong/internal/keywords" + "github.com/oolong-sh/oolong/internal/notes" + "github.com/oolong-sh/oolong/internal/state" ) func handleGetGraph(w http.ResponseWriter, r *http.Request) { + log.Println("Request received:", r.Method, r.URL, r.Host) w.Header().Set("Content-Type", "application/json") - // TODO: server up graph json directly rather than writing to file + // get snapshot of current state + s := state.State() + + // convert state into serializable format for graph + kw := keywords.NGramsToKeywordsMap(s.NGrams) + notes := notes.DocumentsToNotes(s.Documents) - // TODO: finish implementation - // data, err := graph.SerializeGraph() - data := "" + // serialize graph data + // TODO: pass in thresholds (with request? or with config?) + data, err := graph.SerializeGraph(kw, notes, 0.1, 80) + if err != nil { + http.Error(w, "Error serializing graph data", 500) + } + // encode graph data in reponse if err := json.NewEncoder(w).Encode(data); err != nil { - http.Error(w, "Error encoding graph data", 400) + http.Error(w, "Error encoding graph data", 500) } } diff --git a/internal/api/note_handlers.go b/internal/api/note_handlers.go index 13dd30e..1bbdcb1 100644 --- a/internal/api/note_handlers.go +++ b/internal/api/note_handlers.go @@ -5,16 +5,22 @@ import ( "log" "net/http" "os" + "path/filepath" "github.com/oolong-sh/oolong/internal/state" ) +type createUpdateRequest struct { + Path string `json:"path"` + Content string `json:"content"` +} + // 'GET /notes' endpoint handler returns all available note paths func handleGetNotes(w http.ResponseWriter, r *http.Request) { log.Println("Request received:", r.Method, r.URL, r.Host) s := state.State() - data := make([]string, len(s.Documents)) + data := []string{} for k := range s.Documents { data = append(data, k) } @@ -23,8 +29,7 @@ func handleGetNotes(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(data) } -// 'GET /note/{path}' endpoint handler gets note contents corresponding to input path -// TODO: maybe change path to a request body/form item since it can have slashes +// 'GET /note?path=' endpoint handler gets note contents corresponding to input path func handleGetNote(w http.ResponseWriter, r *http.Request) { log.Println("Request received:", r.Method, r.URL, r.Host) @@ -50,46 +55,63 @@ func handleGetNote(w http.ResponseWriter, r *http.Request) { } } -// 'POST /note/{path}' endpoint handler creates note contents corresponding to input path +// 'POST /note' endpoint handler creates a note file (and any missing directories) corresponding to input path +// Expected request body: { "path": "/path/to/note", "content", "full note contents to write" } func handleCreateNote(w http.ResponseWriter, r *http.Request) { - log.Println("Request received:", r.Method, r.URL, r.Host) + log.Println("Request received:", r.Method, r.URL, r.Host, r.Body) - path := r.URL.Query().Get("path") - if path == "" { - http.Error(w, "Path parameter not specified ", http.StatusBadRequest) - return + // parse request body + var req createUpdateRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Failed to decode request body", 400) } // check if path before file exists, then check if file exists - if e, err := exists(path); err != nil { + if e, err := exists(req.Path); err != nil { log.Println(err) http.Error(w, "Error checking path", 500) return } else if e { - log.Printf("File %s already exists.\n", path) + log.Printf("File %s already exists.\n", req.Path) http.Error(w, "Note file already exists", 500) return } - // TODO: create directory case? - // - this will also require adding an additional watcher - _, err := os.Create(path) - if err != nil { + // create directories and file + dir := filepath.Dir(req.Path) + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + log.Println(err) + http.Error(w, "Failed to create missing directories", 500) + return + } + if err := os.WriteFile(req.Path, []byte(req.Content), 0644); err != nil { log.Println(err) - http.Error(w, "Failed to create note file", 500) + http.Error(w, "Failed to create file directories", 500) return } } -// DOC: +// 'PUT /note' endpoint handler updates note contents corresponding to input path +// It will create files that do not exist, but will not create directories +// Expected request body: { "path": "/path/to/note", "content", "full note contents to write" } func handleUpdateNote(w http.ResponseWriter, r *http.Request) { - // TODO: allow writing notes + log.Println("Request received:", r.Method, r.URL, r.Host, r.Body) - // NOTE: DO NOT CALL STATE UPDATE HERE, LET WATCHER HANDLE IT - // - this function only needs to write to a file in the watched locations + // parse request body + var req createUpdateRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Failed to decode request body", 400) + } + + // write contents to file + if err := os.WriteFile(req.Path, []byte(req.Content), 0666); err != nil { + log.Println(err) + http.Error(w, "Failed to write to note file", 500) + return + } } -// DOC: +// 'Delete /note?path=/path/to/note' endpoint handler deletess a note file based on query input func handleDeleteNote(w http.ResponseWriter, r *http.Request) { log.Println("Request received:", r.Method, r.URL, r.Host) @@ -99,17 +121,7 @@ func handleDeleteNote(w http.ResponseWriter, r *http.Request) { return } - // check if path before file exists, then check if file exists - if e, err := exists(path); err != nil { - log.Println(err) - http.Error(w, "Error checking path", 500) - return - } else if !e { - log.Printf("File %s does not exists.\n", path) - http.Error(w, "File does not exist", 500) - return - } - + // attempt to remove file if err := os.Remove(path); err != nil { log.Println("Failed to delete file", err) http.Error(w, "Failed to remove file", 500)