Lists API

This commit is contained in:
Brieuc Dubois 2023-12-27 20:12:39 +01:00
parent 4a1a61ca7f
commit 89cbd67bbb
7 changed files with 285 additions and 37 deletions

95
focus-lists/db.go Normal file
View File

@ -0,0 +1,95 @@
package main
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
var db *sql.DB
type List struct {
ID int `json:"id"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Color string `json:"color"`
}
func InitDB(driver string, connStr string) error {
var err error
db, err = sql.Open(driver, connStr)
if err != nil {
return err
}
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS lists (
id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id INTEGER,
title TEXT,
color TEXT
);
`)
if err != nil {
return err
}
return nil
}
func Create(l List) (int, error) {
res, err := db.Exec("INSERT INTO lists (project_id, title, color) VALUES (?, ?, ?)", l.ProjectID, l.Title, l.Color)
if err != nil {
return 0, err
}
id, err := res.LastInsertId()
if err != nil {
return 0, err
}
return int(id), nil
}
func GetAll(projectID int) ([]List, error) {
rows, err := db.Query("SELECT * FROM lists WHERE project_id = ?", projectID)
if err != nil {
return nil, err
}
defer rows.Close()
var lists []List
for rows.Next() {
var l List
if err := rows.Scan(&l.ID, &l.ProjectID, &l.Title, &l.Color); err != nil {
return nil, err
}
lists = append(lists, l)
}
if err = rows.Err(); err != nil {
return nil, err
}
return lists, nil
}
func Get(id int) (*List, error) {
var l List
err := db.QueryRow("SELECT * FROM lists WHERE id = ?", id).Scan(&l.ID, &l.ProjectID, &l.Title, &l.Color)
if err != nil {
return nil, err
}
return &l, nil
}
func Delete(id int) error {
_, err := db.Exec("DELETE FROM lists WHERE id = ?", id)
return err
}
func Update(l List) error {
_, err := db.Exec("UPDATE lists SET project_id = ?, title = ?, color = ? WHERE id = ?", l.ProjectID, l.Title, l.Color, l.ID)
return err
}

21
focus-lists/go.mod Normal file
View File

@ -0,0 +1,21 @@
module git.bhasher.com/focus/focus-lists
go 1.21.4
require github.com/gofiber/fiber/v2 v2.51.0
require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.50.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.14.0 // indirect
)
require github.com/mattn/go-sqlite3 v1.14.19

41
focus-lists/go.sum Normal file
View File

@ -0,0 +1,41 @@
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86gKQ=
github.com/gofiber/fiber/v2 v2.51.0/go.mod h1:xaQRZQJGqnKOQnbQw+ltvku3/h8QxvNi8o6JiJ7Ll0U=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

107
focus-lists/main.go Normal file
View File

@ -0,0 +1,107 @@
package main
import (
"fmt"
"log"
"strconv"
"github.com/gofiber/fiber/v2"
)
func main() {
driver := "sqlite3"
connStr := "db.sqlite"
port := "3001"
if err := InitDB(driver, connStr); err != nil {
log.Fatal(err)
}
app := fiber.New()
app.Post("/list", createListHandler)
app.Get("/lists/:board_id", getAllListsHandler)
app.Get("/list/:id", getListHandler)
app.Delete("/list/:id", deleteListHandler)
app.Put("/list/:id", updateListHandler)
log.Fatal(app.Listen(fmt.Sprintf(":%v", port)))
}
func createListHandler(c *fiber.Ctx) error {
list := List{}
if err := c.BodyParser(&list); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
}
id, err := Create(list)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot create list"})
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"id": id})
}
func getAllListsHandler(c *fiber.Ctx) error {
boardID, err := strconv.Atoi(c.Params("board_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid board ID"})
}
lists, err := GetAll(boardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve lists"})
}
return c.JSON(lists)
}
func getListHandler(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid list ID"})
}
list, err := Get(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve list"})
}
if list == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "List not found"})
}
return c.JSON(list)
}
func deleteListHandler(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid list ID"})
}
err = Delete(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot delete list"})
}
return c.SendStatus(fiber.StatusNoContent)
}
func updateListHandler(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid list ID"})
}
list := List{ID: id}
if err := c.BodyParser(&list); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
}
err = Update(list)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot update list"})
}
return c.SendStatus(fiber.StatusOK)
}

View File

@ -31,9 +31,7 @@ func main() {
func getAllProjectsHandler(c *fiber.Ctx) error { func getAllProjectsHandler(c *fiber.Ctx) error {
projects, err := GetAll() projects, err := GetAll()
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve projects"})
"error": "Cannot retrieve projects",
})
} }
fmt.Println(projects) fmt.Println(projects)
@ -44,21 +42,15 @@ func getAllProjectsHandler(c *fiber.Ctx) error {
func getProjectHandler(c *fiber.Ctx) error { func getProjectHandler(c *fiber.Ctx) error {
id, err := c.ParamsInt("id") id, err := c.ParamsInt("id")
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
"error": "Invalid project ID",
})
} }
project, err := Get(id) project, err := Get(id)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error fetching project"})
"error": "Error fetching project",
})
} }
if project == nil { if project == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Project not found"})
"error": "Project not found",
})
} }
return c.JSON(project) return c.JSON(project)
} }
@ -66,43 +58,31 @@ func getProjectHandler(c *fiber.Ctx) error {
func createProjectHandler(c *fiber.Ctx) error { func createProjectHandler(c *fiber.Ctx) error {
p := new(Project) p := new(Project)
if err := c.BodyParser(p); err != nil { if err := c.BodyParser(p); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Error parsing request"})
"error": "Error parsing request",
})
} }
id, err := Create(*p) id, err := Create(*p)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error creating project"})
"error": "Error creating project",
})
} }
return c.Status(fiber.StatusCreated).JSON(fiber.Map{ return c.Status(fiber.StatusCreated).JSON(fiber.Map{"id": id})
"id": id,
})
} }
func updateProjectHandler(c *fiber.Ctx) error { func updateProjectHandler(c *fiber.Ctx) error {
id, err := c.ParamsInt("id") id, err := c.ParamsInt("id")
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
"error": "Invalid project ID",
})
} }
p := Project{ID: id} p := Project{ID: id}
if err := c.BodyParser(&p); err != nil { if err := c.BodyParser(&p); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Error parsing request"})
"error": "Error parsing request",
})
} }
err = Update(p) err = Update(p)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error updating project"})
"error": "Error updating project",
})
} }
return c.SendStatus(fiber.StatusOK) return c.SendStatus(fiber.StatusOK)
@ -111,17 +91,13 @@ func updateProjectHandler(c *fiber.Ctx) error {
func deleteProjectHandler(c *fiber.Ctx) error { func deleteProjectHandler(c *fiber.Ctx) error {
id, err := c.ParamsInt("id") id, err := c.ParamsInt("id")
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
"error": "Invalid project ID",
})
} }
err = Delete(id) err = Delete(id)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error deleting project"})
"error": "Error deleting project",
})
} }
return c.SendStatus(fiber.StatusNoContent) return c.SendStatus(fiber.StatusOK)
} }

6
go.work Normal file
View File

@ -0,0 +1,6 @@
go 1.21.4
use (
./focus-projects
./focus-lists
)

2
go.work.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=