Files
volumen/internal/admin/settings_views.go
T
petrbalvin f8ed33df83
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Initial commit
Assisted-by: GLM 5.3
2026-09-29 10:03:32 +02:00

183 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
package admin
import (
"fmt"
"strings"
"sourcedock.dev/petrbalvin/volumen/internal/store"
"sourcedock.dev/petrbalvin/volumen/internal/tokens"
"sourcedock.dev/petrbalvin/volumen/internal/users"
"sourcedock.dev/petrbalvin/volumen/internal/webhooks"
)
// roleOption is one <option> of a role select.
type roleOption struct {
Value string
Selected bool
}
// userRow is one entry of the users panel.
type userRow struct {
Username string
Display string
Initial string
Role string
Photo string
IsSelf bool
RoleOptions []roleOption
}
// hookRow is one configured webhook endpoint.
type hookRow struct {
Index string
URL string
// Managed is false for a hook declared in config.toml, which the
// settings forms may test but not change.
Managed bool
Enabled bool
Signed bool
EventsText string
}
// deliveryRow is one webhook delivery log entry.
type deliveryRow struct {
Timestamp string
Event string
HookURL string
OK bool
StatusCode int
Error string
Attempts int
// Result is the pre-formatted failure text ("failed (N attempts)"),
// translated by the caller that knows the request's language.
Result string
}
// tokenRow is one API token table row.
type tokenRow struct {
Name string
CreatedDay string
LastUsedDay string
}
// mediaRow is one media library tile.
type mediaRow struct {
Name string
URL string
SizeKB string
// Dimensions is the header-carried pixel size ("1920 × 1080"), or
// "" when the container did not yield one.
Dimensions string
}
func roleOptions(current string) []roleOption {
out := make([]roleOption, 0, len(users.Roles))
for _, role := range users.Roles {
out = append(out, roleOption{Value: role, Selected: role == current})
}
return out
}
func userRows(current string, list []*users.User) []userRow {
out := make([]userRow, 0, len(list))
for _, user := range list {
display := user.Name
if display == "" {
display = user.Username
}
out = append(out, userRow{
Username: user.Username,
Display: display,
Initial: firstUpper(display, "?"),
Role: user.Role,
Photo: user.Photo,
IsSelf: user.Username == current,
RoleOptions: roleOptions(user.Role),
})
}
return out
}
// hookRows renders the manager's merged hook list; the first static
// count came from config.toml and the rest are the admin's to manage.
func hookRows(hooks []webhooks.Webhook, staticCount int) []hookRow {
out := make([]hookRow, 0, len(hooks))
for i, hook := range hooks {
eventsText := "all"
if len(hook.Events) > 0 {
eventsText = strings.Join(hook.Events, ", ")
}
out = append(out, hookRow{
Index: fmt.Sprintf("%d", i),
URL: hook.URL,
Managed: i >= staticCount,
Enabled: hook.Enabled,
Signed: hook.Secret != "",
EventsText: eventsText,
})
}
return out
}
func deliveryRows(list []webhooks.Delivery) []deliveryRow {
out := make([]deliveryRow, 0, len(list))
for _, d := range list {
out = append(out, deliveryRow{
Timestamp: d.Timestamp,
Event: d.Event,
HookURL: d.HookURL,
OK: d.Status == "ok",
StatusCode: d.StatusCode,
Error: d.Error,
Attempts: d.Attempts,
})
}
return out
}
func tokenRows(list []tokens.Token) []tokenRow {
out := make([]tokenRow, 0, len(list))
for _, token := range list {
lastUsed := "never"
if len(token.LastUsed) >= 10 {
lastUsed = token.LastUsed[:10]
}
created := token.Created
if len(created) >= 10 {
created = created[:10]
}
out = append(out, tokenRow{
Name: token.Name,
CreatedDay: created,
LastUsedDay: lastUsed,
})
}
return out
}
func mediaRows(list []store.Media) []mediaRow {
out := make([]mediaRow, 0, len(list))
for _, item := range list {
out = append(out, mediaRow{
Name: item.Name,
URL: item.URL,
SizeKB: fmt.Sprintf("%.1f", float64(item.Size)/1024),
Dimensions: pixelSize(item.Width, item.Height),
})
}
return out
}
// pixelSize renders the header-carried pixel size, empty when the
// container did not yield one.
func pixelSize(width, height int) string {
if width <= 0 || height <= 0 {
return ""
}
return fmt.Sprintf("%d × %d", width, height)
}