64 lines
1.8 KiB
Go
64 lines
1.8 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|||
|
|
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||
|
|
|
||
|
|
package admin
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"sourcedock.dev/petrbalvin/volumen/internal/store"
|
||
|
|
)
|
||
|
|
|
||
|
|
func (a *Admin) registerMediaRoutes(mux *http.ServeMux) {
|
||
|
|
mux.HandleFunc("GET /admin/media", a.requireLogin(a.handleMediaLibrary))
|
||
|
|
mux.HandleFunc("POST /admin/media/{name}/delete", a.requireLogin(a.handleMediaDelete))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (a *Admin) handleMediaLibrary(w http.ResponseWriter, r *http.Request) {
|
||
|
|
data := a.pageData(r)
|
||
|
|
items := a.deps.Store.ListMedia()
|
||
|
|
data.MediaItems = mediaRows(items)
|
||
|
|
data.MediaTotal = humanSize(totalSize(items))
|
||
|
|
data.Crumbs = []Crumb{{Label: "Media", IsLast: true, UI: true}}
|
||
|
|
a.renderPage(w, r, "media.html", data, http.StatusOK)
|
||
|
|
}
|
||
|
|
|
||
|
|
// totalSize sums the byte sizes of the media library.
|
||
|
|
func totalSize(items []store.Media) int64 {
|
||
|
|
var total int64
|
||
|
|
for _, item := range items {
|
||
|
|
total += item.Size
|
||
|
|
}
|
||
|
|
return total
|
||
|
|
}
|
||
|
|
|
||
|
|
// humanSize formats a byte count for the library summary: kilobytes
|
||
|
|
// below a megabyte (rounded up, so nothing reads as zero), megabytes
|
||
|
|
// above it, empty for an empty library.
|
||
|
|
func humanSize(total int64) string {
|
||
|
|
switch {
|
||
|
|
case total <= 0:
|
||
|
|
return ""
|
||
|
|
case total < 1024*1024:
|
||
|
|
kb := (total + 1023) / 1024
|
||
|
|
return fmt.Sprintf("%d kB", kb)
|
||
|
|
default:
|
||
|
|
return fmt.Sprintf("%.1f MB", float64(total)/(1024*1024))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (a *Admin) handleMediaDelete(w http.ResponseWriter, r *http.Request) {
|
||
|
|
if !a.requireCSRF(w, r) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
name := r.PathValue("name")
|
||
|
|
if !a.deps.Store.DeleteMedia("/media/" + strings.TrimPrefix(name, "/")) {
|
||
|
|
http.Error(w, "File not found", http.StatusNotFound)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
a.record(r, "media.deleted", fmt.Sprintf("/media/%s", name), nil)
|
||
|
|
http.Redirect(w, r, "/admin/media", http.StatusSeeOther)
|
||
|
|
}
|