API consistence

This commit is contained in:
Brieuc Dubois 2023-12-30 16:03:44 +01:00
parent 70c8f93c69
commit 47c8184967
12 changed files with 451 additions and 249 deletions

View File

@ -16,7 +16,7 @@ func CreateCard(c types.Card) (int, error) {
return int(id), nil return int(id), nil
} }
func GetAllCardsOf(projectID int) ([]types.FullCard, error) { func GetProjectsCards(projectID int) ([]types.FullCard, error) {
rows, err := db.Query("SELECT * FROM cards WHERE project_id = ?", projectID) rows, err := db.Query("SELECT * FROM cards WHERE project_id = ?", projectID)
if err != nil { if err != nil {
return nil, err return nil, err
@ -30,7 +30,7 @@ func GetAllCardsOf(projectID int) ([]types.FullCard, error) {
return nil, err return nil, err
} }
tags, err := GetAllTagsOfCard(c.ID, projectID) tags, err := GetCardTags(c.ID, projectID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -47,14 +47,21 @@ func GetAllCardsOf(projectID int) ([]types.FullCard, error) {
} }
func GetCard(id int) (*types.FullCard, error) { func GetCard(id int) (*types.FullCard, error) {
var c types.FullCard
err := db.QueryRow("SELECT * FROM cards WHERE id = ?", id).Scan(&c.ID, &c.ProjectID, &c.Title, &c.Content) rows, err := db.Query("SELECT * FROM cards WHERE id = ?", id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close()
tags, err := GetAllTagsOfCard(id, c.ProjectID) if !rows.Next() {
return nil, nil
}
var c types.FullCard
rows.Scan(&c.ID, &c.ProjectID, &c.Title, &c.Content)
tags, err := GetCardTags(id, c.ProjectID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -63,12 +70,28 @@ func GetCard(id int) (*types.FullCard, error) {
return &c, nil return &c, nil
} }
func DeleteCard(id int) error { func DeleteCard(id int) (int64, error) {
_, err := db.Exec("DELETE FROM cards WHERE id = ?", id) res, err := db.Exec("DELETE FROM cards WHERE id = ?", id)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }
func UpdateCard(c types.Card) error { func UpdateCard(c types.Card) (int64, error) {
_, err := db.Exec("UPDATE cards SET project_id = ?, title = ?, content = ? WHERE id = ?", c.ProjectID, c.Title, c.Content, c.ID) res, err := db.Exec("UPDATE cards SET project_id = ?, title = ?, content = ? WHERE id = ?", c.ProjectID, c.Title, c.Content, c.ID)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
}
func ExistCard(id int) (bool, error) {
var count int
err := db.QueryRow("SELECT COUNT(*) FROM cards WHERE id = ?", id).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
} }

View File

@ -4,12 +4,12 @@ import (
"git.bhasher.com/bhasher/focus/backend/types" "git.bhasher.com/bhasher/focus/backend/types"
) )
func AddTagToCard(ct types.CardTag) error { func CreateCardTag(ct types.CardTag) error {
_, err := db.Exec("INSERT INTO cardtags (card_id, tag_id, value) VALUES (?, ?, ?)", ct.CardID, ct.TagID, ct.Value) _, err := db.Exec("INSERT INTO cardtags (card_id, tag_id, value) VALUES (?, ?, ?)", ct.CardID, ct.TagID, ct.Value)
return err return err
} }
func GetAllTagsOfCard(cardID int, projectID int) ([]types.FullCardTag, error) { func GetCardTags(cardID int, projectID int) ([]types.FullCardTag, error) {
if projectID < 0 { if projectID < 0 {
card, err := GetCard(cardID) card, err := GetCard(cardID)
if err != nil { if err != nil {
@ -44,17 +44,26 @@ func GetAllTagsOfCard(cardID int, projectID int) ([]types.FullCardTag, error) {
return cardtags, nil return cardtags, nil
} }
func DeleteTagOfCard(card_id int, tag_id int) error { func DeleteCardTag(card_id int, tag_id int) (int64, error) {
_, err := db.Exec("DELETE FROM cardtags WHERE card_id = ? AND tag_id = ?", card_id, tag_id) res, err := db.Exec("DELETE FROM cardtags WHERE card_id = ? AND tag_id = ?", card_id, tag_id)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }
func DeleteTagsOfCard(card_id int) error { func DeleteCardTags(card_id int) (int64, error) {
_, err := db.Exec("DELETE FROM cardtags WHERE card_id = ?", card_id) res, err := db.Exec("DELETE FROM cardtags WHERE card_id = ?", card_id)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }
func UpdateTagOfCard(ct types.CardTag) error { func UpdateCardTag(ct types.CardTag) (int64, error) {
_, err := db.Exec("UPDATE cardtags SET value = ? WHERE card_id = ? AND tag_id = ?", ct.Value, ct.CardID, ct.TagID) res, err := db.Exec("UPDATE cardtags SET value = ? WHERE card_id = ? AND tag_id = ?", ct.Value, ct.CardID, ct.TagID)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }

View File

@ -43,6 +43,7 @@ func InitDB(driver string, connStr string) error {
card_id INTEGER, card_id INTEGER,
tag_id INTEGER, tag_id INTEGER,
value TEXT, value TEXT,
PRIMARY KEY(card_id, tag_id),
FOREIGN KEY(card_id) REFERENCES cards(id) FOREIGN KEY(card_id) REFERENCES cards(id)
FOREIGN KEY(tag_id) REFERENCES tags(id) FOREIGN KEY(tag_id) REFERENCES tags(id)
); );

View File

@ -44,22 +44,37 @@ func GetAllProjects() ([]types.Project, error) {
func GetProject(id int) (*types.Project, error) { func GetProject(id int) (*types.Project, error) {
var p types.Project var p types.Project
err := db.QueryRow("SELECT * FROM projects WHERE id = ?", id).Scan(&p.ID, &p.Title) rows, err := db.Query("SELECT * FROM projects WHERE id = ?", id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close()
if !rows.Next() {
return nil, nil
}
if err := rows.Scan(&p.ID, &p.Title); err != nil {
return nil, err
}
return &p, nil return &p, nil
} }
func DeleteProject(id int) error { func DeleteProject(id int) (int64, error) {
_, err := db.Exec("DELETE FROM projects WHERE id = ?", id) res, err := db.Exec("DELETE FROM projects WHERE id = ?", id)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }
func UpdateProject(p types.Project) error { func UpdateProject(p types.Project) (int64, error) {
_, err := db.Exec("UPDATE projects SET title = ? WHERE id = ?", p.Title, p.ID) res, err := db.Exec("UPDATE projects SET title = ? WHERE id = ?", p.Title, p.ID)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }
func ExistProject(id int) (bool, error) { func ExistProject(id int) (bool, error) {

View File

@ -16,7 +16,7 @@ func CreateTag(t types.Tag) (int, error) {
return int(id), nil return int(id), nil
} }
func GetAllTagsOf(projectID int) ([]types.Tag, error) { func GetProjectTags(projectID int) ([]types.Tag, error) {
rows, err := db.Query("SELECT * FROM tags WHERE project_id = ?", projectID) rows, err := db.Query("SELECT * FROM tags WHERE project_id = ?", projectID)
if err != nil { if err != nil {
return nil, err return nil, err
@ -42,20 +42,42 @@ func GetAllTagsOf(projectID int) ([]types.Tag, error) {
func GetTag(id int) (*types.Tag, error) { func GetTag(id int) (*types.Tag, error) {
var t types.Tag var t types.Tag
err := db.QueryRow("SELECT * FROM tags WHERE id = ?", id).Scan(&t.ID, &t.ProjectID, &t.Title, &t.Type) rows, err := db.Query("SELECT * FROM tags WHERE id = ?", id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !rows.Next() {
return nil, nil
}
rows.Scan(&t.ID, &t.ProjectID, &t.Title, &t.Type)
return &t, nil return &t, nil
} }
func DeleteTag(id int) error { func DeleteTag(id int) (int64, error) {
_, err := db.Exec("DELETE FROM tags WHERE id = ?", id) res, err := db.Exec("DELETE FROM tags WHERE id = ?", id)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
} }
func UpdateTag(t types.Tag) error { func UpdateTag(t types.Tag) (int64, error) {
_, err := db.Exec("UPDATE tags SET project_id = ?, title = ?, type = ? WHERE id = ?", t.ProjectID, t.Title, t.Type, t.ID) res, err := db.Exec("UPDATE tags SET project_id = ?, title = ?, type = ? WHERE id = ?", t.ProjectID, t.Title, t.Type, t.ID)
return err if err != nil {
return 0, err
}
return res.RowsAffected()
}
func ExistTag(id int) (bool, error) {
var count int
err := db.QueryRow("SELECT COUNT(*) FROM tas WHERE id = ?", id).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
} }

View File

@ -6,7 +6,6 @@ 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"
) )
@ -27,54 +26,85 @@ func CreateCard(c *fiber.Ctx) error {
}) })
} }
c.Status(fiber.StatusCreated) return c.Status(fiber.StatusCreated).JSON(fiber.Map{
c.Location(fmt.Sprintf("/api/cards/%v", id)) "id": id,
return c.JSON(fiber.Map{
"id": id,
"_links": utils.HALProjectLinks(id),
}) })
} }
func GetAllCardsOf(c *fiber.Ctx) error { func GetProjectCards(c *fiber.Ctx) error {
projectID, err := strconv.Atoi(c.Params("project_id")) projectID, err := strconv.Atoi(c.Params("project_id"))
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"status": "error", "error": "Invalid project_id", "trace": fmt.Sprint(err)}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Invalid project_id",
"trace": fmt.Sprint(err),
})
} }
projects, err := db.GetAllCardsOf(projectID) exists, err := db.ExistProject(projectID)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"status": "error", "error": "Cannot retrieve cards", "trace": fmt.Sprint(err)}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding project",
"trace": fmt.Sprint(err),
})
} }
return c.JSON(fiber.Map{"status": "ok", "data": projects}) if !exists {
return c.SendStatus(fiber.StatusNotFound)
}
cards, err := db.GetProjectsCards(projectID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve cards",
"trace": fmt.Sprint(err),
})
}
return c.Status(fiber.StatusOK).JSON(cards)
} }
func GetCard(c *fiber.Ctx) error { func GetCard(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id")) id, err := strconv.Atoi(c.Params("id"))
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Invalid card ID",
"trace": fmt.Sprint(err),
})
} }
card, err := db.GetCard(id) card, err := db.GetCard(id)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve card"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve card",
"trace": fmt.Sprint(err),
})
} }
if card == nil { if card == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Card not found"}) return c.SendStatus(fiber.StatusNotFound)
} }
return c.JSON(card) return c.Status(fiber.StatusOK).JSON(card)
} }
func DeleteCard(c *fiber.Ctx) error { func DeleteCard(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id")) id, err := strconv.Atoi(c.Params("id"))
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"status": "error", "error": "Invalid card ID", "trace": fmt.Sprint(err)}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Invalid card ID",
"trace": fmt.Sprint(err),
})
} }
err = db.DeleteCard(id) count, err := db.DeleteCard(id)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"status": "error", "error": "Cannot delete card", "trace": fmt.Sprint(err)}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot delete card",
"trace": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
} }
return c.SendStatus(fiber.StatusNoContent) return c.SendStatus(fiber.StatusNoContent)
@ -91,9 +121,16 @@ func UpdateCard(c *fiber.Ctx) error {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
} }
err = db.UpdateCard(card) count, err := db.UpdateCard(card)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot update card"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot update card",
"trace": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
} }
return c.SendStatus(fiber.StatusOK) return c.SendStatus(fiber.StatusOK)

View File

@ -0,0 +1,219 @@
package handlers
import (
"fmt"
"strconv"
"strings"
"git.bhasher.com/bhasher/focus/backend/db"
"git.bhasher.com/bhasher/focus/backend/types"
"github.com/gofiber/fiber/v2"
)
func CreateCardTag(c *fiber.Ctx) error {
cardID, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card_id"})
}
tagID, err := strconv.Atoi(c.Params("tag_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid tag_id"})
}
cardtag := types.CardTag{CardID: cardID, TagID: tagID}
if err := c.BodyParser(&cardtag); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
}
exist, err := db.ExistCard(cardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding card",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Card not found"})
}
exist, err = db.ExistTag(tagID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding tag",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Tag not found"})
}
err = db.CreateCardTag(cardtag)
if err != nil {
if strings.HasPrefix(err.Error(), "UNIQUE constraint failed") {
return c.SendStatus(fiber.StatusConflict)
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot add tag to card",
"trace": fmt.Sprint(err),
})
}
return c.SendStatus(fiber.StatusCreated)
}
func GetCardTags(c *fiber.Ctx) error {
cardID, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card_id"})
}
exist, err := db.ExistCard(cardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding card",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.SendStatus(fiber.StatusNotFound)
}
cardtags, err := db.GetCardTags(cardID, -1)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve tags of card",
"stack": fmt.Sprint(err),
})
}
return c.Status(fiber.StatusOK).JSON(cardtags)
}
func DeleteCardTag(c *fiber.Ctx) error {
cardID, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"})
}
tagID, err := strconv.Atoi(c.Params("tag_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid tag ID"})
}
exist, err := db.ExistCard(cardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding card",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Card not found"})
}
exist, err = db.ExistTag(tagID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding tag",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Tag not found"})
}
count, err := db.DeleteCardTag(cardID, tagID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot delete tag of card",
"stack": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.SendStatus(fiber.StatusNoContent)
}
func DeleteCardTags(c *fiber.Ctx) error {
cardID, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"})
}
exist, err := db.ExistCard(cardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding card",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Card not found"})
}
_, err = db.DeleteCardTags(cardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot delete tags of card",
"stack": fmt.Sprint(err),
})
}
return c.SendStatus(fiber.StatusNoContent)
}
func UpdateCardTag(c *fiber.Ctx) error {
cardID, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"})
}
tagID, err := strconv.Atoi(c.Params("tag_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid tag ID"})
}
cardtag := types.CardTag{CardID: cardID, TagID: tagID}
if err := c.BodyParser(&cardtag); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
}
exist, err := db.ExistCard(cardID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding card",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Card not found"})
}
exist, err = db.ExistTag(tagID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding tag",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Tag not found"})
}
count, err := db.UpdateCardTag(cardtag)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot update tag of card",
"stack": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.SendStatus(fiber.StatusNoContent)
}

View File

@ -1,95 +0,0 @@
package handlers
import (
"fmt"
"strconv"
"git.bhasher.com/bhasher/focus/backend/db"
"git.bhasher.com/bhasher/focus/backend/types"
"github.com/gofiber/fiber/v2"
)
func CreateTagOfCard(c *fiber.Ctx) error {
cardtag := types.CardTag{}
if err := c.BodyParser(&cardtag); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
}
err := db.AddTagToCard(cardtag)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot add tag to card"})
}
return c.SendStatus(fiber.StatusOK)
}
func GetAllTagsOfCard(c *fiber.Ctx) error {
cardID, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"status": "error", "error": "Invalid card_id"})
}
cardtags, err := db.GetAllTagsOfCard(cardID, -1)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"status": "error", "error": "Cannot retrieve tags of card", "stack": fmt.Sprint(err)})
}
return c.JSON(fiber.Map{"status": "ok", "data": cardtags})
}
func DeleteTagOfCard(c *fiber.Ctx) error {
card_id, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"})
}
tag_id, err := strconv.Atoi(c.Params("tag_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid tag ID"})
}
err = db.DeleteTagOfCard(card_id, tag_id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot delete tag of card"})
}
return c.SendStatus(fiber.StatusNoContent)
}
func DeleteTagsOfCard(c *fiber.Ctx) error {
card_id, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"})
}
err = db.DeleteTagsOfCard(card_id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot delete tags of card"})
}
return c.SendStatus(fiber.StatusNoContent)
}
func UpdateTagOfCard(c *fiber.Ctx) error {
card_id, err := strconv.Atoi(c.Params("card_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid card ID"})
}
tag_id, err := strconv.Atoi(c.Params("tag_id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"status": "error", "error": "Invalid tag ID", "stack": fmt.Sprint(err)})
}
cardtag := types.CardTag{CardID: card_id, TagID: tag_id}
if err := c.BodyParser(&cardtag); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
}
err = db.UpdateTagOfCard(cardtag)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot update tag of card"})
}
return c.SendStatus(fiber.StatusOK)
}

View File

@ -5,7 +5,6 @@ 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"
) )
@ -18,22 +17,7 @@ func GetAllProjects(c *fiber.Ctx) error {
}) })
} }
halProjects := make([]fiber.Map, len(projects)) return c.Status(fiber.StatusOK).JSON(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 {
@ -53,10 +37,7 @@ func GetProject(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusNotFound) return c.SendStatus(fiber.StatusNotFound)
} }
return utils.SendHAL(c, fiber.StatusOK, fiber.Map{ return c.Status(fiber.StatusOK).JSON(project)
"project": project,
"_links": utils.HALProjectLinks(project.ID),
})
} }
func CreateProject(c *fiber.Ctx) error { func CreateProject(c *fiber.Ctx) error {
@ -73,10 +54,8 @@ func CreateProject(c *fiber.Ctx) error {
}) })
} }
c.Location(fmt.Sprintf("/api/projects/%v", id)) return c.Status(fiber.StatusCreated).JSON(fiber.Map{
return utils.SendHAL(c, fiber.StatusCreated, fiber.Map{ "id": id,
"id": id,
"_links": utils.HALProjectLinks(id),
}) })
} }
@ -91,19 +70,7 @@ 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"})
} }
exists, err := db.ExistProject(id) count, err := db.UpdateProject(p)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding project",
"trace": fmt.Sprint(err),
})
}
if !exists {
return c.SendStatus(fiber.StatusNotFound)
}
err = db.UpdateProject(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",
@ -111,6 +78,10 @@ func UpdateProject(c *fiber.Ctx) error {
}) })
} }
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.SendStatus(fiber.StatusNoContent) return c.SendStatus(fiber.StatusNoContent)
} }
@ -120,19 +91,7 @@ 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"})
} }
exists, err := db.ExistProject(id) count, err := db.DeleteProject(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding project",
"trace": fmt.Sprint(err),
})
}
if !exists {
return c.SendStatus(fiber.StatusNotFound)
}
err = db.DeleteProject(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",
@ -140,5 +99,9 @@ func DeleteProject(c *fiber.Ctx) error {
}) })
} }
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.SendStatus(fiber.StatusNoContent) return c.SendStatus(fiber.StatusNoContent)
} }

View File

@ -17,24 +17,42 @@ func CreateTag(c *fiber.Ctx) error {
id, err := db.CreateTag(tag) id, err := db.CreateTag(tag)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot create tag", "trace": fmt.Sprint(err)}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot create tag",
"trace": fmt.Sprint(err),
})
} }
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"id": id}) return c.Status(fiber.StatusCreated).JSON(fiber.Map{"id": id})
} }
func GetAllTagsOf(c *fiber.Ctx) error { func GetProjectTags(c *fiber.Ctx) error {
projectID, err := strconv.Atoi(c.Params("project_id")) projectID, err := strconv.Atoi(c.Params("project_id"))
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"status": "error", "error": "Invalid project_id"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project_id"})
} }
projects, err := db.GetAllTagsOf(projectID) exists, err := db.ExistProject(projectID)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve tags"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding project",
"trace": fmt.Sprint(err),
})
} }
return c.JSON(fiber.Map{"status": "ok", "data": projects}) if !exists {
return c.SendStatus(fiber.StatusNotFound)
}
tags, err := db.GetProjectTags(projectID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve tags",
"trace": fmt.Sprint(err),
})
}
return c.JSON(tags)
} }
func GetTag(c *fiber.Ctx) error { func GetTag(c *fiber.Ctx) error {
@ -45,10 +63,13 @@ func GetTag(c *fiber.Ctx) error {
tag, err := db.GetTag(id) tag, err := db.GetTag(id)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot retrieve tag"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve tag",
"trace": fmt.Sprint(err),
})
} }
if tag == nil { if tag == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Tag not found"}) return c.SendStatus(fiber.StatusNotFound)
} }
return c.JSON(tag) return c.JSON(tag)
@ -60,9 +81,16 @@ func DeleteTag(c *fiber.Ctx) error {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid tag ID"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid tag ID"})
} }
err = db.DeleteTag(id) count, err := db.DeleteTag(id)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot delete tag"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot delete tag",
"trace": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
} }
return c.SendStatus(fiber.StatusNoContent) return c.SendStatus(fiber.StatusNoContent)
@ -79,9 +107,16 @@ func UpdateTag(c *fiber.Ctx) error {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"}) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot parse request"})
} }
err = db.UpdateTag(tag) count, err := db.UpdateTag(tag)
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot update tag"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot update tag",
"trace": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
} }
return c.SendStatus(fiber.StatusOK) return c.SendStatus(fiber.StatusOK)

View File

@ -35,8 +35,8 @@ func main() {
app.Get("/api/projects/:id", handlers.GetProject) app.Get("/api/projects/:id", handlers.GetProject)
app.Put("/api/projects/:id", handlers.UpdateProject) app.Put("/api/projects/:id", handlers.UpdateProject)
app.Delete("/api/projects/: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/cards", handlers.GetProjectCards)
app.Get("/api/projects/:project_id/tags", handlers.GetAllTagsOf) app.Get("/api/projects/:project_id/tags", handlers.GetProjectTags)
app.Post("/api/cards", handlers.CreateCard) app.Post("/api/cards", handlers.CreateCard)
app.Get("/api/cards/:id", handlers.GetCard) app.Get("/api/cards/:id", handlers.GetCard)
@ -48,11 +48,11 @@ func main() {
app.Delete("/api/tags/:id", handlers.DeleteTag) app.Delete("/api/tags/:id", handlers.DeleteTag)
app.Put("/api/tags/:id", handlers.UpdateTag) app.Put("/api/tags/:id", handlers.UpdateTag)
app.Post("/api/cards/:card_id/tags/:tag_id", handlers.CreateTagOfCard) app.Post("/api/cards/:card_id/tags/:tag_id", handlers.CreateCardTag)
app.Get("/api/cards/:card_id/tags", handlers.GetAllTagsOfCard) app.Get("/api/cards/:card_id/tags", handlers.GetCardTags)
app.Put("/api/cards/:card_id/tags/:tag_id", handlers.UpdateTagOfCard) app.Put("/api/cards/:card_id/tags/:tag_id", handlers.UpdateCardTag)
app.Delete("/api/cards/:card_id/tags/:tag_id", handlers.DeleteTagOfCard) app.Delete("/api/cards/:card_id/tags/:tag_id", handlers.DeleteCardTag)
app.Delete("/api/cards/:card_id/tags", handlers.DeleteTagsOfCard) app.Delete("/api/cards/:card_id/tags", handlers.DeleteCardTags)
log.Fatal(app.Listen(fmt.Sprintf(":%v", port))) log.Fatal(app.Listen(fmt.Sprintf(":%v", port)))
} }

View File

@ -1,27 +0,0 @@
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)},
},
}
}