added nested query for QR codes, generateQRCodeURLs refactor

This commit is contained in:
icanotc 2023-08-28 01:07:50 -04:00
parent 508de803c1
commit 396160b0c8

View file

@ -2,9 +2,12 @@ package v1
import ( import (
"bytes" "bytes"
"context"
_ "embed"
"fmt" "fmt"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/hay-kot/homebox/backend/internal/core/services" "github.com/hay-kot/homebox/backend/internal/core/services"
"github.com/hay-kot/homebox/backend/internal/data/repo"
"github.com/hay-kot/homebox/backend/internal/web/adapters" "github.com/hay-kot/homebox/backend/internal/web/adapters"
"github.com/hay-kot/httpkit/errchain" "github.com/hay-kot/httpkit/errchain"
"github.com/signintech/gopdf" "github.com/signintech/gopdf"
@ -13,8 +16,6 @@ import (
"image/png" "image/png"
"io" "io"
"net/http" "net/http"
_ "embed"
) )
//go:embed assets/QRIcon.png //go:embed assets/QRIcon.png
@ -25,8 +26,9 @@ type query struct {
Data string `schema:"data" validate:"required,max=4296"` Data string `schema:"data" validate:"required,max=4296"`
} }
type pageQuery struct { type pageConfigQuery struct {
Nested *bool `schema:"nested" validate:"required"` Nested *bool `schema:"nested" validate:"required"`
NestLevel int `schema:"nestLevel" validate:"required,gte=1"`
PrintType string `schema:"printType" validate:"required,oneof=items locations both"` PrintType string `schema:"printType" validate:"required,oneof=items locations both"`
BaseAddr string `schema:"baseAddr" validate:"required"` BaseAddr string `schema:"baseAddr" validate:"required"`
} }
@ -89,14 +91,14 @@ func (ctrl *V1Controller) HandleGenerateQRCode() errchain.HandlerFunc {
// @Tags Items // @Tags Items
// @Produce application/pdf // @Produce application/pdf
// @Param location_id path string true "UUID of the location" // @Param location_id path string true "UUID of the location"
// @Param page query pageQuery true "query info for how the QR codes are generated" // @Param page query pageConfigQuery true "query info for how the QR codes are generated"
// @Success 200 {string} string "application/pdf" // @Success 200 {string} string "application/pdf"
// @Router /v1/qrcode/{location_id} [GET] // @Router /v1/qrcode/{location_id} [GET]
// @Security Bearer // @Security Bearer
func (ctrl *V1Controller) HandleGenerateQRCodeForLocations() errchain.HandlerFunc { func (ctrl *V1Controller) HandleGenerateQRCodeForLocations() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error { return func(w http.ResponseWriter, r *http.Request) error {
data, err := adapters.DecodeQuery[pageQuery](r) //decode the query with the pageQuery struct data, err := adapters.DecodeQuery[pageConfigQuery](r) //decode the query with the pageConfigQuery struct
if err != nil { if err != nil {
return err return err
} }
@ -114,39 +116,67 @@ func (ctrl *V1Controller) HandleGenerateQRCodeForLocations() errchain.HandlerFun
fmt.Println(routeUUID) fmt.Println(routeUUID)
auth := services.NewContext(r.Context()) auth := services.NewContext(r.Context())
locations, err := ctrl.repo.Locations.Get(auth, routeUUID) locations, err := ctrl.repo.Locations.Get(auth, routeUUID) //get the location
if err != nil { if err != nil {
return err return err
} }
var URLs []string var URLs []string
//if *data.Nested { URLs, err = ctrl.generateQRCodeURLs(locations, URLs, data) //this will append URLS to the URLs slice based on config (data)
// if err != nil {
//} return err
}
if data.PrintType == "items" { pdf, err := ctrl.generatePDF(URLs)
for _, thing := range locations.Items {
encodeStr := data.BaseAddr + "/item/" + thing.ID.String() //concat the url and then UUID // Return the concatenated QR code images as a response
URLs = append(URLs, encodeStr) w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", "attachment; filename=qrCodes.pdf")
fmt.Printf("%v", URLs)
//_, err = w.Write([]byte(fmt.Sprintf("%v", URLs)))
_, err = pdf.WriteTo(w)
if err != nil {
return err
} }
} else if data.PrintType == "locations" { return err
for _, thing := range locations.Children {
encodeStr := data.BaseAddr + "/location/" + thing.ID.String() //concat the url and then UUID
URLs = append(URLs, encodeStr)
}
} else if data.PrintType == "both" {
for _, thing := range locations.Items {
encodeStr := data.BaseAddr + "/item/" + thing.ID.String() //concat the url and then UUID
URLs = append(URLs, encodeStr)
}
for _, thing := range locations.Children {
encodeStr := data.BaseAddr + "/location/" + thing.ID.String() //concat the url and then UUID
URLs = append(URLs, encodeStr)
} }
} }
func (ctrl *V1Controller) generateQRCodeURLs(input repo.LocationOut, output []string, printConfig pageConfigQuery) ([]string, error) {
// processLocation processes the given location and its items or children based on the printConfig settings
if printConfig.PrintType == "items" || printConfig.PrintType == "both" {
for _, item := range input.Items {
output = append(output, printConfig.BaseAddr+"/item/"+item.ID.String())
}
}
if printConfig.PrintType == "locations" || printConfig.PrintType == "both" {
for _, child := range input.Children {
output = append(output, printConfig.BaseAddr+"/location/"+child.ID.String())
}
}
if *printConfig.Nested && printConfig.NestLevel > 1 {
printConfig.NestLevel-- //decrease nest level for each recursive call
for _, child := range input.Children {
childLocation, err := ctrl.repo.Locations.Get(context.Background(), child.ID)
if err != nil {
return nil, err
}
output, err = ctrl.generateQRCodeURLs(childLocation, output, printConfig)
if err != nil {
return nil, err
}
}
}
return output, nil
}
func (ctrl *V1Controller) generatePDF(URLs []string) (*gopdf.GoPdf, error) {
pdf := gopdf.GoPdf{} pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
pdf.AddPage() pdf.AddPage()
@ -166,12 +196,12 @@ func (ctrl *V1Controller) HandleGenerateQRCodeForLocations() errchain.HandlerFun
//turn each thing into a image buffer that gopdf accepts //turn each thing into a image buffer that gopdf accepts
qrc, err := qrcode.New(thing) qrc, err := qrcode.New(thing)
if err != nil { if err != nil {
return err return nil, err
} }
logo, err := png.Decode(bytes.NewReader(qrcodeLogo)) logo, err := png.Decode(bytes.NewReader(qrcodeLogo))
if err != nil { if err != nil {
return err return nil, err
} }
img := bytes.NewBuffer(nil) img := bytes.NewBuffer(nil)
@ -179,34 +209,21 @@ func (ctrl *V1Controller) HandleGenerateQRCodeForLocations() errchain.HandlerFun
err = qrc.Save(wr) err = qrc.Save(wr)
if err != nil { if err != nil {
return err return nil, err
} }
//add the image buffer to the pdf //add the image buffer to the pdf
imgBytes, err := gopdf.ImageHolderByBytes(img.Bytes()) imgBytes, err := gopdf.ImageHolderByBytes(img.Bytes())
if err != nil { if err != nil {
return err return nil, err
} }
x := (i % 4) * 150 x := (i % 4) * 150
y := rowCounter * 150 y := rowCounter * 150
err = pdf.ImageByHolder(imgBytes, float64(x), float64(y), nil) err = pdf.ImageByHolder(imgBytes, float64(x), float64(y), nil)
if err != nil { if err != nil {
return err return nil, err
}
}
// Return the concatenated QR code images as a response
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", "attachment; filename=qrCodes.pdf")
fmt.Printf("%v", URLs)
//_, err = w.Write([]byte(fmt.Sprintf("%v", URLs)))
_, err = pdf.WriteTo(w)
if err != nil {
return err
}
return err
} }
} }
return &pdf, nil
}