From 1efac96704cbf577d66fc494eb96c4724dba06bd Mon Sep 17 00:00:00 2001 From: clz Date: Fri, 2 Jun 2023 16:07:54 +0800 Subject: [PATCH] feat: label curd --- go.mod | 2 + go.sum | 4 ++ internal/label/domain.go | 20 ++++++- internal/label/handle.go | 100 +++++++++++++++++++++++++++++++++++ internal/label/middleware.go | 37 +++++++++++++ internal/label/reposiroty.go | 18 ++++--- internal/label/service.go | 26 +++++---- 7 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 internal/label/middleware.go diff --git a/go.mod b/go.mod index 162589a..949e1a0 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,14 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/philhofer/fwd v1.1.2 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/samber/lo v1.38.1 // indirect github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect github.com/tinylib/msgp v1.1.8 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.45.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect golang.org/x/sys v0.7.0 // indirect gorm.io/driver/sqlite v1.5.1 // indirect gorm.io/gorm v1.25.1 // indirect diff --git a/go.sum b/go.sum index fc31556..7d133a4 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4= github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= @@ -61,6 +63,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= diff --git a/internal/label/domain.go b/internal/label/domain.go index eebfcbe..d8a3e7c 100644 --- a/internal/label/domain.go +++ b/internal/label/domain.go @@ -12,6 +12,22 @@ type Label struct { Count int } +type LabelDTO struct { + ID int `json:"id"` + Type string `json:"type"` + Name string `json:"name"` + Count int `json:"count"` +} + +func (l *Label) Dto() interface{} { + return LabelDTO{ + ID: int(l.ID), + Type: l.Type, + Name: l.Name, + Count: l.Count, + } +} + type LabelRepository interface { GetLabels(ctx context.Context) ([]Label, error) GetLabelById(ctx context.Context, id int) (*Label, error) @@ -21,8 +37,8 @@ type LabelRepository interface { } type LabelService interface { - GetLabels(ctx context.Context) ([]Label, error) - GetLabelById(ctx context.Context, id int) (*Label, error) + GetLabels(ctx context.Context) ([]interface{}, error) + GetLabelById(ctx context.Context, id int) (interface{}, error) CreateLabel(ctx context.Context, label *Label) error UpdateLabel(ctx context.Context, label *Label) error DeleteLabel(ctx context.Context, id int) error diff --git a/internal/label/handle.go b/internal/label/handle.go index cb50e8e..fafaa5c 100644 --- a/internal/label/handle.go +++ b/internal/label/handle.go @@ -3,6 +3,7 @@ package label import ( "context" "github.com/gofiber/fiber/v2" + "gorm.io/gorm" ) type LabelHandler struct { @@ -15,6 +16,11 @@ func NewLabelHandler(labelRoute fiber.Router, ls LabelService) { } labelRoute.Get("", handler.getLabels) + labelRoute.Post("", handler.createLabel) + + labelRoute.Get("/:labelID", handler.getLabelById) + labelRoute.Put("/:labelID", handler.checkIfLabelExistsMiddleware, handler.updateLabel) + labelRoute.Delete("/:labelID", handler.checkIfLabelExistsMiddleware, handler.deleteLabel) } func (h *LabelHandler) getLabels(c *fiber.Ctx) error { @@ -32,3 +38,97 @@ func (h *LabelHandler) getLabels(c *fiber.Ctx) error { "data": labels, }) } + +func (h *LabelHandler) createLabel(c *fiber.Ctx) error { + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + label := &Label{} + + if err := c.BodyParser(label); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + err := h.labelService.CreateLabel(customContext, label) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "Label has been created successfully!", + }) +} + +func (h *LabelHandler) getLabelById(c *fiber.Ctx) error { + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + targetLabelId, err := c.ParamsInt("labelID") + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "Please provide a valid label id", + }) + } + label, err := h.labelService.GetLabelById(customContext, targetLabelId) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "data": label, + }) +} + +func (h *LabelHandler) deleteLabel(c *fiber.Ctx) error { + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + targetLabelId := c.Locals("labelID").(int) + err := h.labelService.DeleteLabel(customContext, targetLabelId) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + return c.SendStatus(fiber.StatusNoContent) +} + +func (h *LabelHandler) updateLabel(c *fiber.Ctx) error { + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + targetLabelId := c.Locals("labelID").(int) + label := &Label{Model: gorm.Model{ID: uint(targetLabelId)}} + + if err := c.BodyParser(label); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + err := h.labelService.UpdateLabel(customContext, label) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "Label has been updated successfully!", + }) +} diff --git a/internal/label/middleware.go b/internal/label/middleware.go new file mode 100644 index 0000000..9a8c7db --- /dev/null +++ b/internal/label/middleware.go @@ -0,0 +1,37 @@ +package label + +import ( + "context" + "github.com/gofiber/fiber/v2" +) + +func (h *LabelHandler) checkIfLabelExistsMiddleware(c *fiber.Ctx) error { + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + targetLabelID, err := c.ParamsInt("labelID") + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "status": "fail", + "message": "Please specify a valid label ID!", + }) + } + + searchLabel, err := h.labelService.GetLabelById(customContext, targetLabelID) + if err != nil { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + if searchLabel == nil { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ + "status": "fail", + "message": "These is no label with this ID!", + }) + } + + c.Locals("labelID", targetLabelID) + return c.Next() + +} diff --git a/internal/label/reposiroty.go b/internal/label/reposiroty.go index e387454..16bf7af 100644 --- a/internal/label/reposiroty.go +++ b/internal/label/reposiroty.go @@ -25,21 +25,23 @@ func (s *sqliteRepository) GetLabels(ctx context.Context) ([]Label, error) { } func (s *sqliteRepository) GetLabelById(ctx context.Context, id int) (*Label, error) { - //TODO implement me - panic("implement me") + var label Label + res := s.First(&label, id) + if res.Error != nil { + return nil, res.Error + } + + return &label, nil } func (s *sqliteRepository) CreateLabel(ctx context.Context, label *Label) error { - //TODO implement me - panic("implement me") + return s.Create(label).Error } func (s *sqliteRepository) UpdateLabel(ctx context.Context, label *Label) error { - //TODO implement me - panic("implement me") + return s.Save(label).Error } func (s *sqliteRepository) DeleteLabel(ctx context.Context, id int) error { - //TODO implement me - panic("implement me") + return s.Delete(&Label{}, id).Error } diff --git a/internal/label/service.go b/internal/label/service.go index b194b09..faf5fda 100644 --- a/internal/label/service.go +++ b/internal/label/service.go @@ -2,6 +2,7 @@ package label import ( "context" + "github.com/samber/lo" ) type labelService struct { @@ -12,26 +13,29 @@ func NewLabelService(labelRepository LabelRepository) LabelService { return &labelService{labelRepository: labelRepository} } -func (l *labelService) GetLabels(ctx context.Context) ([]Label, error) { - return l.labelRepository.GetLabels(ctx) +func (l *labelService) GetLabels(ctx context.Context) ([]interface{}, error) { + labels, err := l.labelRepository.GetLabels(ctx) + + return lo.Map(labels, func(l Label, _ int) interface{} { return l.Dto() }), err } -func (l *labelService) GetLabelById(ctx context.Context, id int) (*Label, error) { - //TODO implement me - panic("implement me") +func (l *labelService) GetLabelById(ctx context.Context, id int) (interface{}, error) { + label, err := l.labelRepository.GetLabelById(ctx, id) + if err != nil { + return nil, err + } + + return label.Dto(), nil } func (l *labelService) CreateLabel(ctx context.Context, label *Label) error { - //TODO implement me - panic("implement me") + return l.labelRepository.CreateLabel(ctx, label) } func (l *labelService) UpdateLabel(ctx context.Context, label *Label) error { - //TODO implement me - panic("implement me") + return l.labelRepository.UpdateLabel(ctx, label) } func (l *labelService) DeleteLabel(ctx context.Context, id int) error { - //TODO implement me - panic("implement me") + return l.labelRepository.DeleteLabel(ctx, id) }