HAL for /api/projects
This commit is contained in:
parent
daee67d6c3
commit
70c8f93c69
|
@ -1,61 +0,0 @@
|
||||||
package db
|
|
||||||
|
|
||||||
import "git.bhasher.com/bhasher/focus/backend/types"
|
|
||||||
|
|
||||||
func CreateList(l types.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 GetAllListsOf(projectID int) ([]types.List, error) {
|
|
||||||
rows, err := db.Query("SELECT * FROM lists WHERE project_id = ?", projectID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var lists []types.List
|
|
||||||
for rows.Next() {
|
|
||||||
var l types.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 GetList(id int) (*types.List, error) {
|
|
||||||
var l types.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 DeleteList(id int) error {
|
|
||||||
_, err := db.Exec("DELETE FROM lists WHERE id = ?", id)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateList(l types.List) error {
|
|
||||||
_, err := db.Exec("UPDATE lists SET project_id = ?, title = ?, color = ? WHERE id = ?", l.ProjectID, l.Title, l.Color, l.ID)
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -61,3 +61,13 @@ func UpdateProject(p types.Project) error {
|
||||||
_, err := db.Exec("UPDATE projects SET title = ? WHERE id = ?", p.Title, p.ID)
|
_, err := db.Exec("UPDATE projects SET title = ? WHERE id = ?", p.Title, p.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExistProject(id int) (bool, error) {
|
||||||
|
var count int
|
||||||
|
err := db.QueryRow("SELECT COUNT(*) FROM projects WHERE id = ?", id).Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count > 0, nil
|
||||||
|
}
|
||||||
|
|
|
@ -6,21 +6,33 @@ import (
|
||||||
|
|
||||||
"git.bhasher.com/bhasher/focus/backend/db"
|
"git.bhasher.com/bhasher/focus/backend/db"
|
||||||
"git.bhasher.com/bhasher/focus/backend/types"
|
"git.bhasher.com/bhasher/focus/backend/types"
|
||||||
|
"git.bhasher.com/bhasher/focus/backend/utils"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateCard(c *fiber.Ctx) error {
|
func CreateCard(c *fiber.Ctx) error {
|
||||||
card := types.Card{}
|
card := types.Card{}
|
||||||
if err := c.BodyParser(&card); err != nil {
|
if err := c.BodyParser(&card); err != nil {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"status": "error", "error": "Cannot parse request", "trace": fmt.Sprint(err)})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||||
|
"error": "Cannot parse request",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := db.CreateCard(card)
|
id, err := db.CreateCard(card)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"status": "error", "error": "Cannot create card", "trace": fmt.Sprint(err)})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Cannot create card",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"status": "ok", "id": id})
|
c.Status(fiber.StatusCreated)
|
||||||
|
c.Location(fmt.Sprintf("/api/cards/%v", id))
|
||||||
|
return c.JSON(fiber.Map{
|
||||||
|
"id": id,
|
||||||
|
"_links": utils.HALProjectLinks(id),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllCardsOf(c *fiber.Ctx) error {
|
func GetAllCardsOf(c *fiber.Ctx) error {
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"git.bhasher.com/bhasher/focus/backend/db"
|
|
||||||
"git.bhasher.com/bhasher/focus/backend/types"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateList(c *fiber.Ctx) error {
|
|
||||||
list := types.List{}
|
|
||||||
if err := c.BodyParser(&list); err != nil {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := db.CreateList(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 GetAllListsOf(c *fiber.Ctx) error {
|
|
||||||
projectID, err := strconv.Atoi(c.Params("project_id"))
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
|
|
||||||
}
|
|
||||||
|
|
||||||
lists, err := db.GetAllListsOf(projectID)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve lists"})
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.JSON(lists)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetList(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 := db.GetList(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 DeleteList(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 = db.DeleteList(id)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot delete list"})
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusNoContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateList(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 := types.List{ID: id}
|
|
||||||
if err := c.BodyParser(&list); err != nil {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.UpdateList(list)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot update list"})
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
|
||||||
}
|
|
|
@ -1,18 +1,39 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"git.bhasher.com/bhasher/focus/backend/db"
|
"git.bhasher.com/bhasher/focus/backend/db"
|
||||||
"git.bhasher.com/bhasher/focus/backend/types"
|
"git.bhasher.com/bhasher/focus/backend/types"
|
||||||
|
"git.bhasher.com/bhasher/focus/backend/utils"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAllProjects(c *fiber.Ctx) error {
|
func GetAllProjects(c *fiber.Ctx) error {
|
||||||
projects, err := db.GetAllProjects()
|
projects, err := db.GetAllProjects()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve projects"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Cannot retrieve projects",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(projects)
|
halProjects := make([]fiber.Map, len(projects))
|
||||||
|
for i, p := range projects {
|
||||||
|
halProjects[i] = fiber.Map{
|
||||||
|
"project": p,
|
||||||
|
"_links": utils.HALProjectLinks(p.ID),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.SendHAL(c, fiber.StatusOK, fiber.Map{
|
||||||
|
"_links": fiber.Map{
|
||||||
|
"self": fiber.Map{"href": "/api/projects"},
|
||||||
|
},
|
||||||
|
"_embedded": fiber.Map{
|
||||||
|
"projects": halProjects,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProject(c *fiber.Ctx) error {
|
func GetProject(c *fiber.Ctx) error {
|
||||||
|
@ -23,12 +44,19 @@ func GetProject(c *fiber.Ctx) error {
|
||||||
|
|
||||||
project, err := db.GetProject(id)
|
project, err := db.GetProject(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error fetching project"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Error fetching project",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if project == nil {
|
if project == nil {
|
||||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Project not found"})
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
return c.JSON(project)
|
|
||||||
|
return utils.SendHAL(c, fiber.StatusOK, fiber.Map{
|
||||||
|
"project": project,
|
||||||
|
"_links": utils.HALProjectLinks(project.ID),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateProject(c *fiber.Ctx) error {
|
func CreateProject(c *fiber.Ctx) error {
|
||||||
|
@ -39,10 +67,17 @@ func CreateProject(c *fiber.Ctx) error {
|
||||||
|
|
||||||
id, err := db.CreateProject(*p)
|
id, err := db.CreateProject(*p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error creating project"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Error creating project",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"id": id})
|
c.Location(fmt.Sprintf("/api/projects/%v", id))
|
||||||
|
return utils.SendHAL(c, fiber.StatusCreated, fiber.Map{
|
||||||
|
"id": id,
|
||||||
|
"_links": utils.HALProjectLinks(id),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateProject(c *fiber.Ctx) error {
|
func UpdateProject(c *fiber.Ctx) error {
|
||||||
|
@ -56,12 +91,27 @@ func UpdateProject(c *fiber.Ctx) error {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Error parsing request"})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Error parsing request"})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.UpdateProject(p)
|
exists, err := db.ExistProject(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error updating project"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Error finding project",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
if !exists {
|
||||||
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.UpdateProject(p)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Error updating project",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(fiber.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteProject(c *fiber.Ctx) error {
|
func DeleteProject(c *fiber.Ctx) error {
|
||||||
|
@ -70,10 +120,25 @@ func DeleteProject(c *fiber.Ctx) error {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.DeleteProject(id)
|
exists, err := db.ExistProject(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Error deleting project"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Error finding project",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
if !exists {
|
||||||
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.DeleteProject(id)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": "Error deleting project",
|
||||||
|
"trace": fmt.Sprint(err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(fiber.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,35 +30,29 @@ func main() {
|
||||||
AllowHeaders: "Origin, Content-Type, Accept",
|
AllowHeaders: "Origin, Content-Type, Accept",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
app.Post("/api/project", handlers.CreateProject)
|
app.Post("/api/projects", handlers.CreateProject)
|
||||||
app.Get("/api/projects", handlers.GetAllProjects)
|
app.Get("/api/projects", handlers.GetAllProjects)
|
||||||
app.Get("/api/project/:id", handlers.GetProject)
|
app.Get("/api/projects/:id", handlers.GetProject)
|
||||||
app.Put("/api/project/:id", handlers.UpdateProject)
|
app.Put("/api/projects/:id", handlers.UpdateProject)
|
||||||
app.Delete("/api/project/:id", handlers.DeleteProject)
|
app.Delete("/api/projects/:id", handlers.DeleteProject)
|
||||||
|
app.Get("/api/projects/:project_id/cards", handlers.GetAllCardsOf)
|
||||||
|
app.Get("/api/projects/:project_id/tags", handlers.GetAllTagsOf)
|
||||||
|
|
||||||
app.Post("/api/list", handlers.CreateList)
|
app.Post("/api/cards", handlers.CreateCard)
|
||||||
app.Get("/api/lists/:project_id", handlers.GetAllListsOf)
|
app.Get("/api/cards/:id", handlers.GetCard)
|
||||||
app.Get("/api/list/:id", handlers.GetList)
|
app.Put("/api/cards/:id", handlers.UpdateCard)
|
||||||
app.Delete("/api/list/:id", handlers.DeleteList)
|
app.Delete("/api/cards/:id", handlers.DeleteCard)
|
||||||
app.Put("/api/list/:id", handlers.UpdateList)
|
|
||||||
|
|
||||||
app.Post("/api/card", handlers.CreateCard)
|
app.Post("/api/tags", handlers.CreateTag)
|
||||||
app.Get("/api/cards/:project_id", handlers.GetAllCardsOf)
|
app.Get("/api/tags/:id", handlers.GetTag)
|
||||||
app.Get("/api/card/:id", handlers.GetCard)
|
app.Delete("/api/tags/:id", handlers.DeleteTag)
|
||||||
app.Delete("/api/card/:id", handlers.DeleteCard)
|
app.Put("/api/tags/:id", handlers.UpdateTag)
|
||||||
app.Put("/api/card/:id", handlers.UpdateCard)
|
|
||||||
|
|
||||||
app.Post("/api/tag", handlers.CreateTag)
|
app.Post("/api/cards/:card_id/tags/:tag_id", handlers.CreateTagOfCard)
|
||||||
app.Get("/api/tags/:project_id", handlers.GetAllTagsOf)
|
app.Get("/api/cards/:card_id/tags", handlers.GetAllTagsOfCard)
|
||||||
app.Get("/api/tag/:id", handlers.GetTag)
|
app.Put("/api/cards/:card_id/tags/:tag_id", handlers.UpdateTagOfCard)
|
||||||
app.Delete("/api/tag/:id", handlers.DeleteTag)
|
app.Delete("/api/cards/:card_id/tags/:tag_id", handlers.DeleteTagOfCard)
|
||||||
app.Put("/api/tag/:id", handlers.UpdateTag)
|
app.Delete("/api/cards/:card_id/tags", handlers.DeleteTagsOfCard)
|
||||||
|
|
||||||
app.Post("/api/cardtag", handlers.CreateTagOfCard)
|
|
||||||
app.Get("/api/cardtags/:card_id", handlers.GetAllTagsOfCard)
|
|
||||||
app.Delete("/api/cardtag/:card_id/:tag_id", handlers.DeleteTagOfCard)
|
|
||||||
app.Delete("/api/cardtags/:card_id", handlers.DeleteTagsOfCard)
|
|
||||||
app.Put("/api/cardtag/:card_id/:tag_id", handlers.UpdateTagOfCard)
|
|
||||||
|
|
||||||
log.Fatal(app.Listen(fmt.Sprintf(":%v", port)))
|
log.Fatal(app.Listen(fmt.Sprintf(":%v", port)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SendHAL(c *fiber.Ctx, status int, data fiber.Map) error {
|
||||||
|
if err := c.JSON(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Status(status)
|
||||||
|
c.Context().SetContentType("application/hal+json")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func HALProjectLinks(id int) fiber.Map {
|
||||||
|
return fiber.Map{
|
||||||
|
"_links": fiber.Map{
|
||||||
|
"self": fiber.Map{"href": fmt.Sprintf("/api/projects/%v", id)},
|
||||||
|
"cards": fiber.Map{"href": fmt.Sprintf("/api/projects/%v/cards", id)},
|
||||||
|
"tags": fiber.Map{"href": fmt.Sprintf("/api/projects/%v/tags", id)},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue