feat(error): add error message popup and retry when creating all kinds of authors

This is very much so hacky jank on top of more hacky jank but it works
This commit is contained in:
Slug-Boi
2025-04-04 19:44:26 +02:00
parent fe7f2c604f
commit d70825da65
+177 -37
View File
@@ -4,7 +4,6 @@ package tui
// from the Bubbles component library. // from the Bubbles component library.
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@@ -14,7 +13,6 @@ import (
"github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
//"github.com/inancgumus/screen"
) )
var ( var (
@@ -36,6 +34,63 @@ type model_ca struct {
inputs []textinput.Model inputs []textinput.Model
quitting bool quitting bool
exclude bool exclude bool
errorModel *errorModel
}
// Error popup model
type errorModel struct {
missing []string
visible bool
}
func errorGetMissingFields(m model_ca) {
inpLen := len(m.inputs)
if !tempAuthorToggle {
inpLen -= 1
}
if len(m.inputs) > 0 {
for i := 0; i < inpLen; i++ {
if m.inputs[i].Value() == "" {
m.errorModel.missing = append(m.errorModel.missing, "- "+strings.Split(m.inputs[i].Placeholder,"(")[0])
}
}
} else {
m.errorModel.missing = append(m.errorModel.missing, "GIGA ERROR NO INPUTS")
}
}
func (e errorModel) View() string {
var sb strings.Builder
sb.WriteString("Error")
if len(e.missing) > 0 {
sb.WriteString("\nMissing fields: \n")
sb.WriteString(strings.Join(e.missing, "\n"))
}
// Create centered content
content := lipgloss.JoinVertical(
lipgloss.Left, // Changed from Center to Left for better alignment
sb.String(),
"\n\n[enter/esc]",
)
// Create the error box
errorBox := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("9")).
Padding(1, 2).
Width(40).
Foreground(lipgloss.Color("9")).
Background(lipgloss.Color("0")).
Align(lipgloss.Center).
Render(content)
return lipgloss.NewStyle().
Padding(1, 0).
Render(errorBox)
} }
var parent_m *model var parent_m *model
@@ -45,13 +100,13 @@ func createAuthorModel(old_m *model) model_ca {
m := model_ca{ m := model_ca{
inputs: make([]textinput.Model, 5), inputs: make([]textinput.Model, 5),
errorModel: intitialErrorModel(),
} }
var t textinput.Model var t textinput.Model
for i := range m.inputs { for i := range m.inputs {
t = textinput.New() t = textinput.New()
t.Cursor.Style = cursorStyle t.Cursor.Style = cursorStyle
//t.CharLimit = 32
switch i { switch i {
case 0: case 0:
@@ -75,11 +130,71 @@ func createAuthorModel(old_m *model) model_ca {
return m return m
} }
func intitialErrorModel() *errorModel {
return &errorModel{
missing: []string{},
visible: false,
}
}
func createGHAuthorModel(old_m *model, user utils.User) model_ca {
parent_m = old_m
m := model_ca{
inputs: make([]textinput.Model, 5),
errorModel: intitialErrorModel(),
}
var t textinput.Model
for i := range m.inputs {
t = textinput.New()
t.Cursor.Style = cursorStyle
switch i {
case 0:
t.Placeholder = "Shortname (e.g. jo)"
t.SetValue(user.Shortname)
t.Focus()
t.PromptStyle = focusedStyle
t.TextStyle = focusedStyle
case 1:
t.Placeholder = "Long name (e.g. JohnDoe)"
t.SetValue(user.Longname)
case 2:
t.Placeholder = "Username (e.g. JohnDoe-gh)"
t.SetValue(user.Username)
case 3:
t.Placeholder = "Email (e.g. JohnDoe@domain.do"
t.SetValue("")
case 4:
t.Placeholder = "Group tags (e.g. gr1|gr2)"
t.SetValue(strings.Join(user.Groups, "|"))
}
m.inputs[i] = t
}
return m
}
func EntryGHAuthorModel(user utils.User) {
model := createGHAuthorModel(&model{}, user)
print(model.inputs[0].Value())
if _, err := tea.NewProgram(model).Run(); err != nil {
fmt.Println("Error running program:", err)
os.Exit(1)
}
}
func tempAuthorModel(old_m *model) model_ca { func tempAuthorModel(old_m *model) model_ca {
parent_m = old_m parent_m = old_m
m := model_ca{ m := model_ca{
inputs: make([]textinput.Model, 2), inputs: make([]textinput.Model, 2),
errorModel: intitialErrorModel(),
} }
var t textinput.Model var t textinput.Model
@@ -110,13 +225,35 @@ func (m model_ca) Init() tea.Cmd {
return textinput.Blink return textinput.Blink
} }
func updateErrorPopup(m model_ca, msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "enter", "esc", "ctrl+c":
m.errorModel.missing = []string{}
m.errorModel.visible = false
return m, nil
}
}
return m, nil
}
func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.errorModel.visible {
return updateErrorPopup(m, msg)
}
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch msg.String() { switch msg.String() {
case "ctrl+c", "esc": case "ctrl+c", "esc":
m.inputs = nil m.inputs = nil
if parent_m.keys != nil {
return nil, nil return nil, nil
}
return m, tea.Quit
// Set focus to next input // Set focus to next input
case "tab", "shift+tab", "enter", "up", "down": case "tab", "shift+tab", "enter", "up", "down":
@@ -126,8 +263,17 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if !tempAuthorToggle { if !tempAuthorToggle {
if s == "enter" && m.focusIndex == len(m.inputs)+1 { if s == "enter" && m.focusIndex == len(m.inputs)+1 {
m.quitting = true m.quitting = true
m.AddAuthor() m.errorModel.visible = m.AddAuthor()
if m.errorModel.visible {
m.quitting = false
return m, nil
}
if parent_m.keys != nil {
return model{list: parent_m.list}, tea.ClearScreen return model{list: parent_m.list}, tea.ClearScreen
} else {
m.quitting = true
return m, tea.Quit
}
} else if s == "enter" && m.focusIndex == len(m.inputs) { } else if s == "enter" && m.focusIndex == len(m.inputs) {
// toggle exclude // toggle exclude
m.exclude = !m.exclude m.exclude = !m.exclude
@@ -136,8 +282,17 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} else { } else {
if s == "enter" && m.focusIndex == len(m.inputs) { if s == "enter" && m.focusIndex == len(m.inputs) {
m.quitting = true m.quitting = true
m.TempAddAuthor() m.errorModel.visible = m.TempAddAuthor()
if m.errorModel.visible {
m.quitting = false
return m, nil
}
if parent_m.keys != nil {
return model{list: parent_m.list}, tea.ClearScreen return model{list: parent_m.list}, tea.ClearScreen
} else {
m.quitting = true
return m, tea.Quit
}
} }
} }
@@ -192,6 +347,13 @@ func (m *model_ca) updateInputs(msg tea.Msg) tea.Cmd {
} }
func (m model_ca) View() string { func (m model_ca) View() string {
if m.errorModel.visible {
if len(m.errorModel.missing) == 0 {
errorGetMissingFields(m)
}
return m.errorModel.View()
}
if m.quitting { if m.quitting {
return "" return ""
} }
@@ -237,19 +399,13 @@ func (m model_ca) View() string {
return b.String() return b.String()
} }
func (m *model_ca) AddAuthor() { func (m *model_ca) AddAuthor() bool {
if len(m.inputs) > 0 && if len(m.inputs) > 0 &&
m.inputs[0].Value() != "" && m.inputs[0].Value() != "" &&
m.inputs[1].Value() != "" && m.inputs[1].Value() != "" &&
m.inputs[2].Value() != "" && m.inputs[2].Value() != "" &&
m.inputs[3].Value() != "" { m.inputs[3].Value() != "" {
author_file := utils.Find_authorfile()
f, err := os.OpenFile(author_file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
panic(err)
}
defer f.Close()
var groups []string var groups []string
if m.inputs[4].Value() == "" { if m.inputs[4].Value() == "" {
groups = []string{} groups = []string{}
@@ -257,9 +413,6 @@ func (m *model_ca) AddAuthor() {
groups = strings.Split(m.inputs[4].Value(), "|") groups = strings.Split(m.inputs[4].Value(), "|")
} }
// create and add the user to the users map // create and add the user to the users map
usr := utils.User{ usr := utils.User{
Shortname: m.inputs[0].Value(), Shortname: m.inputs[0].Value(),
@@ -270,42 +423,29 @@ func (m *model_ca) AddAuthor() {
Groups: groups, Groups: groups,
} }
utils.Users[m.inputs[0].Value()] = usr utils.CreateAuthor(usr)
utils.Users[m.inputs[1].Value()] = usr
utils.Authors.Authors[m.inputs[1].Value()] = usr
data, err := json.MarshalIndent(utils.Authors, "", " ")
if err != nil {
panic(fmt.Sprintf("Error marshalling json: %v", err))
}
// write the data to the file
f.Truncate(0)
f.Seek(0, 0)
f.Write(data)
f.Close()
// redefine the users map for the tui to use
utils.Define_users(utils.Find_authorfile())
author := m.inputs[0].Value() author := m.inputs[0].Value()
if parent_m.keys != nil {
item_str := utils.Users[author].Username + " - " + utils.Users[author].Email item_str := utils.Users[author].Username + " - " + utils.Users[author].Email
dupProtect[item_str] = author dupProtect[item_str] = author
parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str)) parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str))
} }
return false
}
return true
} }
func (m *model_ca) TempAddAuthor() { func (m *model_ca) TempAddAuthor() bool {
if len(m.inputs) > 1 && m.inputs[0].Value() != "" && m.inputs[1].Value() != "" { if len(m.inputs) > 1 && m.inputs[0].Value() != "" && m.inputs[1].Value() != "" {
item_str := m.inputs[0].Value() + " - " + m.inputs[1].Value() item_str := m.inputs[0].Value() + " - " + m.inputs[1].Value()
dupProtect[item_str] = m.inputs[0].Value() + ":" + m.inputs[1].Value() dupProtect[item_str] = m.inputs[0].Value() + ":" + m.inputs[1].Value()
i := item(item_str) i := item(item_str)
parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str)) parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str))
selectToggle(i) selectToggle(i)
return false
} }
return true
} }