Files
uptop/internal/tui/tab_users.go
T
lerko 0e6dc774cb refactor(tui): extract shared table rendering, fix cursor bounds
- New table_helpers.go with renderTable() and shared styles
- Remove 4 duplicated style blocks (header/cell/selected/border)
  from tab_alerts.go and tab_users.go
- All 3 tab views now use renderTable() for offset/end calc,
  selected row highlighting, and table construction
- Sites tab keeps siteGroupStyle via StyleOverride callback
- Clamp cursor to list length at end of refreshData() to prevent
  index-out-of-bounds after concurrent list changes
- Fix off-by-one in tab click handler (i <= maxTabs → i < tabCount)
2026-05-15 00:49:14 -04:00

116 lines
2.4 KiB
Go

package tui
import (
"fmt"
"go-upkeep/internal/monitor"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/huh"
)
type userFormData struct {
Username string
PublicKey string
Role string
}
func fmtRole(role string) string {
if role == "admin" {
return specialStyle.Render(role)
}
return role
}
func fmtKey(key string) string {
if len(key) > 40 {
return key[:20] + "..." + key[len(key)-17:]
}
return key
}
func (m Model) viewUsersTab() string {
if len(m.users) == 0 {
return "\n No users configured. Press [n] to add one."
}
return m.renderTable(
[]string{"#", "USERNAME", "ROLE", "PUBLIC KEY"},
len(m.users),
func(start, end int) [][]string {
var rows [][]string
for i := start; i < end; i++ {
u := m.users[i]
rows = append(rows, []string{
fmt.Sprintf("%d", i+1),
m.zones.Mark(fmt.Sprintf("user-%d", i), limitStr(u.Username, 15)),
fmtRole(u.Role),
fmtKey(u.PublicKey),
})
}
return rows
},
nil, nil,
)
}
func (m *Model) initUserHuhForm() tea.Cmd {
m.userFormData = &userFormData{
Role: "user",
}
if m.editID > 0 {
for _, u := range m.users {
if u.ID == m.editID {
m.userFormData.Username = u.Username
m.userFormData.PublicKey = u.PublicKey
m.userFormData.Role = u.Role
break
}
}
}
m.huhForm = huh.NewForm(
huh.NewGroup(
huh.NewInput().Title("Username").
Placeholder("admin").
Value(&m.userFormData.Username).
Validate(func(s string) error {
if s == "" {
return fmt.Errorf("username is required")
}
return nil
}),
huh.NewInput().Title("SSH Public Key").
Placeholder("ssh-ed25519 AAAA...").
Value(&m.userFormData.PublicKey).
Validate(func(s string) error {
if s == "" {
return fmt.Errorf("public key is required")
}
return nil
}),
huh.NewSelect[string]().Title("Role").
Options(
huh.NewOption("User", "user"),
huh.NewOption("Admin", "admin"),
).Value(&m.userFormData.Role),
).Title("SSH Access"),
).WithTheme(huh.ThemeDracula())
return m.huhForm.Init()
}
func (m *Model) submitUserForm() {
d := m.userFormData
if m.editID > 0 {
if err := m.store.UpdateUser(m.editID, d.Username, d.PublicKey, d.Role); err != nil {
monitor.AddLog("Update user failed: " + err.Error())
}
} else {
if err := m.store.AddUser(d.Username, d.PublicKey, d.Role); err != nil {
monitor.AddLog("Add user failed: " + err.Error())
}
}
m.state = stateUsers
}