Backend for filters

This commit is contained in:
Brieuc Dubois 2024-01-10 15:35:12 +01:00
parent b6e36fdf00
commit 7404aed139
7 changed files with 256 additions and 1 deletions

76
backend/db/filters.go Normal file
View File

@ -0,0 +1,76 @@
package db
import "git.bhasher.com/bhasher/focus/backend/types"
func CreateFilter(filter types.Filter) (int, error) {
res, err := db.Exec("INSERT INTO filters (view_id, tag_id, filter_type, option_id) VALUES (?, ?, ?, ?)", filter.ViewID, filter.TagID, filter.FilterType, filter.OptionID)
if err != nil {
return 0, err
}
id, err := res.LastInsertId()
if err != nil {
return 0, err
}
return int(id), nil
}
func GetViewFilters(viewID int) ([]types.Filter, error) {
rows, err := db.Query("SELECT * FROM filters WHERE view_id = ?", viewID)
if err != nil {
return nil, err
}
defer rows.Close()
var filters []types.Filter
for rows.Next() {
var f types.Filter
if err := rows.Scan(&f.ID, &f.ViewID, &f.TagID, &f.FilterType, &f.OptionID); err != nil {
return nil, err
}
filters = append(filters, f)
}
if err = rows.Err(); err != nil {
return nil, err
}
return filters, nil
}
func GetFilter(id int) (*types.Filter, error) {
rows, err := db.Query("SELECT * FROM filters WHERE id = ?", id)
if err != nil {
return nil, err
}
defer rows.Close()
if !rows.Next() {
return nil, nil
}
var f types.Filter
rows.Scan(&f.ID, &f.ViewID, &f.TagID, &f.FilterType, &f.OptionID)
return &f, nil
}
func UpdateFilter(f types.Filter) (int64, error) {
res, err := db.Exec("UPDATE filters SET view_id = ?, tag_id = ?, filter_type = ?, option_id = ? WHERE id = ?", f.ViewID, f.TagID, f.FilterType, f.OptionID, f.ID)
if err != nil {
return 0, err
}
return res.RowsAffected()
}
func DeleteFilter(id int) (int64, error) {
res, err := db.Exec("DELETE FROM filters WHERE id = ?", id)
if err != nil {
return 0, err
}
return res.RowsAffected()
}

View File

@ -67,6 +67,17 @@ func InitDB(driver string, connStr string) error {
FOREIGN KEY(secondary_tag_id) REFERENCES tags(id)
);
CREATE TABLE IF NOT EXISTS filters (
id INTEGER PRIMARY KEY AUTOINCREMENT,
view_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
filter_type INTEGER NOT NULL,
option_id INTEGER,
FOREIGN KEY(view_id) REFERENCES views(id),
FOREIGN KEY(tag_id) REFERENCES tags(id),
FOREIGN KEY(option_id) REFERENCES tagsoptions(id)
);
INSERT INTO schema_version (version)
SELECT ? WHERE NOT EXISTS (SELECT 1 FROM schema_version);
`, DB_VERSION)

View File

@ -74,3 +74,13 @@ func DeleteView(id int) (int64, error) {
return res.RowsAffected()
}
func ExistView(id int) (bool, error) {
var count int
err := db.QueryRow("SELECT COUNT(*) FROM views WHERE id = ?", id).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
}

131
backend/handlers/filters.go Normal file
View File

@ -0,0 +1,131 @@
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 filtersRouter(router fiber.Router) error {
router.Post("/", CreateFilter)
router.Get("/:id", GetFilter)
router.Put("/:id", UpdateFilter)
router.Delete("/:id", DeleteFilter)
return nil
}
func CreateFilter(c *fiber.Ctx) error {
filter := types.Filter{}
if err := c.BodyParser(&filter); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Cannot parse request",
"trace": fmt.Sprint(err),
})
}
exist, err := db.ExistView(filter.ViewID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding view",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "View not found"})
}
id, err := db.CreateFilter(filter)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot create filter",
"trace": fmt.Sprint(err),
})
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
"id": id,
})
}
func GetFilter(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid filter ID"})
}
filter, err := db.GetFilter(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve filter",
"trace": fmt.Sprint(err),
})
}
if filter == nil {
return c.SendStatus(fiber.StatusNotFound)
}
return c.Status(fiber.StatusOK).JSON(filter)
}
func UpdateFilter(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid filter ID"})
}
filter := types.Filter{ID: id}
if err := c.BodyParser(&filter); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Cannot parse request",
"trace": fmt.Sprint(err),
})
}
exist, err := db.ExistView(filter.ViewID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error finding view",
"trace": fmt.Sprint(err),
})
}
if !exist {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "View not found"})
}
count, err := db.UpdateFilter(filter)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot update filter",
"trace": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.SendStatus(fiber.StatusNoContent)
}
func DeleteFilter(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid filter ID"})
}
count, err := db.DeleteFilter(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot delete filter",
"trace": fmt.Sprint(err),
})
}
if count == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.SendStatus(fiber.StatusNoContent)
}

View File

@ -11,6 +11,7 @@ func v1Router(router fiber.Router) error {
cardsRouter(router.Group("/cards"))
tagsRouter(router.Group("/tags"))
viewsRouter(router.Group("/views"))
filtersRouter(router.Group("/filters"))
return nil
}

View File

@ -14,7 +14,7 @@ func viewsRouter(router fiber.Router) error {
router.Get("/:id", GetView)
router.Put("/:id", UpdateView)
router.Delete("/:id", DeleteView)
router.Get("/:id/filters", GetView)
return nil
}
@ -108,3 +108,20 @@ func DeleteView(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusNoContent)
}
func GetViewFilters(c *fiber.Ctx) error {
id, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid view ID"})
}
filters, err := db.GetViewFilters(id)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Cannot retrieve view filters",
"trace": fmt.Sprint(err),
})
}
return c.Status(fiber.StatusOK).JSON(filters)
}

9
backend/types/filter.go Normal file
View File

@ -0,0 +1,9 @@
package types
type Filter struct {
ID int `json:"id"`
ViewID int `json:"view_id"`
TagID int `json:"tag_id"`
FilterType int `json:"filter_type"`
OptionID int `json:"option_id"`
}