Compare commits
1 Commits
9e638dcfc2
...
trifold
| Author | SHA1 | Date | |
|---|---|---|---|
|
977926a059
|
@@ -1,350 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/models"
|
||||
//"git.dynamicdiscord.de/kalipso/zineshop/services"
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
|
||||
)
|
||||
|
||||
type ConfigController interface {
|
||||
AddConfigHandler(*gin.Context)
|
||||
ConfigHandler(*gin.Context)
|
||||
ConfigView(*gin.Context)
|
||||
|
||||
GetAllPaper(*gin.Context)
|
||||
PaperView(*gin.Context)
|
||||
PaperHandler(*gin.Context)
|
||||
AddPaperHandler(*gin.Context)
|
||||
|
||||
InvoiceView(*gin.Context)
|
||||
InvoiceHandler(*gin.Context)
|
||||
|
||||
CreateTag(*gin.Context)
|
||||
GetAllTags(*gin.Context)
|
||||
TagView(*gin.Context)
|
||||
TagHandler(*gin.Context)
|
||||
AddTagHandler(*gin.Context)
|
||||
}
|
||||
|
||||
type configController struct{}
|
||||
|
||||
func NewConfigController() ConfigController {
|
||||
return &configController{}
|
||||
}
|
||||
|
||||
func (rc *configController) AddConfigHandler(c *gin.Context) {
|
||||
key := c.PostForm("key")
|
||||
value := c.PostForm("value")
|
||||
|
||||
if key == "" || value == "" {
|
||||
err := "Key or Value empty during config creation"
|
||||
fmt.Println(err)
|
||||
c.HTML(http.StatusBadRequest, "configview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
config := models.Config{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
|
||||
_, err := repositories.ConfigOptions.Create(config)
|
||||
if err != nil {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": err,
|
||||
"success": "",
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "configview.html", data)
|
||||
return
|
||||
}
|
||||
|
||||
rc.ConfigView(c)
|
||||
}
|
||||
|
||||
func (rc *configController) ConfigView(c *gin.Context) {
|
||||
configOptions, err := repositories.ConfigOptions.GetAll()
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "configview.html", gin.H{"data": gin.H{"error": err}})
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"configOptions": configOptions,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "configview.html", data)
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "configview.html", data)
|
||||
}
|
||||
|
||||
func (rc *configController) ConfigHandler(ctx *gin.Context) {
|
||||
key := ctx.PostForm("key")
|
||||
value := ctx.PostForm("value")
|
||||
action := ctx.PostForm("action")
|
||||
|
||||
config, err := repositories.ConfigOptions.GetById(ctx.Param("id"))
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "configview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
if action == "update" {
|
||||
config.Key = key
|
||||
config.Value = value
|
||||
config, err = repositories.ConfigOptions.Update(config)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "configview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if action == "delete" {
|
||||
repositories.ConfigOptions.DeleteById(ctx.Param("id"))
|
||||
}
|
||||
|
||||
rc.ConfigView(ctx)
|
||||
}
|
||||
|
||||
func (rc *configController) PaperHandler(ctx *gin.Context) {
|
||||
newPaper, err := models.NewPaper(ctx)
|
||||
action := ctx.PostForm("action")
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "paperview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
paper, err := repositories.Papers.GetById(ctx.Param("id"))
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "paperview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
if action == "update" {
|
||||
paper.Name = newPaper.Name
|
||||
paper.Brand = newPaper.Brand
|
||||
paper.Size = newPaper.Size
|
||||
paper.Weight = newPaper.Weight
|
||||
paper.Price = newPaper.Price
|
||||
paper, err = repositories.Papers.Update(paper)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "paperview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if action == "delete" {
|
||||
repositories.Papers.DeleteById(ctx.Param("id"))
|
||||
}
|
||||
|
||||
rc.PaperView(ctx)
|
||||
}
|
||||
|
||||
func (rc *configController) AddPaperHandler(c *gin.Context) {
|
||||
paper, err := models.NewPaper(c)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
c.HTML(http.StatusBadRequest, "paperview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = repositories.Papers.Create(paper)
|
||||
if err != nil {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": err,
|
||||
"success": "",
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "paperview.html", data)
|
||||
return
|
||||
}
|
||||
|
||||
rc.PaperView(c)
|
||||
}
|
||||
|
||||
func (rc *configController) PaperView(c *gin.Context) {
|
||||
papers, err := repositories.Papers.GetAll()
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "paperview.html", gin.H{"data": gin.H{"error": err}})
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"paper": papers,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "paperview.html", data)
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "paperview.html", data)
|
||||
}
|
||||
|
||||
func (rc *configController) GetAllPaper(c *gin.Context) {
|
||||
papers, err := repositories.Papers.GetAll()
|
||||
|
||||
if err != nil {
|
||||
ReplyError(c, fmt.Errorf("Could not query Papers"))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, papers)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (rc *configController) InvoiceView(c *gin.Context) {
|
||||
invoices, err := repositories.Invoices.GetAll()
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "invoiceview.html", gin.H{"data": gin.H{"error": err}})
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"invoices": invoices,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "invoiceview.html", data)
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "invoiceview.html", data)
|
||||
}
|
||||
|
||||
func (rc *configController) InvoiceHandler(ctx *gin.Context) {
|
||||
action := ctx.PostForm("action")
|
||||
if action == "delete" {
|
||||
repositories.Invoices.DeleteById(ctx.Param("id"))
|
||||
}
|
||||
|
||||
rc.InvoiceView(ctx)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (rc *configController) TagHandler(ctx *gin.Context) {
|
||||
name := ctx.PostForm("name")
|
||||
color := ctx.PostForm("color")
|
||||
action := ctx.PostForm("action")
|
||||
|
||||
tag, err := repositories.Tags.GetById(ctx.Param("id"))
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
if action == "update" {
|
||||
tag.Name = name
|
||||
tag.Color = color
|
||||
tag, err = repositories.Tags.Update(tag)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if action == "delete" {
|
||||
repositories.Tags.DeleteById(ctx.Param("id"))
|
||||
}
|
||||
|
||||
rc.TagView(ctx)
|
||||
}
|
||||
|
||||
func (rc *configController) AddTagHandler(c *gin.Context) {
|
||||
tag, err := models.NewTag(c)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
c.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = repositories.Tags.Create(tag)
|
||||
if err != nil {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": err,
|
||||
"success": "",
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "tagview.html", data)
|
||||
return
|
||||
}
|
||||
|
||||
rc.TagView(c)
|
||||
}
|
||||
|
||||
func (rc *configController) TagView(c *gin.Context) {
|
||||
tags, err := repositories.Tags.GetAll()
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "tagview.html", gin.H{"data": gin.H{"error": err}})
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"tags": tags,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "tagview.html", data)
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "tagview.html", data)
|
||||
}
|
||||
|
||||
func (rc *configController) 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("tag 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 *configController) 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)
|
||||
}
|
||||
@@ -63,14 +63,7 @@ func (rc *printController) PrintCartView(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
paper, err := repositories.Papers.GetAll()
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
||||
return
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"paper": paper,
|
||||
"cartItems": cartItems,
|
||||
})
|
||||
|
||||
@@ -85,16 +78,9 @@ func (rc *printController) PrintOrderView(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
paper, err := repositories.Papers.GetAll()
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
||||
return
|
||||
}
|
||||
|
||||
cartItems := order.CartItems
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"paper": paper,
|
||||
"cartItems": cartItems,
|
||||
})
|
||||
|
||||
@@ -104,7 +90,6 @@ func (rc *printController) PrintOrderView(c *gin.Context) {
|
||||
func (rc *printController) PrintHandler(c *gin.Context) {
|
||||
variantIds := c.PostFormArray("variant-id[]")
|
||||
variantAmounts := c.PostFormArray("variant-amount[]")
|
||||
variantPapertypes := c.PostFormArray("variant-papertype[]")
|
||||
variantCoverPages := c.PostFormArray("variant-coverpage[]")
|
||||
|
||||
if len(variantIds) != len(variantAmounts) || len(variantIds) != len(variantCoverPages) {
|
||||
@@ -113,7 +98,6 @@ func (rc *printController) PrintHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
var printJobs []models.PrintJob
|
||||
priceTotal := 0.0
|
||||
for idx := range variantIds {
|
||||
variant, err := repositories.ShopItems.GetVariantById(variantIds[idx])
|
||||
|
||||
@@ -129,21 +113,9 @@ func (rc *printController) PrintHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
paperType, err := repositories.Papers.GetById(fmt.Sprintf("%v", variantPapertypes[idx]))
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
||||
return
|
||||
}
|
||||
|
||||
var coverPage *models.Paper
|
||||
if variantCoverPages[idx] != "0" {
|
||||
coverPageTmp, err := repositories.Papers.GetById(fmt.Sprintf("%v", variantCoverPages[idx]))
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
||||
return
|
||||
}
|
||||
|
||||
coverPage = &coverPageTmp
|
||||
coverPage := false
|
||||
if variantCoverPages[idx] == "1" {
|
||||
coverPage = true
|
||||
}
|
||||
|
||||
variantAmount, err := strconv.Atoi(variantAmounts[idx])
|
||||
@@ -152,56 +124,23 @@ func (rc *printController) PrintHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Printing Costs:")
|
||||
|
||||
printJob, err := models.NewPrintJob(shopItem, variant, paperType, coverPage, uint(variantAmount))
|
||||
printJob, err := models.NewPrintJob(shopItem, variant, coverPage, uint(variantAmount))
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
||||
return
|
||||
}
|
||||
printJob.CalculatePrintCosts()
|
||||
priceTotal += printJob.PriceTotal
|
||||
|
||||
printJobs = append(printJobs, printJob)
|
||||
}
|
||||
|
||||
invoice := models.Invoice{
|
||||
PrintJobs: printJobs,
|
||||
PricePerClick: 0.002604,
|
||||
PartCosts: 0.0067,
|
||||
PriceTotal: priceTotal,
|
||||
}
|
||||
invoice, err := repositories.Invoices.Create(invoice)
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}})
|
||||
return
|
||||
}
|
||||
|
||||
executeJobs := func() {
|
||||
for _, printJob := range printJobs {
|
||||
printJob.ShopItem.WasPrinted = true
|
||||
_, err = repositories.ShopItems.Update(printJob.ShopItem)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err)
|
||||
}
|
||||
|
||||
err := printJob.Execute()
|
||||
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
printJob.Execute()
|
||||
}
|
||||
}
|
||||
|
||||
go executeJobs()
|
||||
|
||||
fmt.Println(invoice)
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"invoice": invoice,
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "printstarted.html", data)
|
||||
c.HTML(http.StatusOK, "index.html", nil)
|
||||
}
|
||||
|
||||
@@ -29,10 +29,15 @@ type ShopItemController interface {
|
||||
AddItemHandler(*gin.Context)
|
||||
AddItemsView(*gin.Context)
|
||||
AddItemsHandler(*gin.Context)
|
||||
CreateTag(*gin.Context)
|
||||
GetAllTags(*gin.Context)
|
||||
EditItemView(*gin.Context)
|
||||
EditItemHandler(*gin.Context)
|
||||
DeleteItemView(*gin.Context)
|
||||
DeleteItemHandler(*gin.Context)
|
||||
TagView(*gin.Context)
|
||||
TagHandler(*gin.Context)
|
||||
AddTagHandler(*gin.Context)
|
||||
}
|
||||
|
||||
type shopItemController struct{}
|
||||
@@ -161,7 +166,6 @@ func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.Shop
|
||||
Pdf: dstPdf,
|
||||
Variants: variants,
|
||||
PrintMode: printMode,
|
||||
WasPrinted: false,
|
||||
}
|
||||
|
||||
fmt.Println("Creating Shopitem: ", shopItem)
|
||||
@@ -401,7 +405,6 @@ func (rc *shopItemController) AddItemsHandler(c *gin.Context) {
|
||||
Pdf: dstPdf,
|
||||
Variants: variants,
|
||||
PrintMode: "CreateBooklet",
|
||||
WasPrinted: false,
|
||||
}
|
||||
|
||||
_, err = repositories.ShopItems.Create(shopItem)
|
||||
@@ -539,7 +542,6 @@ func (rc *shopItemController) EditItemHandler(c *gin.Context) {
|
||||
newShopItem.Variants = shopItem.Variants
|
||||
newShopItem.BasePrice = shopItem.BasePrice
|
||||
newShopItem.IsPublic = shopItem.IsPublic
|
||||
newShopItem.WasPrinted = false
|
||||
|
||||
if len(shopItem.Tags) != 0 {
|
||||
newShopItem.Tags = shopItem.Tags
|
||||
@@ -619,6 +621,115 @@ func (rc *shopItemController) DeleteItemHandler(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "index.html", data)
|
||||
}
|
||||
|
||||
func (rc *shopItemController) TagHandler(ctx *gin.Context) {
|
||||
name := ctx.PostForm("name")
|
||||
color := ctx.PostForm("color")
|
||||
action := ctx.PostForm("action")
|
||||
|
||||
tag, err := repositories.Tags.GetById(ctx.Param("id"))
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
if action == "update" {
|
||||
tag.Name = name
|
||||
tag.Color = color
|
||||
tag, err = repositories.Tags.Update(tag)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if action == "delete" {
|
||||
repositories.Tags.DeleteById(ctx.Param("id"))
|
||||
}
|
||||
|
||||
rc.TagView(ctx)
|
||||
}
|
||||
|
||||
func (rc *shopItemController) AddTagHandler(c *gin.Context) {
|
||||
tag, err := models.NewTag(c)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
c.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = repositories.Tags.Create(tag)
|
||||
if err != nil {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": err,
|
||||
"success": "",
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "tagview.html", data)
|
||||
return
|
||||
}
|
||||
|
||||
rc.TagView(c)
|
||||
}
|
||||
|
||||
func (rc *shopItemController) TagView(c *gin.Context) {
|
||||
tags, err := repositories.Tags.GetAll()
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "tagview.html", gin.H{"data": gin.H{"error": err}})
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"tags": tags,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "tagview.html", data)
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "tagview.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()})
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -3,7 +3,6 @@ module git.dynamicdiscord.de/kalipso/zineshop
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/dslipak/pdf v0.0.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
|
||||
2
go.sum
2
go.sum
@@ -9,8 +9,6 @@ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQ
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dslipak/pdf v0.0.2 h1:djAvcM5neg9Ush+zR6QXB+VMJzR6TdnX766HPIg1JmI=
|
||||
github.com/dslipak/pdf v0.0.2/go.mod h1:2L3SnkI9cQwnAS9gfPz2iUoLC0rUZwbucpbKi5R1mUo=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
|
||||
20
main.go
20
main.go
@@ -19,7 +19,6 @@ var (
|
||||
userController controllers.UserController = controllers.UserController{}
|
||||
cartItemController controllers.CartItemController = controllers.NewCartItemController()
|
||||
printController controllers.PrintController = controllers.NewPrintController()
|
||||
configController controllers.ConfigController = controllers.NewConfigController()
|
||||
authValidator middlewares.AuthValidator = middlewares.AuthValidator{}
|
||||
)
|
||||
|
||||
@@ -68,23 +67,10 @@ func main() {
|
||||
viewRoutes.GET("/cart/print", authValidator.RequireAdmin, printController.PrintCartView)
|
||||
viewRoutes.POST("/print", authValidator.RequireAdmin, printController.PrintHandler)
|
||||
|
||||
viewRoutes.GET("/config", authValidator.RequireAdmin, configController.ConfigView)
|
||||
viewRoutes.POST("/config/:id", authValidator.RequireAdmin, configController.ConfigHandler)
|
||||
viewRoutes.POST("/config", authValidator.RequireAdmin, configController.AddConfigHandler)
|
||||
|
||||
viewRoutes.GET("/tags", authValidator.RequireAdmin, configController.TagView)
|
||||
viewRoutes.POST("/tags/:id", authValidator.RequireAdmin, configController.TagHandler)
|
||||
viewRoutes.GET("/tags", authValidator.RequireAdmin, shopItemController.TagView)
|
||||
viewRoutes.POST("/tags/:id", authValidator.RequireAdmin, shopItemController.TagHandler)
|
||||
viewRoutes.GET("/tags/:id", userController.TagView)
|
||||
viewRoutes.POST("/tags", authValidator.RequireAdmin, configController.AddTagHandler)
|
||||
|
||||
viewRoutes.GET("/paper", authValidator.RequireAdmin, configController.PaperView)
|
||||
viewRoutes.POST("/paper/:id", authValidator.RequireAdmin, configController.PaperHandler)
|
||||
viewRoutes.GET("/paper/:id", userController.TagView)
|
||||
viewRoutes.POST("/paper", authValidator.RequireAdmin, configController.AddPaperHandler)
|
||||
|
||||
viewRoutes.GET("/invoice", authValidator.RequireAdmin, configController.InvoiceView)
|
||||
viewRoutes.POST("/invoice/:id", authValidator.RequireAdmin, configController.InvoiceHandler)
|
||||
|
||||
viewRoutes.POST("/tags", authValidator.RequireAdmin, shopItemController.AddTagHandler)
|
||||
viewRoutes.GET("/cart", authValidator.RequireAuth, cartItemController.CartItemView)
|
||||
viewRoutes.POST("/cart", authValidator.RequireAuth, cartItemController.AddItemHandler)
|
||||
viewRoutes.POST("/cart/delete", authValidator.RequireAuth, cartItemController.DeleteItemHandler)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
gorm.Model
|
||||
Key string `json:"key" binding:"required" gorm:"unique;not null"`
|
||||
Value string `json:"value" binding:"required"`
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PaperSize string
|
||||
|
||||
const (
|
||||
A3 PaperSize = "A3"
|
||||
A4 PaperSize = "A4"
|
||||
A5 PaperSize = "A5"
|
||||
SRA3 PaperSize = "SRA3"
|
||||
)
|
||||
|
||||
func ParseSize(s string) (c PaperSize, err error) {
|
||||
s = strings.ToUpper(s)
|
||||
if s == "A3" {
|
||||
return A3, nil
|
||||
} else if s == "A4" {
|
||||
return A4, nil
|
||||
} else if s == "A5" {
|
||||
return A5, nil
|
||||
} else if s == "SRA3" {
|
||||
return SRA3, nil
|
||||
}
|
||||
|
||||
return c, fmt.Errorf("Cannot parse category %s", s)
|
||||
}
|
||||
|
||||
type Paper struct {
|
||||
gorm.Model
|
||||
Name string `json:"name" binding:"required" gorm:"not null"`
|
||||
Brand string `json:"brand" binding:"required"`
|
||||
Size PaperSize `json:"size" binding:"required"`
|
||||
Weight int `json:"weight" binding:"required"`
|
||||
Price float64 `json:"price" binding:"required"`
|
||||
}
|
||||
|
||||
func NewPaper(ctx *gin.Context) (Paper, error) {
|
||||
name := ctx.PostForm("name")
|
||||
brand := ctx.PostForm("brand")
|
||||
sizeTmp := ctx.PostForm("size")
|
||||
weightTmp := ctx.PostForm("weight")
|
||||
priceTmp := ctx.PostForm("price")
|
||||
|
||||
size, err := ParseSize(sizeTmp)
|
||||
|
||||
if err != nil {
|
||||
return Paper{}, fmt.Errorf("Couldnt parse Size")
|
||||
}
|
||||
|
||||
weight, err := strconv.Atoi(weightTmp)
|
||||
|
||||
if err != nil {
|
||||
return Paper{}, fmt.Errorf("Couldnt parse Weight")
|
||||
}
|
||||
|
||||
price, err := strconv.ParseFloat(priceTmp, 64)
|
||||
|
||||
if err != nil {
|
||||
return Paper{}, fmt.Errorf("Couldnt parse Price")
|
||||
}
|
||||
|
||||
if name == "" || brand == "" {
|
||||
return Paper{}, fmt.Errorf("Name or brand empty")
|
||||
}
|
||||
|
||||
// Convert the price string to float64
|
||||
tag := Paper{
|
||||
Name: name,
|
||||
Brand: brand,
|
||||
Size: size,
|
||||
Weight: weight,
|
||||
Price: price,
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
@@ -2,9 +2,6 @@ package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/utils"
|
||||
"gorm.io/gorm"
|
||||
"math"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
@@ -18,39 +15,15 @@ const (
|
||||
LongEdge PrintOption = ""
|
||||
ShortEdge PrintOption = "-o Binding=TopBinding"
|
||||
CreateBooklet PrintOption = "-o Combination=Booklet -o PageSize=A5"
|
||||
TriFold PrintOption = "-o Fold=TriFold -o Binding=TopBinding"
|
||||
TriFold PrintOption = "-o Fold=TriFold -o Binding=RightBinding"
|
||||
)
|
||||
|
||||
type OldPrintJob struct {
|
||||
type PrintJob struct {
|
||||
Pdf string
|
||||
Amount uint
|
||||
Options []PrintOption
|
||||
}
|
||||
|
||||
type Invoice struct {
|
||||
gorm.Model
|
||||
PrintJobs []PrintJob
|
||||
PricePerClick float64
|
||||
PartCosts float64
|
||||
PriceTotal float64
|
||||
}
|
||||
|
||||
type PrintJob struct {
|
||||
gorm.Model
|
||||
ShopItemID uint
|
||||
ShopItem ShopItem
|
||||
VariantID uint
|
||||
Variant ItemVariant
|
||||
PaperTypeId uint
|
||||
PaperType Paper `gorm:"foreignKey:PaperTypeId"`
|
||||
CoverPaperTypeId *uint
|
||||
CoverPaperType *Paper `gorm:"foreignKey:CoverPaperTypeId"`
|
||||
Amount uint
|
||||
PricePerPiece float64
|
||||
PriceTotal float64
|
||||
InvoiceID uint
|
||||
}
|
||||
|
||||
func GetPrintMode(mode string) PrintOption {
|
||||
if mode == "LongEdge" {
|
||||
return LongEdge
|
||||
@@ -67,7 +40,7 @@ func GetPrintMode(mode string) PrintOption {
|
||||
return CreateBooklet
|
||||
}
|
||||
|
||||
func NewPrintJob(shopItem ShopItem, variant ItemVariant, paperType Paper, coverPaperType *Paper, amount uint) (PrintJob, error) {
|
||||
func NewPrintJob(shopItem ShopItem, variant ItemVariant, coverPage bool, amount uint) (PrintJob, error) {
|
||||
if shopItem.Pdf == "" {
|
||||
return PrintJob{}, fmt.Errorf("ShopItem has no PDF assigned")
|
||||
}
|
||||
@@ -76,44 +49,32 @@ func NewPrintJob(shopItem ShopItem, variant ItemVariant, paperType Paper, coverP
|
||||
return PrintJob{}, fmt.Errorf("Amount to big. This is denied for security reasons")
|
||||
}
|
||||
|
||||
result := PrintJob{
|
||||
ShopItem: shopItem,
|
||||
Variant: variant,
|
||||
PaperType: paperType,
|
||||
CoverPaperType: coverPaperType,
|
||||
Amount: amount,
|
||||
var result PrintJob
|
||||
result.Pdf = shopItem.Pdf
|
||||
result.Amount = amount
|
||||
|
||||
if variant.Name == "Colored" {
|
||||
result.Options = append(result.Options, Colored)
|
||||
}
|
||||
|
||||
if coverPage {
|
||||
result.Options = append(result.Options, CoverPage)
|
||||
}
|
||||
|
||||
result.Options = append(result.Options, GetPrintMode(shopItem.PrintMode))
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (p *PrintJob) IsColored() bool {
|
||||
return p.Variant.Name == "Colored"
|
||||
}
|
||||
|
||||
func (p *PrintJob) GeneratePrintOptions() []PrintOption {
|
||||
var result []PrintOption
|
||||
if p.Variant.Name == "Colored" {
|
||||
result = append(result, Colored)
|
||||
}
|
||||
|
||||
if p.CoverPaperType != nil {
|
||||
result = append(result, CoverPage)
|
||||
}
|
||||
|
||||
result = append(result, GetPrintMode(p.ShopItem.PrintMode))
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *PrintJob) Execute() error {
|
||||
baseCommand := "lp -d KonicaBooklet"
|
||||
baseCommand += fmt.Sprintf(" -n %v ", p.Amount)
|
||||
|
||||
for _, option := range p.GeneratePrintOptions() {
|
||||
for _, option := range p.Options {
|
||||
baseCommand += fmt.Sprintf(" %v ", option)
|
||||
}
|
||||
|
||||
baseCommand += fmt.Sprintf(" -- %s", p.ShopItem.Pdf)
|
||||
baseCommand += fmt.Sprintf(" -- %s", p.Pdf)
|
||||
|
||||
parts := strings.Fields(baseCommand)
|
||||
|
||||
@@ -130,37 +91,3 @@ func (p *PrintJob) Execute() error {
|
||||
fmt.Printf("Output:\n%s\n", output)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PrintJob) CalculatePrintCosts() (float64, error) {
|
||||
pageCount := utils.CountPagesAtPath(p.ShopItem.Pdf)
|
||||
printMode := GetPrintMode(p.ShopItem.PrintMode)
|
||||
|
||||
//Get actual pagecount depending on printmode
|
||||
actualPageCount := pageCount
|
||||
fmt.Println("PagCount: ", actualPageCount)
|
||||
|
||||
if printMode == CreateBooklet {
|
||||
dividedCount := float64(pageCount) / 4.0
|
||||
actualPageCount = int(math.Ceil(dividedCount))
|
||||
}
|
||||
|
||||
if printMode == LongEdge || printMode == ShortEdge {
|
||||
dividedCount := float64(pageCount) / 2.0
|
||||
actualPageCount = int(math.Ceil(dividedCount))
|
||||
}
|
||||
|
||||
PPC := 0.002604
|
||||
partCost := 0.0067
|
||||
if p.IsColored() {
|
||||
partCost = 0.0478
|
||||
}
|
||||
printingCosts := float64(actualPageCount) * p.PaperType.Price
|
||||
printingCosts += float64(actualPageCount/2) * PPC
|
||||
printingCosts += partCost * float64(actualPageCount)
|
||||
|
||||
fmt.Printf("Printing Costs per Zine: %v\n", printingCosts)
|
||||
fmt.Printf("Printing Costs Total: %v\n", printingCosts*float64(p.Amount))
|
||||
p.PricePerPiece = printingCosts
|
||||
p.PriceTotal = printingCosts * float64(p.Amount)
|
||||
return printingCosts, nil
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ type ItemVariant struct {
|
||||
type ShopItem struct {
|
||||
gorm.Model
|
||||
Name string `json:"name" binding:"required" gorm:"unique;not null"`
|
||||
Abstract string `json:"abstract" binding:"required"`
|
||||
Abstract string `json:"Abstract" binding:"required"`
|
||||
Description string `json:"description" binding:"required"`
|
||||
Category Category `json:"category"`
|
||||
Variants []ItemVariant `json:"variant"`
|
||||
@@ -53,5 +53,4 @@ type ShopItem struct {
|
||||
Image string
|
||||
Pdf string
|
||||
PrintMode string `json:"printMode" gorm:"default:CreateBooklet"`
|
||||
WasPrinted bool `gorm:"default:false"`
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/models"
|
||||
)
|
||||
|
||||
type InvoiceRepository interface {
|
||||
Create(models.Invoice) (models.Invoice, error)
|
||||
GetAll() ([]models.Invoice, error)
|
||||
GetById(string) (models.Invoice, error)
|
||||
//GetByShopItemId(string) (models.Invoice, error)
|
||||
Update(models.Invoice) (models.Invoice, error)
|
||||
DeleteById(string) error
|
||||
}
|
||||
|
||||
type GORMInvoiceRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewGORMInvoiceRepository(db *gorm.DB) InvoiceRepository {
|
||||
return &GORMInvoiceRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *GORMInvoiceRepository) Create(invoice models.Invoice) (models.Invoice, error) {
|
||||
result := t.DB.Create(&invoice)
|
||||
|
||||
if result.Error != nil {
|
||||
return models.Invoice{}, result.Error
|
||||
}
|
||||
|
||||
return invoice, nil
|
||||
}
|
||||
|
||||
func (t *GORMInvoiceRepository) GetAll() ([]models.Invoice, error) {
|
||||
var invoice []models.Invoice
|
||||
result := t.DB.Preload("PrintJobs.ShopItem").Preload("PrintJobs.Variant").Preload("PrintJobs.PaperType").Preload("PrintJobs.CoverPaperType").Preload("PrintJobs").Find(&invoice)
|
||||
|
||||
return invoice, result.Error
|
||||
}
|
||||
|
||||
func (t *GORMInvoiceRepository) GetById(id string) (models.Invoice, error) {
|
||||
invoiceId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return models.Invoice{}, err
|
||||
}
|
||||
|
||||
var invoice models.Invoice
|
||||
result := t.DB.Preload("PrintJobs").First(&invoice, uint(invoiceId))
|
||||
|
||||
if result.Error != nil {
|
||||
return models.Invoice{}, result.Error
|
||||
}
|
||||
|
||||
return invoice, nil
|
||||
}
|
||||
|
||||
func (t *GORMInvoiceRepository) Update(invoice models.Invoice) (models.Invoice, error) {
|
||||
result := t.DB.Save(&invoice)
|
||||
if result.Error != nil {
|
||||
return models.Invoice{}, result.Error
|
||||
}
|
||||
|
||||
return invoice, nil
|
||||
}
|
||||
|
||||
func (t *GORMInvoiceRepository) DeleteById(id string) error {
|
||||
invoiceId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := t.DB.Delete(&models.Invoice{}, invoiceId)
|
||||
return result.Error
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/models"
|
||||
)
|
||||
|
||||
type ConfigRepository interface {
|
||||
Create(models.Config) (models.Config, error)
|
||||
GetAll() ([]models.Config, error)
|
||||
GetById(string) (models.Config, error)
|
||||
Update(models.Config) (models.Config, error)
|
||||
DeleteById(string) error
|
||||
}
|
||||
|
||||
type GORMConfigRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewGORMConfigRepository(db *gorm.DB) ConfigRepository {
|
||||
return &GORMConfigRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *GORMConfigRepository) Create(config models.Config) (models.Config, error) {
|
||||
result := t.DB.Create(&config)
|
||||
|
||||
if result.Error != nil {
|
||||
return models.Config{}, result.Error
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (t *GORMConfigRepository) GetAll() ([]models.Config, error) {
|
||||
var configs []models.Config
|
||||
result := t.DB.Find(&configs)
|
||||
|
||||
return configs, result.Error
|
||||
}
|
||||
|
||||
func (t *GORMConfigRepository) GetById(id string) (models.Config, error) {
|
||||
configId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return models.Config{}, err
|
||||
}
|
||||
|
||||
var config models.Config
|
||||
result := t.DB.First(&config, uint(configId))
|
||||
|
||||
if result.Error != nil {
|
||||
return models.Config{}, result.Error
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (t *GORMConfigRepository) Update(config models.Config) (models.Config, error) {
|
||||
result := t.DB.Save(&config)
|
||||
if result.Error != nil {
|
||||
return models.Config{}, result.Error
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (t *GORMConfigRepository) DeleteById(id string) error {
|
||||
configId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := t.DB.Delete(&models.Config{}, configId)
|
||||
return result.Error
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/models"
|
||||
)
|
||||
|
||||
type PaperRepository interface {
|
||||
Create(models.Paper) (models.Paper, error)
|
||||
GetAll() ([]models.Paper, error)
|
||||
GetById(string) (models.Paper, error)
|
||||
//GetByShopItemId(string) (models.Paper, error)
|
||||
Update(models.Paper) (models.Paper, error)
|
||||
DeleteById(string) error
|
||||
}
|
||||
|
||||
type GORMPaperRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewGORMPaperRepository(db *gorm.DB) PaperRepository {
|
||||
return &GORMPaperRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *GORMPaperRepository) Create(tag models.Paper) (models.Paper, error) {
|
||||
result := t.DB.Create(&tag)
|
||||
|
||||
if result.Error != nil {
|
||||
return models.Paper{}, result.Error
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func (t *GORMPaperRepository) GetAll() ([]models.Paper, error) {
|
||||
var tags []models.Paper
|
||||
result := t.DB.Find(&tags)
|
||||
|
||||
return tags, result.Error
|
||||
}
|
||||
|
||||
func (t *GORMPaperRepository) GetById(id string) (models.Paper, error) {
|
||||
tagId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return models.Paper{}, err
|
||||
}
|
||||
|
||||
var tag models.Paper
|
||||
result := t.DB.First(&tag, uint(tagId))
|
||||
|
||||
if result.Error != nil {
|
||||
return models.Paper{}, result.Error
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func (t *GORMPaperRepository) Update(tag models.Paper) (models.Paper, error) {
|
||||
result := t.DB.Save(&tag)
|
||||
if result.Error != nil {
|
||||
return models.Paper{}, result.Error
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func (t *GORMPaperRepository) DeleteById(id string) error {
|
||||
tagId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := t.DB.Delete(&models.Paper{}, tagId)
|
||||
return result.Error
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.dynamicdiscord.de/kalipso/zineshop/models"
|
||||
)
|
||||
|
||||
type PrintJobRepository interface {
|
||||
Create(models.PrintJob) (models.PrintJob, error)
|
||||
GetAll() ([]models.PrintJob, error)
|
||||
GetById(string) (models.PrintJob, error)
|
||||
//GetByShopItemId(string) (models.PrintJob, error)
|
||||
Update(models.PrintJob) (models.PrintJob, error)
|
||||
DeleteById(string) error
|
||||
}
|
||||
|
||||
type GORMPrintJobRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewGORMPrintJobRepository(db *gorm.DB) PrintJobRepository {
|
||||
return &GORMPrintJobRepository{
|
||||
DB: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *GORMPrintJobRepository) Create(printJob models.PrintJob) (models.PrintJob, error) {
|
||||
result := t.DB.Create(&printJob)
|
||||
|
||||
if result.Error != nil {
|
||||
return models.PrintJob{}, result.Error
|
||||
}
|
||||
|
||||
return printJob, nil
|
||||
}
|
||||
|
||||
func (t *GORMPrintJobRepository) GetAll() ([]models.PrintJob, error) {
|
||||
var printJobs []models.PrintJob
|
||||
result := t.DB.Preload("ShopItem").Preload("Variant").Preload("PaperType").Preload("CoverPaperType").Find(&printJobs)
|
||||
|
||||
return printJobs, result.Error
|
||||
}
|
||||
|
||||
func (t *GORMPrintJobRepository) GetById(id string) (models.PrintJob, error) {
|
||||
printJobId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return models.PrintJob{}, err
|
||||
}
|
||||
|
||||
var printJob models.PrintJob
|
||||
result := t.DB.Preload("ShopItem").Preload("Variant").Preload("PaperType").Preload("CoverPaperType").First(&printJob, uint(printJobId))
|
||||
|
||||
if result.Error != nil {
|
||||
return models.PrintJob{}, result.Error
|
||||
}
|
||||
|
||||
return printJob, nil
|
||||
}
|
||||
|
||||
func (t *GORMPrintJobRepository) Update(printJob models.PrintJob) (models.PrintJob, error) {
|
||||
result := t.DB.Save(&printJob)
|
||||
if result.Error != nil {
|
||||
return models.PrintJob{}, result.Error
|
||||
}
|
||||
|
||||
return printJob, nil
|
||||
}
|
||||
|
||||
func (t *GORMPrintJobRepository) DeleteById(id string) error {
|
||||
printJobId, err := strconv.Atoi(id)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := t.DB.Delete(&models.PrintJob{}, printJobId)
|
||||
return result.Error
|
||||
}
|
||||
@@ -9,16 +9,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ShopItems ShopItemRepository
|
||||
Users UserRepository
|
||||
Tags TagRepository
|
||||
CartItems CartItemRepository
|
||||
Orders OrderRepository
|
||||
Tokens RegisterTokenRepository
|
||||
ConfigOptions ConfigRepository
|
||||
Papers PaperRepository
|
||||
PrintJobs PrintJobRepository
|
||||
Invoices InvoiceRepository
|
||||
ShopItems ShopItemRepository
|
||||
Users UserRepository
|
||||
Tags TagRepository
|
||||
CartItems CartItemRepository
|
||||
Orders OrderRepository
|
||||
Tokens RegisterTokenRepository
|
||||
)
|
||||
|
||||
func InitRepositories() {
|
||||
@@ -33,10 +29,6 @@ func InitRepositories() {
|
||||
&models.Tag{},
|
||||
&models.CartItem{},
|
||||
&models.Order{},
|
||||
&models.Config{},
|
||||
&models.Paper{},
|
||||
&models.PrintJob{},
|
||||
&models.Invoice{},
|
||||
&models.RegisterToken{})
|
||||
|
||||
if err != nil {
|
||||
@@ -49,8 +41,4 @@ func InitRepositories() {
|
||||
CartItems = NewGORMCartItemRepository(db)
|
||||
Orders = NewGORMOrderRepository(db)
|
||||
Tokens = NewGORMRegisterTokenRepository(db)
|
||||
ConfigOptions = NewGORMConfigRepository(db)
|
||||
Papers = NewGORMPaperRepository(db)
|
||||
PrintJobs = NewGORMPrintJobRepository(db)
|
||||
Invoices = NewGORMInvoiceRepository(db)
|
||||
}
|
||||
|
||||
@@ -591,10 +591,6 @@ video {
|
||||
grid-column: span 3 / span 3;
|
||||
}
|
||||
|
||||
.-m-1\.5 {
|
||||
margin: -0.375rem;
|
||||
}
|
||||
|
||||
.m-2 {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
@@ -603,10 +599,6 @@ video {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.m-8 {
|
||||
margin: 2rem;
|
||||
}
|
||||
|
||||
.-mx-2 {
|
||||
margin-left: -0.5rem;
|
||||
margin-right: -0.5rem;
|
||||
@@ -686,18 +678,10 @@ video {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.inline-flex {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.table {
|
||||
display: table;
|
||||
}
|
||||
@@ -774,10 +758,6 @@ video {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.min-w-full {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.max-w-2xl {
|
||||
max-width: 42rem;
|
||||
}
|
||||
@@ -802,10 +782,6 @@ video {
|
||||
max-width: 1280px;
|
||||
}
|
||||
|
||||
.max-w-4xl {
|
||||
max-width: 56rem;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
@@ -834,30 +810,14 @@ video {
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-6 {
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-7 {
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
@@ -870,10 +830,6 @@ video {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
@@ -936,10 +892,6 @@ video {
|
||||
border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1));
|
||||
}
|
||||
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
@@ -1022,11 +974,6 @@ video {
|
||||
background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-blue-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-blue-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));
|
||||
@@ -1102,11 +1049,6 @@ video {
|
||||
background-color: rgb(220 252 231 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-green-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-green-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
|
||||
@@ -1192,11 +1134,6 @@ video {
|
||||
background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-red-800 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(153 27 27 / var(--tw-bg-opacity, 1));
|
||||
@@ -1292,16 +1229,6 @@ video {
|
||||
background-color: rgb(24 24 27 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-red-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-green-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.fill-red-50 {
|
||||
fill: #fef2f2;
|
||||
}
|
||||
@@ -1315,10 +1242,6 @@ video {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.p-1\.5 {
|
||||
padding: 0.375rem;
|
||||
}
|
||||
|
||||
.p-2 {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
@@ -1331,10 +1254,6 @@ video {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.p-8 {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
@@ -1400,11 +1319,6 @@ video {
|
||||
padding-bottom: 6rem;
|
||||
}
|
||||
|
||||
.py-3 {
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.py-4 {
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
@@ -1415,16 +1329,6 @@ video {
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.px-8 {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.pb-3 {
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
@@ -1461,18 +1365,6 @@ video {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-start {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.text-end {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
@@ -1544,10 +1436,6 @@ video {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.leading-10 {
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
@@ -1829,33 +1717,11 @@ video {
|
||||
color: rgb(39 39 42 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.text-red-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(185 28 28 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.text-green-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(21 128 61 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.antialiased {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.shadow-2xl {
|
||||
--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||
@@ -1878,24 +1744,6 @@ video {
|
||||
outline-color: #d1d5db;
|
||||
}
|
||||
|
||||
.ring-1 {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.ring-inset {
|
||||
--tw-ring-inset: inset;
|
||||
}
|
||||
|
||||
.ring-red-600\/10 {
|
||||
--tw-ring-color: rgb(220 38 38 / 0.1);
|
||||
}
|
||||
|
||||
.ring-green-600\/20 {
|
||||
--tw-ring-color: rgb(22 163 74 / 0.2);
|
||||
}
|
||||
|
||||
.filter {
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
@@ -1984,11 +1832,6 @@ video {
|
||||
background-color: rgb(67 56 202 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.hover\:bg-red-700:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(185 28 28 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.hover\:bg-red-900:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(127 29 29 / var(--tw-bg-opacity, 1));
|
||||
@@ -2242,10 +2085,6 @@ video {
|
||||
max-width: 80rem;
|
||||
}
|
||||
|
||||
.lg\:grid-cols-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.lg\:grid-cols-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
@@ -2270,20 +2109,12 @@ video {
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.xl\:grid-cols-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.xl\:grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1536px) {
|
||||
.\32xl\:grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.\32xl\:px-0 {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
@@ -2300,11 +2131,6 @@ video {
|
||||
border-color: rgb(31 41 55 / var(--tw-divide-opacity, 1));
|
||||
}
|
||||
|
||||
.dark\:divide-neutral-700 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-opacity: 1;
|
||||
border-color: rgb(64 64 64 / var(--tw-divide-opacity, 1));
|
||||
}
|
||||
|
||||
.dark\:border-gray-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));
|
||||
@@ -2360,16 +2186,6 @@ video {
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.dark\:text-neutral-200 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(229 229 229 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.dark\:text-neutral-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(115 115 115 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.dark\:text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
|
||||
|
||||
@@ -3,9 +3,6 @@ package utils
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/dslipak/pdf"
|
||||
"io"
|
||||
)
|
||||
|
||||
func GenerateSessionId(length int) string {
|
||||
@@ -20,47 +17,3 @@ func GenerateSessionId(length int) string {
|
||||
func GenerateToken() string {
|
||||
return GenerateSessionId(16)
|
||||
}
|
||||
|
||||
const match = "/Page\x00"
|
||||
|
||||
// Pages reads the given io.ByteReader until EOF is reached, returning the
|
||||
// number of pages encountered.
|
||||
func Pages(reader io.ByteReader) (pages int) {
|
||||
i := 0
|
||||
for {
|
||||
b, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
check:
|
||||
switch match[i] {
|
||||
case 0:
|
||||
if !(b >= 'A' && b <= 'Z' || b >= 'a' && b <= 'z') {
|
||||
pages++
|
||||
}
|
||||
i = 0
|
||||
goto check
|
||||
case b:
|
||||
i++
|
||||
default:
|
||||
i = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PagesAtPath opens a PDF file at the given file path, returning the number
|
||||
// of pages found.
|
||||
func CountPagesAtPath(path string) (pages int) {
|
||||
r, err := pdf.Open(path)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("LOL")
|
||||
fmt.Println(err)
|
||||
return 0
|
||||
}
|
||||
|
||||
pages = r.NumPage()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
{{ template "header.html" . }}
|
||||
|
||||
|
||||
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img class="mx-auto h-10 w-auto" src="/static/img/logo-black.png" alt="Your Company">
|
||||
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Edit config options</h2>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
{{ range .data.configOptions }}
|
||||
<form action="/config/{{ .ID }}" method="POST">
|
||||
<div class="max-w-md mx-auto mt-4">
|
||||
<div class="flex">
|
||||
|
||||
<input type="text" id="key" name="key" value="{{ .Key }}" class="flex-grow border border-gray-300 rounded-l-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
<input type="text" id="value" name="value" value="{{ .Value }}" class="flex-grow border border-gray-300 rounded-l-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
<button type="submit" name="action" value="update" class="bg-blue-600 text-white ml-4 mr-4 rounded px-4 hover:bg-blue-700">Update</button>
|
||||
<button type="submit" name="action" value="delete" class="bg-red-800 text-white rounded px-4 hover:bg-red-900">Delete</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
<form action="/config" method="POST">
|
||||
<div class="max-w-md mx-auto mt-4">
|
||||
<div class="flex">
|
||||
<input type="text" id="key" name="key" placeholder="" class="flex-grow border border-gray-300 rounded-l-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
<input type="text" id="value" name="value" placeholder="" class="flex-grow border border-gray-300 rounded-l-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
<button type="submit" class="bg-green-600 text-white ml-4 mr-4 rounded px-4 hover:bg-green-700">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{ template "footer.html" . }}
|
||||
@@ -38,12 +38,6 @@
|
||||
hover:text-white">Print</a>
|
||||
<a href="/cart" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700
|
||||
hover:text-white">Cart</a>
|
||||
<a href="/config" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700
|
||||
hover:text-white">Config</a>
|
||||
<a href="/paper" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700
|
||||
hover:text-white">Paper</a>
|
||||
<a href="/invoice" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700
|
||||
hover:text-white">Invoices</a>
|
||||
<a href="/logout" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-red-300 hover:bg-gray-700 hover:text-white">Logout</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<div class="-m-1.5 overflow-x-auto">
|
||||
<div class="p-1.5 min-w-full inline-block align-middle">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-neutral-700">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">Image</th>
|
||||
<th scope="col" class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">Name</th>
|
||||
<th scope="col" class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">Variant</th>
|
||||
<th scope="col" class="px-6 py-3 text-end text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">Paper</th>
|
||||
<th scope="col" class="px-6 py-3 text-end text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">CoverPaper</th>
|
||||
<th scope="col" class="px-6 py-3 text-end text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">Amount</th>
|
||||
<th scope="col" class="px-6 py-3 text-end text-xs font-medium text-gray-500 uppercase dark:text-neutral-500">Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-neutral-700">
|
||||
{{ range .PrintJobs }}
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-neutral-200">
|
||||
<a href="/shopitems/{{ .Variant.ShopItemID }}" class="flex items-center aspect-square w-8 h-10 shrink-0">
|
||||
<img class="h-auto w-full max-h-full dark:hidden" src="/{{ .ShopItem.Image }}" alt="imac image" />
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200">{{ .ShopItem.Name }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200">{{ .Variant.Name}}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200">{{ .PaperType.Brand }} - {{.PaperType.Name }}: {{ .PaperType.Size }} {{ .PaperType.Weight }}g/m2</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200">{{ .PaperType.Brand }} - {{.PaperType.Name }}: {{ .PaperType.Size }} {{ .PaperType.Weight }}g/m2</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200">{{ .Amount }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200">{{ .PriceTotal }}</td>
|
||||
</tr>
|
||||
|
||||
{{ end }}
|
||||
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-neutral-200">
|
||||
<b>TOTAL</b>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200"></td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200"></td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200"></td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200"></td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200"></td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-neutral-200"><b>{{ .PriceTotal }}</b></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,29 +0,0 @@
|
||||
{{ template "header.html" . }}
|
||||
|
||||
|
||||
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img class="mx-auto h-10 w-auto" src="/static/img/logo-black.png" alt="Your Company">
|
||||
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Invoices</h2>
|
||||
</div>
|
||||
|
||||
{{ range .data.invoices }}
|
||||
<div class="w-full grid grid-cols-1 gap-4 mx-auto p-4 m-4 flex flex-wrap border rounded shadow-md">
|
||||
<div class="">
|
||||
<div class="font-bold text-center mb-4">
|
||||
Invoice #{{ .ID }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
{{ template "invoice.html" . }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 mt-4 flex flex-wrap gap-2 w-full">
|
||||
<form action="/invoice/{{ .ID }}" method="POST">
|
||||
<button type="submit" name="action" value="delete" class="bg-red-500 hover:bg-red-700 text-white text-sm/6 font-bold py-2 px-4 rounded">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ template "footer.html" . }}
|
||||
@@ -1,82 +0,0 @@
|
||||
{{ template "header.html" . }}
|
||||
|
||||
|
||||
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img class="mx-auto h-10 w-auto" src="/static/img/logo-black.png" alt="Your Company">
|
||||
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Edit Paper</h2>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 ">
|
||||
<div class="w-full grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-4">
|
||||
{{ range .data.paper }}
|
||||
<form action="/paper/{{ .ID }}" method="POST">
|
||||
<div class="max-w-md mx-auto p-4 m-4 bg-gray-100 flex flex-wrap border rounded shadow-md">
|
||||
<div class="font-bold text-center mb-4">
|
||||
{{ .Brand }} - {{ .Name }}: {{ .Size }} {{ .Weight }}g/m2
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Name</label>
|
||||
<input type="text" id="name" name="name" value="{{ .Name }}" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Brand</label>
|
||||
<input type="text" id="brand" name="brand" value="{{ .Brand }}" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">DIN Size</label>
|
||||
<input type="text" id="size" name="size" value="{{ .Size }}" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Weight</label>
|
||||
<input type="text" id="weight" name="weight" value="{{ .Weight }}" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Price per Sheet</label>
|
||||
<input type="number" step="0.0001" min="0.0000" id="price" name="price" value="{{ .Price }}" class="w-full flex-grow border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 mt-4 flex flex-wrap gap-2 w-full">
|
||||
<button type="submit" name="action" value="update" class="bg-blue-500 hover:bg-blue-700 text-white text-sm/6 font-bold py-2 px-4 rounded">Update</button>
|
||||
<button type="submit" name="action" value="delete" class="bg-red-500 hover:bg-red-700 text-white text-sm/6 font-bold py-2 px-4 rounded">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
<form action="/paper" method="POST">
|
||||
<div class="max-w-md mx-auto p-4 flex flex-wrap border rounded shadow-md">
|
||||
<div class="font-bold text-center mb-4">
|
||||
Add new Paper
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Name</label>
|
||||
<input type="text" id="name" name="name" placeholder="name" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Brand</label>
|
||||
<input type="text" id="brand" name="brand" placeholder="brand" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">DIN Size</label>
|
||||
<input type="text" id="size" name="size" placeholder="size" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Weight</label>
|
||||
<input type="text" id="weight" name="weight" placeholder="Weight" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label for="variant-value1" class="block text-sm/6 font-medium text-gray-900">Price per Sheet</label>
|
||||
<input type="number" step="0.0001" min="0.0000" id="price" name="price" placeholder="price per sheet"
|
||||
class="w-full flex-grow border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 mt-4 flex flex-wrap gap-2 w-full">
|
||||
<button type="submit" class="bg-green-500 hover:bg-green-700 text-white text-sm/6 font-bold py-2 px-4 rounded">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{ template "footer.html" . }}
|
||||
@@ -1,22 +0,0 @@
|
||||
{{ template "header.html" . }}
|
||||
|
||||
<section class="bg-white py-8 antialiased dark:bg-gray-900 md:py-16">
|
||||
<div class="mx-auto max-w-3xl">
|
||||
<div class="mt-6 sm:mt-8">
|
||||
<div class="relative overflow-x-auto border-b border-gray-200 dark:border-gray-800">
|
||||
<h2 class="title font-manrope font-bold text-4xl leading-10 mb-8 text-center text-black">Print Started
|
||||
</h2>
|
||||
<div class="w-full grid grid-cols-1 gap-4 mx-auto p-4 m-4 flex flex-wrap border rounded shadow-md">
|
||||
<div class="flex flex-col">
|
||||
{{ template "invoice.html" .data.invoice }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 mt-4 flex flex-wrap gap-2 w-full">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{ template "footer.html" . }}
|
||||
@@ -1,7 +1,7 @@
|
||||
{{ template "header.html" . }}
|
||||
|
||||
<section class="bg-white py-8 antialiased dark:bg-gray-900 md:py-16">
|
||||
<div class="mx-auto max-w-4xl">
|
||||
<div class="mx-auto max-w-3xl">
|
||||
<div class="mt-6 sm:mt-8">
|
||||
<div class="relative overflow-x-auto border-b border-gray-200 dark:border-gray-800">
|
||||
<h2 class="title font-manrope font-bold text-4xl leading-10 mb-8 text-center text-black">Zineshop Print
|
||||
@@ -15,7 +15,7 @@
|
||||
<p class="font-normal text-base leading-7 text-gray-500 text-left mb-5 mt-6">
|
||||
<bold>CoverPage</bold>: If selected, the Printer will take Paper from the BypassTray for the first page. For
|
||||
example you can put colored paper there to have a nice looking front page, and the rest will be normal paper.
|
||||
Make sure you put paper in that tray when selecting this option.<br><br>
|
||||
Makue sure you put paper in that tray when selecting this option.<br><br>
|
||||
|
||||
Print Order: The Zines will be printed from top to bottom as seen in this list.
|
||||
|
||||
@@ -33,30 +33,14 @@
|
||||
<a href="/shopitems/{{ .ItemVariant.ShopItemID }}" class="flex items-center aspect-square w-8 h-10 shrink-0">
|
||||
<img class="h-auto w-full max-h-full dark:hidden" src="/{{ .ShopItem.Image }}" alt="imac image" />
|
||||
</a>
|
||||
|
||||
{{ if .ShopItem.WasPrinted }}
|
||||
<span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-green-600/20 ring-inset">Tested</span>
|
||||
{{ else }}
|
||||
<span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-red-600/10 ring-inset">NOT TESTED</span>
|
||||
{{ end }}
|
||||
<a href="/shopitems/{{ .ItemVariant.ShopItemID }}" class="hover:underline">{{ .ShopItem.Name }} - {{ .ItemVariant.Name }}</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="whitespace-nowrap py-4">
|
||||
<select name="variant-papertype[]" required class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
{{ range $.data.paper }}
|
||||
<option value="{{ .ID }}">{{ .Brand }} - {{ .Name }}: {{ .Size }} {{ .Weight }}g/m2</option>
|
||||
{{ end}}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class="whitespace-nowrap py-4">
|
||||
<select name="variant-coverpage[]" required class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<option selected value="0">None</option>
|
||||
{{ range $.data.paper }}
|
||||
<option value="{{ .ID }}">{{ .Brand }} - {{ .Name }}: {{ .Size }} {{ .Weight }}g/m2</option>
|
||||
{{ end}}
|
||||
<option selected value="0">Normal</option>
|
||||
<option value="1">CoverPage</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<div class="myClass group relative">
|
||||
<a href="/shopitems/{{ .ID }}">
|
||||
<img loading="lazy" src="/{{ .Image }}" alt="Product Image" class="shadow-2xl aspect-4/5 mx-auto rounded bg-gray-200 object-cover group-hover:opacity-75 lg:aspect-auto lg:h-80">
|
||||
<img loading="lazy" src="/{{ .Image }}" alt="Product Image" class="aspect-4/5 mx-auto rounded bg-gray-200 object-cover group-hover:opacity-75 lg:aspect-auto lg:h-80">
|
||||
</a>
|
||||
<div class="mt-4 flex justify-between">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user