feat(admin): editable tunable settings UI with grouped sub-sections
Replace the read-only "System Information" card (which listed hardcoded values) with editable HTMX forms, organized so the live vs restart distinction and related settings are visually clear. admin_settings.templ: - AdminSettings signature now takes liveGroups and restartGroups ([]SettingGroup) instead of a flat entry list. - Remove the static System Information list. Render two cards: "Live" (green, applies immediately) and "Restart Required" (warning header, saved but only takes effect after restart). - Within each card, TunableSettingsSection clusters entries into labeled sub-sections by Group (e.g. "Password Quality", "Device Rate Limits", "Login Lockout", "Worker Pool") with uppercase tracked sub-headers. - TunableSettingRow renders an inline HTMX form per setting: a Yes/No select for bools, a number input with min/max for ints, text otherwise, posting to /admin/settings/tunable. Rows show "modified from default" when the value differs from the compiled default. types.go: - Add SettingEntry (template-local mirror of database.SettingEntry, keeps templates from importing database) and SettingGroup. utils.go: - Add GroupTunableSettings: splits a flat, group-sorted entry list into live and restart []SettingGroup buckets preserving source order. utils_test.go covers the multi-group + empty cases. frontend.go: - The /admin/settings page handler now loads entries from the registry, drops the three keys that have dedicated UI cards (default_timezone dropdown, scan_poll_interval_seconds, auto_scan_enabled) so they are not listed twice, groups the rest, and passes liveGroups/restartGroups into the template.
This commit is contained in:
@@ -303,3 +303,22 @@ func formatDateForInput(d pgtype.Date) string {
|
||||
}
|
||||
return d.Time.Format("2006-01-02")
|
||||
}
|
||||
|
||||
// GroupTunableSettings splits a flat, group-sorted entry list into labeled
|
||||
// sub-section groups, separated into "live" (applies immediately) and
|
||||
// "restart required" buckets. Entries keep their original order so groups stay
|
||||
// coherent.
|
||||
func GroupTunableSettings(entries []SettingEntry) (live, restart []SettingGroup) {
|
||||
var liveGroups, restartGroups []SettingGroup
|
||||
for _, e := range entries {
|
||||
target := &liveGroups
|
||||
if e.RequiresRestart {
|
||||
target = &restartGroups
|
||||
}
|
||||
if len(*target) == 0 || (*target)[len(*target)-1].Name != e.Group {
|
||||
*target = append(*target, SettingGroup{Name: e.Group})
|
||||
}
|
||||
(*target)[len(*target)-1].Entries = append((*target)[len(*target)-1].Entries, e)
|
||||
}
|
||||
return liveGroups, restartGroups
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user