package ui import ( "fmt" "strings" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" "git.warky.dev/wdevs/relspecgo/pkg/models" ) // showDomainList displays the domain management screen func (se *SchemaEditor) showDomainList() { flex := tview.NewFlex().SetDirection(tview.FlexRow) // Title title := tview.NewTextView(). SetText("[::b]Manage Domains"). SetDynamicColors(true). SetTextAlign(tview.AlignCenter) // Create domains table domainTable := tview.NewTable().SetBorders(true).SetSelectable(true, false).SetFixed(1, 0) // Add header row headers := []string{"Name", "Sequence", "Total Tables", "Description"} headerWidths := []int{20, 15, 20} for i, header := range headers { padding := "" if i < len(headerWidths) { padding = strings.Repeat(" ", headerWidths[i]-len(header)) } cell := tview.NewTableCell(header + padding). SetTextColor(tcell.ColorYellow). SetSelectable(false). SetAlign(tview.AlignLeft) domainTable.SetCell(0, i, cell) } // Add existing domains for row, domain := range se.db.Domains { domain := domain // capture for closure // Name - pad to 20 chars nameStr := fmt.Sprintf("%-20s", domain.Name) nameCell := tview.NewTableCell(nameStr).SetSelectable(true) domainTable.SetCell(row+1, 0, nameCell) // Sequence - pad to 15 chars seqStr := fmt.Sprintf("%-15s", fmt.Sprintf("%d", domain.Sequence)) seqCell := tview.NewTableCell(seqStr).SetSelectable(true) domainTable.SetCell(row+1, 1, seqCell) // Total Tables - pad to 20 chars tablesStr := fmt.Sprintf("%-20s", fmt.Sprintf("%d", len(domain.Tables))) tablesCell := tview.NewTableCell(tablesStr).SetSelectable(true) domainTable.SetCell(row+1, 2, tablesCell) // Description - no padding, takes remaining space descCell := tview.NewTableCell(domain.Description).SetSelectable(true) domainTable.SetCell(row+1, 3, descCell) } domainTable.SetTitle(" Domains ").SetBorder(true).SetTitleAlign(tview.AlignLeft) // Action buttons flex btnFlex := tview.NewFlex() btnNewDomain := tview.NewButton("New Domain [n]").SetSelectedFunc(func() { se.showNewDomainDialog() }) btnBack := tview.NewButton("Back [b]").SetSelectedFunc(func() { se.pages.SwitchToPage("main") se.pages.RemovePage("domains") }) // Set up button input captures for Tab/Shift+Tab navigation btnNewDomain.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyBacktab { se.app.SetFocus(domainTable) return nil } if event.Key() == tcell.KeyTab { se.app.SetFocus(btnBack) return nil } return event }) btnBack.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyBacktab { se.app.SetFocus(btnNewDomain) return nil } if event.Key() == tcell.KeyTab { se.app.SetFocus(domainTable) return nil } return event }) btnFlex.AddItem(btnNewDomain, 0, 1, true). AddItem(btnBack, 0, 1, false) domainTable.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEscape { se.pages.SwitchToPage("main") se.pages.RemovePage("domains") return nil } if event.Key() == tcell.KeyTab { se.app.SetFocus(btnNewDomain) return nil } if event.Key() == tcell.KeyEnter { row, _ := domainTable.GetSelection() if row > 0 && row <= len(se.db.Domains) { // Skip header row domainIndex := row - 1 se.showDomainEditor(domainIndex, se.db.Domains[domainIndex]) return nil } } if event.Rune() == 'n' { se.showNewDomainDialog() return nil } if event.Rune() == 'b' { se.pages.SwitchToPage("main") se.pages.RemovePage("domains") return nil } return event }) flex.AddItem(title, 1, 0, false). AddItem(domainTable, 0, 1, true). AddItem(btnFlex, 1, 0, false) se.pages.AddPage("domains", flex, true, true) } // showNewDomainDialog displays a dialog to create a new domain func (se *SchemaEditor) showNewDomainDialog() { form := tview.NewForm() domainName := "" domainDesc := "" form.AddInputField("Name", "", 40, nil, func(value string) { domainName = value }) form.AddInputField("Description", "", 50, nil, func(value string) { domainDesc = value }) form.AddButton("Save", func() { if domainName == "" { return } se.createDomain(domainName, domainDesc) se.pages.RemovePage("new-domain") se.pages.RemovePage("domains") se.showDomainList() }) form.AddButton("Back", func() { se.pages.RemovePage("new-domain") se.pages.RemovePage("domains") se.showDomainList() }) form.SetBorder(true).SetTitle(" New Domain ").SetTitleAlign(tview.AlignLeft) form.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEscape { se.showExitConfirmation("new-domain", "domains") return nil } return event }) se.pages.AddPage("new-domain", form, true, true) } // showDomainEditor displays a dialog to edit an existing domain func (se *SchemaEditor) showDomainEditor(index int, domain *models.Domain) { form := tview.NewForm() domainName := domain.Name domainDesc := domain.Description form.AddInputField("Name", domainName, 40, nil, func(value string) { domainName = value }) form.AddInputField("Description", domainDesc, 50, nil, func(value string) { domainDesc = value }) form.AddButton("Save", func() { if domainName == "" { return } se.updateDomain(index, domainName, domainDesc) se.pages.RemovePage("edit-domain") se.pages.RemovePage("domains") se.showDomainList() }) form.AddButton("Delete", func() { se.showDeleteDomainConfirm(index) }) form.AddButton("Back", func() { se.pages.RemovePage("edit-domain") se.pages.RemovePage("domains") se.showDomainList() }) form.SetBorder(true).SetTitle(" Edit Domain ").SetTitleAlign(tview.AlignLeft) form.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEscape { se.showExitConfirmation("edit-domain", "domains") return nil } return event }) se.pages.AddPage("edit-domain", form, true, true) } // showDeleteDomainConfirm shows a confirmation dialog before deleting a domain func (se *SchemaEditor) showDeleteDomainConfirm(index int) { modal := tview.NewModal(). SetText(fmt.Sprintf("Delete domain '%s'? This action cannot be undone.", se.db.Domains[index].Name)). AddButtons([]string{"Cancel", "Delete"}). SetDoneFunc(func(buttonIndex int, buttonLabel string) { if buttonLabel == "Delete" { se.deleteDomain(index) se.pages.RemovePage("delete-domain-confirm") se.pages.RemovePage("edit-domain") se.pages.RemovePage("domains") se.showDomainList() } else { se.pages.RemovePage("delete-domain-confirm") } }) modal.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEscape { se.pages.RemovePage("delete-domain-confirm") return nil } return event }) se.pages.AddAndSwitchToPage("delete-domain-confirm", modal, true) }