From b8039dda0b36db457674cc3d133f1d46fd86965c Mon Sep 17 00:00:00 2001 From: Singh Date: Tue, 4 Feb 2025 18:13:34 +1100 Subject: [PATCH] Add new endpoints to get and update a task --- db/bolt.go | 50 ++++++++++++++++++++++++++ db/db.go | 2 ++ db/pqdb.go | 46 ++++++++++++++++++++++++ ui/api.go | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+) diff --git a/db/bolt.go b/db/bolt.go index f361cde9..40951fc3 100644 --- a/db/bolt.go +++ b/db/bolt.go @@ -129,6 +129,56 @@ func (b Boltdb) AddTask(cfg Config, task model.Task) (model.Task, error) { return task, nil } +func (b Boltdb) GetTask(cfg Config, task model.Task) (model.Task, error) { + database, err := bolt.Open(cfg.DbName, 0644, nil) + if err != nil { + return task, err + } + defer database.Close() + + var t model.Task + err = database.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(cfg.DbUser)) + bytes := b.Get([]byte(fmt.Sprint(task.ID))) + if bytes == nil { + return bolt.ErrBucketNotFound + } + json.Unmarshal(bytes, &t) + return nil + }) + if err != nil { + return t, err + } + + return t, nil +} + +func (b Boltdb) UpdateTask(cfg Config, task model.Task) (model.Task, error) { + database, err := bolt.Open(cfg.DbName, 0644, nil) + if err != nil { + return task, err + } + defer database.Close() + + err = database.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(cfg.DbUser)) + bytes, err := json.Marshal(task) + if err != nil { + return err + } + err = b.Put([]byte(fmt.Sprint(task.ID)), bytes) + if err != nil { + return err + } + return nil + }) + if err != nil { + return task, err + } + + return task, nil +} + func (b Boltdb) DeleteTask(cfg Config, task model.Task) error { database, err := bolt.Open(cfg.DbName, 0644, nil) if err != nil { diff --git a/db/db.go b/db/db.go index a02e27b0..fae15338 100644 --- a/db/db.go +++ b/db/db.go @@ -42,6 +42,8 @@ type Database interface { CreateTable(cfg Config) error GetAllTasks(cfg Config) ([]model.Task, error) AddTask(cfg Config, task model.Task) (model.Task, error) + GetTask(cfg Config, task model.Task) (model.Task, error) + UpdateTask(cfg Config, task model.Task) (model.Task, error) DeleteTask(cfg Config, task model.Task) error } diff --git a/db/pqdb.go b/db/pqdb.go index d364fdbf..3f7cdbf7 100644 --- a/db/pqdb.go +++ b/db/pqdb.go @@ -178,6 +178,52 @@ func (p Pqdb) AddTask(cfg Config, task model.Task) (model.Task, error) { return task, nil } +func (p Pqdb) GetTask(cfg Config, task model.Task) (model.Task, error) { + dbInfo := p.getDbInfo(cfg) + + db, err := sql.Open("postgres", dbInfo) + + if err != nil { + return task, err + } + + defer db.Close() + + err = db.QueryRow("SELECT * FROM tasks WHERE id=$1", task.ID).Scan(&task.ID, &task.Complete, &task.Priority, &task.Title) + + if err != nil { + return task, err + } + + return task, nil +} + +func (p Pqdb) UpdateTask(cfg Config, task model.Task) (model.Task, error) { + dbInfo := p.getDbInfo(cfg) + + db, err := sql.Open("postgres", dbInfo) + + if err != nil { + return task, err + } + + defer db.Close() + + stmt, err := db.Prepare("UPDATE tasks SET completed=$1, priority=$2, title=$3 WHERE id=$4") + + if err != nil { + return task, err + } + + _, err = stmt.Exec(task.Complete, task.Priority, task.Title, task.ID) + + if err != nil { + return task, err + } + + return task, nil +} + func (p Pqdb) DeleteTask(cfg Config, task model.Task) error { dbInfo := p.getDbInfo(cfg) diff --git a/ui/api.go b/ui/api.go index 166cad9c..d0bda3c8 100644 --- a/ui/api.go +++ b/ui/api.go @@ -164,8 +164,110 @@ func deleteTask(cfg Config) http.Handler { }) } +// swagger:route GET /api/task/{id}/ getTask +// +// Retrieve a task identified by ID +// +// Produces: +// - application/json +// +// Responses: +// 200: aTask +// 404: +// 500: +func getTask(cfg Config) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + id, err := strconv.Atoi(vars["id"]) + + if err != nil { + log.Println(err) + http.Error(w, err.Error(), 500) + return + } + + db := db.GetDatabase(cfg.DB) + + task, err := db.GetTask(cfg.DB, model.Task{ID: id}) + + if err != nil { + log.Println(err) + http.Error(w, fmt.Sprintf("Task with ID %d not found", id), 404) + return + } + + js, _ := json.Marshal(task) + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, string(js)) + }) +} + +// swagger:route PUT /api/task/{id}/ updateTask +// +// Update a task identified by ID and returns updated task +// +// Produces: +// - application/json +// +// Responses: +// 200: aTask +// 400: +// 404: +// 500: +func updateTask(cfg Config) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, err := strconv.Atoi(vars["id"]) + + if err != nil { + log.Println(err) + http.Error(w, err.Error(), 400) + return + } + + db := db.GetDatabase(cfg.DB) + + // Find the task by ID + dbTask, err := db.GetTask(cfg.DB, model.Task{ID: id}) + if err != nil { + log.Println(err) + http.Error(w, fmt.Sprintf("Task with ID %d not found", id), 404) + return + } + + var task model.Task + // Decode the request body into the task model + decoder := json.NewDecoder(r.Body) + err = decoder.Decode(&task) + if err != nil { + log.Println(err) + http.Error(w, err.Error(), 400) + return + } + + dbTask.Title = task.Title + dbTask.Priority = task.Priority + dbTask.Complete = task.Complete + + // Update the task in the database + updatedTask, err := db.UpdateTask(cfg.DB, dbTask) + if err != nil { + log.Println(err) + http.Error(w, err.Error(), 500) + return + } + + js, _ := json.Marshal(updatedTask) + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, string(js)) + }) +} + func apiHandler(cfg Config, router *mux.Router) { router.Handle("/task/{id:[0-9]+}/", deleteTask(cfg)).Methods("DELETE") router.Handle("/task/", getTasks(cfg)).Methods("GET") router.Handle("/task/", addTask(cfg)).Methods("POST") + router.Handle("/task/{id:[0-9]+}/", getTask(cfg)).Methods("GET") + router.Handle("/task/{id:[0-9]+}/", updateTask(cfg)).Methods("PUT") }