From c7b10d24be1336cd8e04daaaf11d1af9a306db2a Mon Sep 17 00:00:00 2001 From: kalipso Date: Mon, 3 Mar 2025 13:49:36 +0100 Subject: [PATCH] add tags --- controllers/shopItemController.go | 130 +++++++++++++++++++++++++---- main.go | 2 + models/shopItem.go | 29 +------ repositories/repository.go | 4 +- repositories/shopItemRepository.go | 7 +- services/shopItemService.go | 28 ++++--- views/additem.html | 18 +--- 7 files changed, 147 insertions(+), 71 deletions(-) diff --git a/controllers/shopItemController.go b/controllers/shopItemController.go index 6d874d7..e8317b2 100644 --- a/controllers/shopItemController.go +++ b/controllers/shopItemController.go @@ -8,6 +8,7 @@ import ( "github.com/gin-gonic/gin" "example.com/gin/test/models" + //"example.com/gin/test/services" "example.com/gin/test/repositories" ) @@ -24,6 +25,8 @@ type ShopItemController interface { ShopItemView(*gin.Context) AddItemView(*gin.Context) AddItemHandler(*gin.Context) + CreateTag(*gin.Context) + GetAllTags(*gin.Context) } type shopItemController struct {} @@ -54,26 +57,60 @@ func (rc *shopItemController) GetById(c *gin.Context) { ReplyOK(c, shopItem) } -func (rc *shopItemController) Create(c *gin.Context) { - shopItem, err := models.NewShopItem(c) +func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.ShopItem, error) { + name := ctx.PostForm("name") + abstract := ctx.PostForm("abstract") + description := ctx.PostForm("description") + priceStr := ctx.PostForm("price") + tagIds := ctx.PostFormArray("tags[]") - if err != nil { - ReplyError(c, err) + if name == "" || description == "" { + return models.ShopItem{}, fmt.Errorf("Name or description empty") } - _, err = repositories.ShopItems.Create(shopItem) + // Convert the price string to float64 + price, err := strconv.ParseFloat(priceStr, 64) + if err != nil { + return models.ShopItem{}, fmt.Errorf("Could not parse price") + } + + shopItem := models.ShopItem{ + Name: name, + Abstract: abstract, + Description: description, + Price: price, + IsPublic: true, + } + + for _, tagId := range tagIds { + tag, err := repositories.Tags.GetById(tagId) + + if err != nil { + return models.ShopItem{}, fmt.Errorf("Could not get tag by id") + } + + shopItem.Tags = append(shopItem.Tags, tag) + } + + return shopItem, nil + //return services.ShopItems.NewShopItem(name, abstract, description, price, tagIds) +} + + +func (rc *shopItemController) Create(c *gin.Context) { + shopItem, err := rc.NewShopItemFromForm(c) + if err != nil { ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err)) return } - //userID := user.(models.User).ID - //rc.DB.Model(&models.shopItem{}).Where("id = ?"), room.ID).Association("Admins").Append(&models.User{ID: userID}) + _, err = repositories.ShopItems.Create(shopItem) - //if result.Error != nil { - // ReplyError(c, fmt.Errorf("shopItem creation failed: %s", result.Error)) - // return - //} + if err != nil { + ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err)) + return + } ReplyOK(c, "shopItem was created") } @@ -87,7 +124,7 @@ func (rc *shopItemController) Update(c *gin.Context) { return } - shopItem, err := models.NewShopItem(c) + shopItem, err := rc.NewShopItemFromForm(c) if err != nil { ReplyError(c, err) @@ -119,8 +156,20 @@ func (rc *shopItemController) Delete(c *gin.Context) { func (rc *shopItemController) ShopItemView(c *gin.Context) { shopItem, err := repositories.ShopItems.GetById(c.Param("id")) + if err != nil { + c.HTML(http.StatusBadRequest, "shopitem.html", gin.H{ "data": gin.H{ "error": err } }) + } + + //TODO: get tags by item + tags, err := repositories.Tags.GetAll() + + if err != nil { + c.HTML(http.StatusBadRequest, "shopitem.html", gin.H{ "data": gin.H{ "error": err } }) + } + data := CreateSessionData(c, gin.H{ "shopItem": shopItem, + "tags": tags, }) if err != nil { @@ -132,9 +181,16 @@ func (rc *shopItemController) ShopItemView(c *gin.Context) { func (rc *shopItemController) AddItemView(c *gin.Context) { + tags, err := repositories.Tags.GetAll() + + if err != nil { + c.HTML(http.StatusBadRequest, "additem.html", gin.H{ "error": err }) + } + data := CreateSessionData(c, gin.H{ "error": "", "success": "", + "tags": tags, }) c.HTML(http.StatusOK, "additem.html", data) @@ -142,10 +198,18 @@ func (rc *shopItemController) AddItemView(c *gin.Context) { func (rc *shopItemController) AddItemHandler(c *gin.Context) { - shopItem, err := models.NewShopItem(c) + shopItem, err := rc.NewShopItemFromForm(c) if err != nil { - ReplyError(c, err) + c.HTML(http.StatusBadRequest, "additem.html", gin.H{ "error": err }) + return + } + + tags, err := repositories.Tags.GetAll() + + if err != nil { + c.HTML(http.StatusBadRequest, "additem.html", gin.H{ "error": err }) + return } _, err = repositories.ShopItems.Create(shopItem) @@ -153,6 +217,7 @@ func (rc *shopItemController) AddItemHandler(c *gin.Context) { data := CreateSessionData(c, gin.H{ "error": err, "success": "", + "tags": tags, }) c.HTML(http.StatusOK, "additem.html", data) @@ -162,11 +227,48 @@ func (rc *shopItemController) AddItemHandler(c *gin.Context) { data := CreateSessionData(c, gin.H{ "error": "", "success": fmt.Sprintf("Item '%s' Registered", shopItem.Name), + "tags": tags, }) c.HTML(http.StatusOK, "additem.html", data) } +func (rc *shopItemController) CreateTag(c *gin.Context) { + tag, err := models.NewTagByJson(c) + + if err != nil { + ReplyError(c, err) + } + + _, err = repositories.Tags.Create(tag) + if err != nil { + ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err)) + return + } + + //userID := user.(models.User).ID + //rc.DB.Model(&models.shopItem{}).Where("id = ?"), room.ID).Association("Admins").Append(&models.User{ID: userID}) + + //if result.Error != nil { + // ReplyError(c, fmt.Errorf("shopItem creation failed: %s", result.Error)) + // return + //} + + ReplyOK(c, fmt.Sprintf("tag '%s' was created", tag.Name)) + +} + +func (rc *shopItemController) GetAllTags(c *gin.Context) { + tags, err := repositories.Tags.GetAll() + + if err != nil { + ReplyError(c, fmt.Errorf("Could not query Tags")) + return + } + + c.JSON(http.StatusOK, tags) +} + func ReplyError(ctx *gin.Context, err error) { ctx.JSON(http.StatusBadRequest, gin.H{ "error": err.Error() }) } diff --git a/main.go b/main.go index 5218b5e..96d3c6c 100644 --- a/main.go +++ b/main.go @@ -57,6 +57,8 @@ func main() { apiRoutes := server.Group("/api") //apiRoutes.Use(middlewares.BasicAuth()) { + apiRoutes.POST("/tags", authValidator.RequireAuth, shopItemController.CreateTag) + apiRoutes.GET("/tags", authValidator.OptionalAuth, shopItemController.GetAllTags) apiRoutes.POST("/shopitems", authValidator.RequireAuth, shopItemController.Create) apiRoutes.GET("/shopitems", authValidator.OptionalAuth, shopItemController.GetAll) apiRoutes.GET("/shopitems/:id", authValidator.OptionalAuth, shopItemController.GetById) diff --git a/models/shopItem.go b/models/shopItem.go index de8d38f..935a5d0 100644 --- a/models/shopItem.go +++ b/models/shopItem.go @@ -1,42 +1,17 @@ package models import ( - "fmt" - "strconv" "gorm.io/gorm" - "github.com/gin-gonic/gin" ) type ShopItem struct { gorm.Model Name string `json:"name" binding:"required" gorm:"unique;not null"` + Abstract string `json:"Abstract" binding:"required"` Description string `json:"description" binding:"required"` Price float64 `json:"price" binding:"required"` IsPublic bool `json:"isPublic" gorm:"default:true"` + Tags []Tag `gorm:"many2many:item_tags;"` //Images gin.multipart.FileHeader `` } -func NewShopItem(ctx *gin.Context) (ShopItem, error) { - name := ctx.PostForm("name") - description := ctx.PostForm("description") - priceStr := ctx.PostForm("price") - - // Convert the price string to float64 - price, err := strconv.ParseFloat(priceStr, 64) - if err != nil { - return ShopItem{}, fmt.Errorf("Could not parse price") - } - - shopItem := ShopItem{ - Name: name, - Description: description, - Price: price, - IsPublic: true, - } - - if name == "" || description == "" { - return ShopItem{}, fmt.Errorf("Name or description empty") - } - - return shopItem, nil -} diff --git a/repositories/repository.go b/repositories/repository.go index a06cec7..c284503 100644 --- a/repositories/repository.go +++ b/repositories/repository.go @@ -11,6 +11,7 @@ import( var( ShopItems ShopItemRepository Users UserRepository + Tags TagRepository ) func InitRepositories() { @@ -19,11 +20,12 @@ func InitRepositories() { panic("failed to connect to database") } - err = db.AutoMigrate(&models.ShopItem{}, &models.User{}, &models.Booking{}) + err = db.AutoMigrate(&models.ShopItem{}, &models.User{}, &models.Tag{}) if err != nil { panic("failed to migrate database") } ShopItems = NewGORMShopItemRepository(db) Users = NewGORMUserRepository(db) + Tags = NewGORMTagRepository(db) } diff --git a/repositories/shopItemRepository.go b/repositories/shopItemRepository.go index fecec87..e1340a1 100644 --- a/repositories/shopItemRepository.go +++ b/repositories/shopItemRepository.go @@ -12,6 +12,7 @@ type ShopItemRepository interface { GetAll() ([]models.ShopItem, error) GetAllPublic() ([]models.ShopItem, error) GetById(string) (models.ShopItem, error) + //GetByTagId(string) ([]models.ShopItem, error) Update(models.ShopItem) (models.ShopItem, error) DeleteById(string) error } @@ -37,14 +38,14 @@ func (r *GORMShopItemRepository) Create(shopItem models.ShopItem) (models.ShopIt func (r *GORMShopItemRepository) GetAll() ([]models.ShopItem, error) { var shopItems []models.ShopItem - result := r.DB.Find(&shopItems) + result := r.DB.Preload("Tags").Find(&shopItems) return shopItems, result.Error } func (r *GORMShopItemRepository) GetAllPublic() ([]models.ShopItem, error) { var shopItems []models.ShopItem - result := r.DB.Where("is_public = 1").Find(&shopItems) + result := r.DB.Preload("Tags").Where("is_public = 1").Find(&shopItems) return shopItems, result.Error @@ -58,7 +59,7 @@ func (r *GORMShopItemRepository) GetById(id string) (models.ShopItem, error) { } var shopItem models.ShopItem - result := r.DB.First(&shopItem, uint(shopItemId)) + result := r.DB.Preload("Tags").First(&shopItem, uint(shopItemId)) if result.Error != nil { return models.ShopItem{}, result.Error diff --git a/services/shopItemService.go b/services/shopItemService.go index 2557c39..d1618c4 100644 --- a/services/shopItemService.go +++ b/services/shopItemService.go @@ -1,7 +1,7 @@ package services import( - "golang.org/x/crypto/bcrypt" + "fmt" "example.com/gin/test/models" "example.com/gin/test/repositories" @@ -13,20 +13,24 @@ var( type ShopItemService struct {} -func (u *ShopItemService) Create(name string, email string, password string) (models.User, error) { - //hash pw - hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) - - if err != nil { - return models.User{}, err +func (u *ShopItemService) NewShopItem(name string, abstract string, description string, price float64, tagIds []string) (models.ShopItem, error) { + shopItem := models.ShopItem{ + Name: name, + Abstract: abstract, + Description: description, + Price: price, + IsPublic: true, } - user := models.User{Name: name, Email: email, Password: string(hash)} - _, err = repositories.Users.Create(user) + for _, tagId := range tagIds { + tag, err := repositories.Tags.GetById(tagId) - if err != nil { - return models.User{}, err + if err != nil { + return models.ShopItem{}, fmt.Errorf("Could not get tag by id") + } + + shopItem.Tags = append(shopItem.Tags, tag) } - return user, nil + return repositories.ShopItems.Create(shopItem) } diff --git a/views/additem.html b/views/additem.html index 084d995..552c32d 100644 --- a/views/additem.html +++ b/views/additem.html @@ -31,22 +31,12 @@
+ {{ range .data.tags }} - - - + {{ end }}