629 lines
14 KiB
Go
629 lines
14 KiB
Go
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"git.dynamicdiscord.de/kalipso/zineshop/models"
|
|
//"git.dynamicdiscord.de/kalipso/zineshop/services"
|
|
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
|
|
)
|
|
|
|
type CRUDController interface {
|
|
Create(*gin.Context)
|
|
GetAll(*gin.Context)
|
|
GetById(*gin.Context)
|
|
Update(*gin.Context)
|
|
Delete(*gin.Context)
|
|
}
|
|
|
|
type ShopItemController interface {
|
|
CRUDController
|
|
ShopItemView(*gin.Context)
|
|
AddItemView(*gin.Context)
|
|
AddItemHandler(*gin.Context)
|
|
AddItemsView(*gin.Context)
|
|
AddItemsHandler(*gin.Context)
|
|
EditItemView(*gin.Context)
|
|
EditItemHandler(*gin.Context)
|
|
DeleteItemView(*gin.Context)
|
|
DeleteItemHandler(*gin.Context)
|
|
}
|
|
|
|
type shopItemController struct{}
|
|
|
|
func NewShopItemController() ShopItemController {
|
|
return &shopItemController{}
|
|
}
|
|
|
|
func (rc *shopItemController) GetAll(c *gin.Context) {
|
|
shopItems, err := repositories.ShopItems.GetAll()
|
|
|
|
if err != nil {
|
|
ReplyError(c, fmt.Errorf("Could not query shopItems"))
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, shopItems)
|
|
}
|
|
|
|
func (rc *shopItemController) GetById(c *gin.Context) {
|
|
shopItem, err := repositories.ShopItems.GetById(c.Param("id"))
|
|
|
|
if err != nil {
|
|
ReplyError(c, fmt.Errorf("Could not query shopItem: %v", err))
|
|
return
|
|
}
|
|
|
|
ReplyOK(c, shopItem)
|
|
}
|
|
|
|
// this currently creates quite big preview images
|
|
// workaround is running the following command in the uploads folder:
|
|
// for file in *.png; do convert "$file" -resize 35% "$file"; done
|
|
func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.ShopItem, error) {
|
|
defaultImagePath := "static/img/zine.jpg"
|
|
name := ctx.PostForm("name")
|
|
abstract := ctx.PostForm("abstract")
|
|
description := ctx.PostForm("description")
|
|
categoryStr := ctx.PostForm("category")
|
|
variantNames := ctx.PostFormArray("variant-name[]")
|
|
variantValues := ctx.PostFormArray("variant-value[]")
|
|
tagIds := ctx.PostFormArray("tags[]")
|
|
image, err := ctx.FormFile("image")
|
|
dstImage := defaultImagePath
|
|
printMode := ctx.PostForm("print-mode")
|
|
|
|
if err == nil {
|
|
dstImage = filepath.Join("static/uploads", image.Filename)
|
|
if err := ctx.SaveUploadedFile(image, dstImage); err != nil {
|
|
return models.ShopItem{}, fmt.Errorf("Could not save image")
|
|
}
|
|
}
|
|
|
|
dstPdf := ""
|
|
pdf, err := ctx.FormFile("pdf")
|
|
|
|
if err == nil {
|
|
dstPdf = filepath.Join("static/uploads", pdf.Filename)
|
|
fmt.Println("Saving pdf at ", dstPdf)
|
|
if err := ctx.SaveUploadedFile(pdf, dstPdf); err != nil {
|
|
return models.ShopItem{}, fmt.Errorf("Could not save PDF")
|
|
}
|
|
|
|
if dstImage == defaultImagePath {
|
|
dstImage = dstPdf + ".preview.png"
|
|
cmd := exec.Command("pdftoppm", "-png", "-singlefile", dstPdf, dstPdf+".preview")
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
fmt.Println("Error during pdftoppm: ", err.Error())
|
|
}
|
|
|
|
cmd2 := exec.Command("convert", dstImage, "-resize", "35%", dstImage)
|
|
_, err = cmd2.Output()
|
|
|
|
if err != nil {
|
|
fmt.Println("Error during resizing preview image: ", err.Error())
|
|
}
|
|
|
|
}
|
|
} else {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
if name == "" || description == "" {
|
|
return models.ShopItem{}, fmt.Errorf("Name or description empty")
|
|
}
|
|
|
|
category, err := models.ParseCategory(categoryStr)
|
|
if err != nil {
|
|
return models.ShopItem{}, err
|
|
}
|
|
|
|
var variants []models.ItemVariant
|
|
|
|
fmt.Println("VariantNames: ", variantNames)
|
|
fmt.Println("VariantValues: ", variantValues)
|
|
if len(variantNames) != len(variantValues) {
|
|
return models.ShopItem{}, fmt.Errorf("Different number of variant names and values")
|
|
}
|
|
|
|
for idx := range variantNames {
|
|
if variantValues[idx] == "" || variantNames[idx] == "" {
|
|
continue
|
|
}
|
|
|
|
price, err := strconv.ParseFloat(variantValues[idx], 64)
|
|
if err != nil {
|
|
return models.ShopItem{}, fmt.Errorf("Could not variant parse price")
|
|
}
|
|
|
|
variants = append(variants, models.ItemVariant{
|
|
Name: variantNames[idx],
|
|
Price: price,
|
|
})
|
|
}
|
|
|
|
shopItem := models.ShopItem{
|
|
Name: name,
|
|
Abstract: abstract,
|
|
Description: description,
|
|
Category: category,
|
|
IsPublic: true,
|
|
BasePrice: rc.GetBasePrice(variants),
|
|
Image: dstImage,
|
|
Pdf: dstPdf,
|
|
Variants: variants,
|
|
PrintMode: printMode,
|
|
WasPrinted: false,
|
|
}
|
|
|
|
fmt.Println("Creating Shopitem: ", shopItem)
|
|
|
|
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
|
|
}
|
|
|
|
func (rc *shopItemController) GetBasePrice(variants []models.ItemVariant) float64 {
|
|
result := 0.0
|
|
|
|
for idx, variant := range variants {
|
|
if idx == 0 {
|
|
result = variant.Price
|
|
continue
|
|
}
|
|
|
|
if variant.Price < result {
|
|
result = variant.Price
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
_, err = repositories.ShopItems.Create(shopItem)
|
|
|
|
if err != nil {
|
|
ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err))
|
|
return
|
|
}
|
|
|
|
ReplyOK(c, "shopItem was created")
|
|
}
|
|
|
|
func (rc *shopItemController) Update(c *gin.Context) {
|
|
shopItemId, err := strconv.Atoi(c.Param("id"))
|
|
|
|
if err != nil {
|
|
ReplyError(c, fmt.Errorf("shopItem with Id '%s' does not exist", c.Param("id")))
|
|
return
|
|
}
|
|
|
|
shopItem, err := rc.NewShopItemFromForm(c)
|
|
|
|
if err != nil {
|
|
ReplyError(c, err)
|
|
return
|
|
}
|
|
|
|
shopItem.ID = uint(shopItemId)
|
|
_, err = repositories.ShopItems.Update(shopItem)
|
|
|
|
if err != nil {
|
|
ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err))
|
|
return
|
|
}
|
|
|
|
ReplyOK(c, "shopItem was updated")
|
|
}
|
|
|
|
// TODO: delete associated cartitems
|
|
func (rc *shopItemController) Delete(c *gin.Context) {
|
|
err := repositories.ShopItems.DeleteById(c.Param("id"))
|
|
|
|
if err != nil {
|
|
ReplyError(c, fmt.Errorf("shopItem deletion failed: %s", err))
|
|
return
|
|
}
|
|
|
|
ReplyOK(c, "shopItem was deleted")
|
|
}
|
|
|
|
func (rc *shopItemController) ShopItemView(c *gin.Context) {
|
|
shopItem, err := repositories.ShopItems.GetById(c.Param("id"))
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": "Item does not exist"}})
|
|
return
|
|
}
|
|
|
|
//TODO: get tags by item
|
|
tags, err := repositories.Tags.GetAll()
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
|
return
|
|
}
|
|
|
|
data := CreateSessionData(c, gin.H{
|
|
"shopItem": shopItem,
|
|
"tags": tags,
|
|
})
|
|
|
|
c.HTML(http.StatusOK, "shopitem.html", data)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
func (rc *shopItemController) AddItemHandler(c *gin.Context) {
|
|
errorHandler := func(err error, tags []models.Tag) {
|
|
data := CreateSessionData(c, gin.H{
|
|
"error": err,
|
|
"success": "",
|
|
"tags": tags,
|
|
})
|
|
|
|
c.HTML(http.StatusOK, "additem.html", data)
|
|
}
|
|
|
|
tags, err := repositories.Tags.GetAll()
|
|
if err != nil {
|
|
errorHandler(err, tags)
|
|
return
|
|
}
|
|
|
|
shopItem, err := rc.NewShopItemFromForm(c)
|
|
if err != nil {
|
|
errorHandler(err, tags)
|
|
return
|
|
}
|
|
|
|
_, err = repositories.ShopItems.Create(shopItem)
|
|
if err != nil {
|
|
errorHandler(err, tags)
|
|
return
|
|
}
|
|
|
|
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) AddItemsView(c *gin.Context) {
|
|
data := CreateSessionData(c, gin.H{})
|
|
|
|
c.HTML(http.StatusOK, "batchupload.html", data)
|
|
}
|
|
|
|
func (rc *shopItemController) AddItemsHandler(c *gin.Context) {
|
|
errorHandler := func(err error) {
|
|
data := CreateSessionData(c, gin.H{
|
|
"error": err,
|
|
})
|
|
c.HTML(http.StatusBadRequest, "batchupload.html", data)
|
|
}
|
|
|
|
form, err := c.MultipartForm()
|
|
|
|
if err != nil {
|
|
errorHandler(err)
|
|
return
|
|
}
|
|
|
|
files := form.File["pdf"]
|
|
|
|
var shopItems []models.ShopItem
|
|
for _, file := range files {
|
|
dstPdf := filepath.Join("static/uploads", file.Filename)
|
|
|
|
if err := c.SaveUploadedFile(file, dstPdf); err != nil {
|
|
errorHandler(err)
|
|
return
|
|
}
|
|
|
|
dstImage := dstPdf + ".preview.png"
|
|
cmd := exec.Command("pdftoppm", "-png", "-singlefile", dstPdf, dstPdf+".preview")
|
|
_, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
fmt.Println("Error during pdftoppm: ", err.Error())
|
|
}
|
|
|
|
cmd2 := exec.Command("convert", dstImage, "-resize", "35%", dstImage)
|
|
_, err = cmd2.Output()
|
|
|
|
if err != nil {
|
|
fmt.Println("Error during resizing preview image: ", err.Error())
|
|
}
|
|
|
|
category, err := models.ParseCategory("Zine")
|
|
if err != nil {
|
|
errorHandler(err)
|
|
return
|
|
}
|
|
|
|
variants := []models.ItemVariant{
|
|
{
|
|
Name: "B/W",
|
|
Price: 1.0,
|
|
},
|
|
}
|
|
|
|
shopItem := models.ShopItem{
|
|
Name: file.Filename,
|
|
Abstract: file.Filename,
|
|
Description: file.Filename,
|
|
Category: category,
|
|
IsPublic: true,
|
|
BasePrice: rc.GetBasePrice(variants),
|
|
Image: dstImage,
|
|
Pdf: dstPdf,
|
|
Variants: variants,
|
|
PrintMode: "CreateBooklet",
|
|
WasPrinted: false,
|
|
}
|
|
|
|
_, err = repositories.ShopItems.Create(shopItem)
|
|
if err != nil {
|
|
errorHandler(err)
|
|
return
|
|
}
|
|
|
|
shopItems = append(shopItems, shopItem)
|
|
}
|
|
|
|
msg := "The Following items were registered:\n"
|
|
|
|
for _, item := range shopItems {
|
|
msg += fmt.Sprintf("%s\n", item.Name)
|
|
}
|
|
|
|
data := CreateSessionData(c, gin.H{
|
|
"error": "",
|
|
"success": msg,
|
|
})
|
|
|
|
c.HTML(http.StatusOK, "batchupload.html", data)
|
|
}
|
|
|
|
func GetCheckedTags(item models.ShopItem) ([]models.CheckedTag, error) {
|
|
allTags, err := repositories.Tags.GetAll()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var tags []models.CheckedTag
|
|
for _, tag := range allTags {
|
|
tmpTag := models.CheckedTag{
|
|
Tag: tag,
|
|
Checked: "",
|
|
}
|
|
|
|
for _, itemTag := range item.Tags {
|
|
if itemTag.Name == tmpTag.Name {
|
|
tmpTag.Checked = "checked"
|
|
break
|
|
}
|
|
}
|
|
|
|
tags = append(tags, tmpTag)
|
|
}
|
|
|
|
return tags, nil
|
|
}
|
|
|
|
func (rc *shopItemController) getEditTemplatData(shopItem models.ShopItem) (gin.H, error) {
|
|
tags, err := GetCheckedTags(shopItem)
|
|
|
|
if err != nil {
|
|
return gin.H{}, err
|
|
}
|
|
|
|
priceBW := ""
|
|
priceColored := ""
|
|
for _, variant := range shopItem.Variants {
|
|
if variant.Name == "B/W" {
|
|
priceBW = fmt.Sprintf("%.2f", variant.Price)
|
|
}
|
|
|
|
if variant.Name == "Colored" {
|
|
priceColored = fmt.Sprintf("%.2f", variant.Price)
|
|
}
|
|
}
|
|
|
|
templateData := gin.H{
|
|
"error": "",
|
|
"success": "",
|
|
"shopItem": shopItem,
|
|
"tags": tags,
|
|
"priceBW": priceBW,
|
|
"priceColored": priceColored,
|
|
}
|
|
|
|
id := fmt.Sprintf("%d", shopItem.ID)
|
|
nextShopItem, err := repositories.ShopItems.GetNextOfId(id)
|
|
|
|
if err == nil {
|
|
fmt.Println("Setting nextitem")
|
|
fmt.Println(nextShopItem)
|
|
templateData["nextShopItem"] = nextShopItem
|
|
}
|
|
|
|
previousShopItem, err := repositories.ShopItems.GetPreviousOfId(id)
|
|
if err == nil {
|
|
templateData["previousShopItem"] = previousShopItem
|
|
}
|
|
|
|
return templateData, nil
|
|
}
|
|
|
|
func (rc *shopItemController) EditItemView(c *gin.Context) {
|
|
id := c.Param("id")
|
|
shopItem, err := repositories.ShopItems.GetById(id)
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": err})
|
|
}
|
|
|
|
templateData, err := rc.getEditTemplatData(shopItem)
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": err})
|
|
}
|
|
|
|
data := CreateSessionData(c, templateData)
|
|
c.HTML(http.StatusOK, "edititem.html", data)
|
|
}
|
|
|
|
func (rc *shopItemController) EditItemHandler(c *gin.Context) {
|
|
shopItem, err := rc.NewShopItemFromForm(c)
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "edititem.html", gin.H{"error": err})
|
|
return
|
|
}
|
|
|
|
newShopItem, err := repositories.ShopItems.GetById(c.Param("id"))
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "edititem.html", gin.H{"error": err})
|
|
return
|
|
}
|
|
|
|
newShopItem.Name = shopItem.Name
|
|
newShopItem.Abstract = shopItem.Abstract
|
|
newShopItem.Description = shopItem.Description
|
|
newShopItem.Category = shopItem.Category
|
|
newShopItem.Variants = shopItem.Variants
|
|
newShopItem.BasePrice = shopItem.BasePrice
|
|
newShopItem.IsPublic = shopItem.IsPublic
|
|
newShopItem.WasPrinted = false
|
|
|
|
if len(shopItem.Tags) != 0 {
|
|
newShopItem.Tags = shopItem.Tags
|
|
}
|
|
|
|
if shopItem.Image != "static/img/zine.jpg" {
|
|
newShopItem.Image = shopItem.Image
|
|
}
|
|
|
|
if shopItem.Pdf != "" {
|
|
newShopItem.Pdf = shopItem.Pdf
|
|
}
|
|
|
|
newShopItem.PrintMode = shopItem.PrintMode
|
|
|
|
templateData, err := rc.getEditTemplatData(newShopItem)
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": err})
|
|
}
|
|
|
|
_, err = repositories.ShopItems.Update(newShopItem)
|
|
if err != nil {
|
|
templateData["error"] = err
|
|
data := CreateSessionData(c, templateData)
|
|
c.HTML(http.StatusOK, "edititem.html", data)
|
|
return
|
|
}
|
|
|
|
templateData["success"] = fmt.Sprintf("Item '%s' Updated", newShopItem.Name)
|
|
data := CreateSessionData(c, templateData)
|
|
c.HTML(http.StatusOK, "edititem.html", data)
|
|
}
|
|
|
|
func (rc *shopItemController) DeleteItemView(c *gin.Context) {
|
|
shopItem, err := repositories.ShopItems.GetById(c.Param("id"))
|
|
tags, err := repositories.Tags.GetAll()
|
|
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "deleteitem.html", gin.H{"error": err})
|
|
}
|
|
|
|
fmt.Println(shopItem)
|
|
|
|
data := CreateSessionData(c, gin.H{
|
|
"error": "",
|
|
"success": "",
|
|
"shopItem": shopItem,
|
|
"tags": tags,
|
|
})
|
|
|
|
c.HTML(http.StatusOK, "deleteitem.html", data)
|
|
}
|
|
|
|
func (rc *shopItemController) DeleteItemHandler(c *gin.Context) {
|
|
err := repositories.ShopItems.DeleteById(c.Param("id"))
|
|
|
|
if err != nil {
|
|
data := CreateSessionData(c, gin.H{
|
|
"error": err,
|
|
"success": "",
|
|
})
|
|
|
|
c.HTML(http.StatusOK, "deleteitem.html", data)
|
|
}
|
|
|
|
shopItems, _ := repositories.ShopItems.GetAll()
|
|
fmt.Println(len(shopItems))
|
|
|
|
data := CreateSessionData(c, gin.H{
|
|
"title": "shopItem Page",
|
|
"shopItems": shopItems,
|
|
})
|
|
|
|
fmt.Println(data)
|
|
|
|
c.HTML(http.StatusOK, "index.html", data)
|
|
}
|
|
|
|
func ReplyError(ctx *gin.Context, err error) {
|
|
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
}
|
|
|
|
func ReplyOK(ctx *gin.Context, message any) {
|
|
ctx.JSON(http.StatusOK, message)
|
|
}
|