simple binary create, delete, list

This commit is contained in:
Niko Abeler 2023-07-27 22:02:13 +02:00
parent e998272f81
commit ebca3e84f2
7 changed files with 220 additions and 0 deletions

View File

@ -24,3 +24,11 @@ func (s *BinaryService) CreateEntryFile(name string, file []byte, entry model.En
func (s *BinaryService) FindById(id string) (*model.BinaryFile, error) { func (s *BinaryService) FindById(id string) (*model.BinaryFile, error) {
return s.repo.FindById(id) return s.repo.FindById(id)
} }
func (s *BinaryService) ListIds() ([]string, error) {
return s.repo.ListIds()
}
func (s *BinaryService) Delete(binary *model.BinaryFile) error {
return s.repo.Delete(binary)
}

View File

@ -19,6 +19,8 @@ type BinaryRepository interface {
Create(name string, data []byte, entry model.Entry) (*model.BinaryFile, error) Create(name string, data []byte, entry model.Entry) (*model.BinaryFile, error)
FindById(id string) (*model.BinaryFile, error) FindById(id string) (*model.BinaryFile, error)
FindByNameForEntry(name string, entry model.Entry) (*model.BinaryFile, error) FindByNameForEntry(name string, entry model.Entry) (*model.BinaryFile, error)
ListIds() ([]string, error)
Delete(binary *model.BinaryFile) error
} }
type AuthorRepository interface { type AuthorRepository interface {

View File

@ -99,3 +99,21 @@ func (repo *DefaultBinaryFileRepo) FindByNameForEntry(name string, entry model.E
} }
return &model.BinaryFile{Id: sqlFile.Id, Name: sqlFile.Name, Data: sqlFile.Data}, nil return &model.BinaryFile{Id: sqlFile.Id, Name: sqlFile.Name, Data: sqlFile.Data}, nil
} }
// ListIds implements repository.BinaryRepository
func (repo *DefaultBinaryFileRepo) ListIds() ([]string, error) {
var ids []string
err := repo.db.Select(&ids, "SELECT id FROM binary_files")
if err != nil {
return nil, err
}
return ids, nil
}
// Delete implements repository.BinaryRepository
func (repo *DefaultBinaryFileRepo) Delete(binary *model.BinaryFile) error {
id := binary.Id
println("Deleting binary file", id)
_, err := repo.db.Exec("DELETE FROM binary_files WHERE id = ?", id)
return err
}

View File

@ -0,0 +1,59 @@
{{define "title"}}Binaries{{end}}
{{define "main"}}
<h2>Binaries</h2>
<form action="/admin/binaries/new" method="post" enctype="multipart/form-data">
<div>
<label for="file">File</label>
<input type="file" name="file" id="file">
</div>
<div>
<input type="submit" value="Upload">
</div>
</form>
<table role="grid">
<thead>
<tr>
<th scope="col">File</th>
<th scope="col">Actions</th>
</tr>
</thead>
{{ range .Binaries }}
<tr>
<td scope="row">
<a href="/media/{{ . }}">{{ . }}</a>
</td>
<td>
<form action="/admin/binaries/delete" method="post">
<input type="hidden" name="file" value="{{ . }}">
<label for="confirm">
<input type="checkbox" name="confirm"> Confirm
</label>
<input style="padding:0;height:2rem;" type="submit" value="Delete">
</form>
</td>
</tr>
{{ end }}
</table>
<hr>
<nav class="row">
{{ if not .FirstPage }}
<div>
<a href="?page={{ .PrevPage }}">Prev</a>
</div>
{{ end }}
<div>Page {{.Page}}</div>
{{ if not .LastPage }}
<div>
<a href="?page={{ .NextPage }}">Next</a>
</div>
{{ end }}
</nav>
{{end}}

View File

@ -52,11 +52,15 @@ func NewWebApp(
// admin // admin
adminHandler := NewAdminHandler(configRepo, configRegister, typeRegistry) adminHandler := NewAdminHandler(configRepo, configRegister, typeRegistry)
binaryManageHandler := NewBinaryManageHandler(configRepo, binService)
admin := app.Group("/admin") admin := app.Group("/admin")
admin.Use(middleware.NewAuthMiddleware(authorService).Handle) admin.Use(middleware.NewAuthMiddleware(authorService).Handle)
admin.Get("/", adminHandler.Handle) admin.Get("/", adminHandler.Handle)
admin.Get("/config/:config/", adminHandler.HandleConfigGet) admin.Get("/config/:config/", adminHandler.HandleConfigGet)
admin.Post("/config/:config/", adminHandler.HandleConfigPost) admin.Post("/config/:config/", adminHandler.HandleConfigPost)
admin.Get("/binaries/", binaryManageHandler.Handle)
admin.Post("/binaries/new/", binaryManageHandler.HandleUpload)
admin.Post("/binaries/delete", binaryManageHandler.HandleDelete)
// Editor // Editor
editor := app.Group("/editor") editor := app.Group("/editor")

View File

@ -0,0 +1,92 @@
package web
import (
"owl-blogs/app"
"owl-blogs/app/repository"
"owl-blogs/render"
"sort"
"strings"
"github.com/gofiber/fiber/v2"
)
type BinaryManageHandler struct {
configRepo repository.ConfigRepository
service *app.BinaryService
}
func NewBinaryManageHandler(configRepo repository.ConfigRepository, service *app.BinaryService) *BinaryManageHandler {
return &BinaryManageHandler{
configRepo: configRepo,
service: service,
}
}
func (h *BinaryManageHandler) Handle(c *fiber.Ctx) error {
siteConfig := getSiteConfig(h.configRepo)
allIds, err := h.service.ListIds()
sort.Slice(allIds, func(i, j int) bool {
return strings.ToLower(allIds[i]) < strings.ToLower(allIds[j])
})
if err != nil {
return err
}
pageData := paginate(c, allIds, 50)
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
return render.RenderTemplateWithBase(c, siteConfig, "views/binary_manager", fiber.Map{
"Binaries": pageData.items,
"Page": pageData.page,
"NextPage": pageData.page + 1,
"PrevPage": pageData.page - 1,
"FirstPage": pageData.page == 1,
"LastPage": pageData.lastPage,
})
}
func (h *BinaryManageHandler) HandleUpload(c *fiber.Ctx) error {
file, err := c.FormFile("file")
if err != nil {
return err
}
reader, err := file.Open()
if err != nil {
return err
}
defer reader.Close()
content := make([]byte, file.Size)
_, err = reader.Read(content)
if err != nil {
return err
}
binary, err := h.service.Create(file.Filename, content)
if err != nil {
return err
}
return c.Redirect("/media/" + binary.Id)
}
func (h *BinaryManageHandler) HandleDelete(c *fiber.Ctx) error {
id := c.FormValue("file")
binary, err := h.service.FindById(id)
if err != nil {
return err
}
confirm := c.FormValue("confirm")
if confirm != "on" {
return c.Redirect("/admin/binaries/")
}
err = h.service.Delete(binary)
if err != nil {
return err
}
return c.Redirect("/admin/binaries/")
}

View File

@ -4,6 +4,9 @@ import (
"owl-blogs/app/repository" "owl-blogs/app/repository"
"owl-blogs/config" "owl-blogs/config"
"owl-blogs/domain/model" "owl-blogs/domain/model"
"strconv"
"github.com/gofiber/fiber/v2"
) )
func getSiteConfig(repo repository.ConfigRepository) model.SiteConfig { func getSiteConfig(repo repository.ConfigRepository) model.SiteConfig {
@ -14,3 +17,37 @@ func getSiteConfig(repo repository.ConfigRepository) model.SiteConfig {
} }
return siteConfig return siteConfig
} }
type paginationData[T any] struct {
items []T
page uint
lastPage bool
}
func paginate[T any](c *fiber.Ctx, items []T, limit int) paginationData[T] {
page := c.Query("page")
if page == "" {
page = "1"
}
pageNum, err := strconv.Atoi(page)
if err != nil {
pageNum = 1
}
offset := (pageNum - 1) * limit
lastPage := false
if offset > len(items) {
offset = len(items)
lastPage = true
}
if offset+limit > len(items) {
limit = len(items) - offset
lastPage = true
}
items = items[offset : offset+limit]
return paginationData[T]{
items: items,
page: uint(pageNum),
lastPage: lastPage,
}
}