add batchupload
This commit is contained in:
@@ -27,6 +27,8 @@ type ShopItemController interface {
|
|||||||
ShopItemView(*gin.Context)
|
ShopItemView(*gin.Context)
|
||||||
AddItemView(*gin.Context)
|
AddItemView(*gin.Context)
|
||||||
AddItemHandler(*gin.Context)
|
AddItemHandler(*gin.Context)
|
||||||
|
AddItemsView(*gin.Context)
|
||||||
|
AddItemsHandler(*gin.Context)
|
||||||
CreateTag(*gin.Context)
|
CreateTag(*gin.Context)
|
||||||
GetAllTags(*gin.Context)
|
GetAllTags(*gin.Context)
|
||||||
EditItemView(*gin.Context)
|
EditItemView(*gin.Context)
|
||||||
@@ -316,6 +318,94 @@ func (rc *shopItemController) AddItemHandler(c *gin.Context) {
|
|||||||
c.HTML(http.StatusOK, "additem.html", data)
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, 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 (rc *shopItemController) EditItemView(c *gin.Context) {
|
func (rc *shopItemController) EditItemView(c *gin.Context) {
|
||||||
shopItem, err := repositories.ShopItems.GetById(c.Param("id"))
|
shopItem, err := repositories.ShopItems.GetById(c.Param("id"))
|
||||||
tags, err := repositories.Tags.GetAll()
|
tags, err := repositories.Tags.GetAll()
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -104,9 +104,11 @@ func main() {
|
|||||||
viewRoutes.GET("/register", userController.RegisterView)
|
viewRoutes.GET("/register", userController.RegisterView)
|
||||||
viewRoutes.GET("/passwordreset", userController.ResetView)
|
viewRoutes.GET("/passwordreset", userController.ResetView)
|
||||||
viewRoutes.GET("/additem", authValidator.RequireAuth, shopItemController.AddItemView)
|
viewRoutes.GET("/additem", authValidator.RequireAuth, shopItemController.AddItemView)
|
||||||
|
viewRoutes.GET("/batchupload", authValidator.RequireAuth, shopItemController.AddItemsView)
|
||||||
viewRoutes.POST("/login", userController.LoginHandler)
|
viewRoutes.POST("/login", userController.LoginHandler)
|
||||||
viewRoutes.POST("/register", userController.RegisterHandler)
|
viewRoutes.POST("/register", userController.RegisterHandler)
|
||||||
viewRoutes.POST("/additem", authValidator.RequireAuth, shopItemController.AddItemHandler)
|
viewRoutes.POST("/additem", authValidator.RequireAuth, shopItemController.AddItemHandler)
|
||||||
|
viewRoutes.POST("/batchupload", authValidator.RequireAuth, shopItemController.AddItemsHandler)
|
||||||
viewRoutes.POST("/passwordreset", userController.ResetHandler)
|
viewRoutes.POST("/passwordreset", userController.ResetHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ func (p *PrintJob) Execute() error {
|
|||||||
baseCommand += fmt.Sprintf(" %v ", option)
|
baseCommand += fmt.Sprintf(" %v ", option)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
baseCommand += fmt.Sprintf(" -- %s", p.Pdf)
|
||||||
|
|
||||||
fmt.Println(baseCommand)
|
fmt.Println(baseCommand)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
53
views/batchupload.html
Normal file
53
views/batchupload.html
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{{ 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/circlea.png" alt="Your Company">
|
||||||
|
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Batch Upload</h2>
|
||||||
|
Select multiple files on the upload. For each a new Shop Item will be created with the Filename as Name, Abstract
|
||||||
|
and Description.<br>
|
||||||
|
Afterwards you should edit every item and set the proper Values for that, price and so on.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
|
<form class="space-y-6" action="/additems" method="POST" enctype="multipart/form-data">
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-900">
|
||||||
|
PDF
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-md">
|
||||||
|
<div class="space-y-1 text-center">
|
||||||
|
<svg class="mx-auto h-12 w-12 text-gray-900" stroke="currentColor" fill="none" viewBox="0 0 48 48" aria-hidden="true">
|
||||||
|
<path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
|
</svg>
|
||||||
|
<div class="flex text-sm text-gray-600">
|
||||||
|
<label for="pdf-upload" class="relative cursor-pointer bg-white rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500">
|
||||||
|
<span class="">Upload a file</span>
|
||||||
|
<input id="pdf-upload" name="pdf" type="file" multiple="multiple" accept="application/pdf" class="sr-only">
|
||||||
|
</label>
|
||||||
|
<p class="pl-1 text-gray-900">or drag and drop</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-gray-900">
|
||||||
|
PDF up to 50MB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-10 text-center text-sm/6 text-red-500">
|
||||||
|
{{ .data.error }}
|
||||||
|
</p>
|
||||||
|
<p class="mt-10 text-center text-sm/6 text-green-500">
|
||||||
|
{{ .data.success }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Add Item</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ template "footer.html" . }}
|
||||||
@@ -29,6 +29,10 @@
|
|||||||
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 px-4 sm:px-8">
|
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 px-4 sm:px-8">
|
||||||
<a href="/additem" 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">Add Item</a>
|
<a href="/additem" 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">Add Item</a>
|
||||||
<a href="/tags" 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">Tags</a>
|
<a href="/tags" 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">Tags</a>
|
||||||
|
<a href="/cart/print" 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">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="/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>
|
<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>
|
</div>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
|||||||
@@ -4,10 +4,15 @@
|
|||||||
<div class="mx-auto max-w-3xl">
|
<div class="mx-auto max-w-3xl">
|
||||||
<div class="mt-6 sm:mt-8">
|
<div class="mt-6 sm:mt-8">
|
||||||
<div class="relative overflow-x-auto border-b border-gray-200 dark:border-gray-800">
|
<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
|
||||||
|
Service
|
||||||
|
</h2>
|
||||||
|
<p class="font-normal text-base leading-7 text-gray-900 text-left mb-5 mt-6">
|
||||||
|
Pressing Print will automatically print the given Zines for you.<br>
|
||||||
|
Add Zines for printing simply by adding them to the Cart
|
||||||
|
</p>
|
||||||
|
|
||||||
<p class="font-normal text-base leading-7 text-gray-500 text-left mb-5 mt-6">
|
<p class="font-normal text-base leading-7 text-gray-500 text-left mb-5 mt-6">
|
||||||
Welcome to the Zineshop Printservice.<br>
|
|
||||||
Pressing Print will automatically print the given Zines for you.
|
|
||||||
All you have to do is set an Amount for each Zine you want to print.<br><br>
|
|
||||||
<bold>CoverPage</bold>: If selected, the Printer will take Paper from the BypassTray for the first page. For
|
<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.
|
example you can put colored paper there to have a nice looking front page, and the rest will be normal paper.
|
||||||
Makue 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>
|
||||||
|
|||||||
@@ -77,25 +77,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
|
||||||
<div class="bg-gray-200 rounded m-4 p-4">
|
|
||||||
<div class="relative flex rounded-lg justify-center items-center">
|
|
||||||
<img src="/{{ .data.shopItem.Image }}" alt="shopping image"
|
|
||||||
class="object-cover items-center justify-center rounded">
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg">{{ .data.shopItem.Name }}</h3>
|
|
||||||
<i class="text-xs">{{ .data.shopItem.Abstract }}</i>
|
|
||||||
<p class="text-xs">{{ .data.shopItem.Description }}</p>
|
|
||||||
<p class="">Price: {{ .data.shopItem.Price }}</p>
|
|
||||||
{{ if .loggedIn }}
|
|
||||||
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 px-4 sm:px-8">
|
|
||||||
<a href="{{ .data.shopItem.ID }}/edit" 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">Edit</a>
|
|
||||||
<a href="{{ .data.shopItem.ID }}/delete" 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">Delete</a>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
{{ template "footer.html" . }}
|
{{ template "footer.html" . }}
|
||||||
|
|||||||
Reference in New Issue
Block a user