seperate dns retrieval into its own model
This commit is contained in:
parent
ef2dbcede5
commit
a6bcb9be38
5 changed files with 179 additions and 72 deletions
|
|
@ -8,6 +8,7 @@ const (
|
||||||
PageLogin Page = iota
|
PageLogin Page = iota
|
||||||
PageMenu
|
PageMenu
|
||||||
PageListDomains
|
PageListDomains
|
||||||
|
PageDNSRetrieve
|
||||||
)
|
)
|
||||||
|
|
||||||
type SwitchPageMsg struct {
|
type SwitchPageMsg struct {
|
||||||
|
|
@ -18,7 +19,10 @@ type SessionReadyMsg struct {
|
||||||
Client *porkbun.Client
|
Client *porkbun.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListDomainsMsg struct {
|
type ListDomainsMsg struct{}
|
||||||
|
|
||||||
|
type DNSRetrieveMsg struct {
|
||||||
|
Domain string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrorMsg error
|
type ErrorMsg error
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/config"
|
"git.juancwu.dev/juancwu/porkbacon/internal/config"
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/ui/messages"
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/messages"
|
||||||
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/dns"
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/listdomains"
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/listdomains"
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/login"
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/login"
|
||||||
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/menu"
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/pages/menu"
|
||||||
|
|
@ -17,6 +18,7 @@ type MainModel struct {
|
||||||
login *login.Model
|
login *login.Model
|
||||||
menu *menu.Model
|
menu *menu.Model
|
||||||
listDomains *listdomains.Model
|
listDomains *listdomains.Model
|
||||||
|
dnsRetrieve dns.RetrieveModel
|
||||||
isMenuInit bool
|
isMenuInit bool
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
|
|
@ -57,17 +59,21 @@ func (m MainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
case messages.SessionReadyMsg:
|
case messages.SessionReadyMsg:
|
||||||
m.menu = menu.New(msg.Client)
|
m.menu = menu.New(msg.Client)
|
||||||
m.listDomains = listdomains.New(msg.Client)
|
m.listDomains = listdomains.New(msg.Client)
|
||||||
|
m.dnsRetrieve = dns.NewRetrieveModel(msg.Client)
|
||||||
if m.width > 0 && m.height > 0 {
|
if m.width > 0 && m.height > 0 {
|
||||||
newMenu, _ := m.menu.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
|
newMenu, _ := m.menu.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
|
||||||
m.menu = newMenu.(*menu.Model)
|
m.menu = newMenu.(*menu.Model)
|
||||||
}
|
}
|
||||||
m.currentPage = messages.PageMenu
|
m.currentPage = messages.PageMenu
|
||||||
m.isMenuInit = true
|
m.isMenuInit = true
|
||||||
return m, tea.Batch(m.menu.Init(), m.listDomains.Init())
|
return m, tea.Batch(m.menu.Init(), m.listDomains.Init(), m.dnsRetrieve.Init())
|
||||||
case messages.ListDomainsMsg:
|
case messages.ListDomainsMsg:
|
||||||
m.currentPage = messages.PageListDomains
|
m.currentPage = messages.PageListDomains
|
||||||
|
case messages.DNSRetrieveMsg:
|
||||||
|
m.currentPage = messages.PageDNSRetrieve
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var newModel tea.Model
|
||||||
switch m.currentPage {
|
switch m.currentPage {
|
||||||
case messages.PageLogin:
|
case messages.PageLogin:
|
||||||
var newLogin tea.Model
|
var newLogin tea.Model
|
||||||
|
|
@ -78,9 +84,11 @@ func (m MainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
newMenu, cmd = m.menu.Update(msg)
|
newMenu, cmd = m.menu.Update(msg)
|
||||||
m.menu = newMenu.(*menu.Model)
|
m.menu = newMenu.(*menu.Model)
|
||||||
case messages.PageListDomains:
|
case messages.PageListDomains:
|
||||||
var newModel tea.Model
|
|
||||||
newModel, cmd = m.listDomains.Update(msg)
|
newModel, cmd = m.listDomains.Update(msg)
|
||||||
m.listDomains = newModel.(*listdomains.Model)
|
m.listDomains = newModel.(*listdomains.Model)
|
||||||
|
case messages.PageDNSRetrieve:
|
||||||
|
newModel, cmd = m.dnsRetrieve.Update(msg)
|
||||||
|
m.dnsRetrieve = newModel.(dns.RetrieveModel)
|
||||||
}
|
}
|
||||||
cmds = append(cmds, cmd)
|
cmds = append(cmds, cmd)
|
||||||
|
|
||||||
|
|
@ -95,6 +103,8 @@ func (m MainModel) View() string {
|
||||||
return m.menu.View()
|
return m.menu.View()
|
||||||
case messages.PageListDomains:
|
case messages.PageListDomains:
|
||||||
return m.listDomains.View()
|
return m.listDomains.View()
|
||||||
|
case messages.PageDNSRetrieve:
|
||||||
|
return m.dnsRetrieve.View()
|
||||||
default:
|
default:
|
||||||
return "Unknown Page"
|
return "Unknown Page"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
157
internal/ui/pages/dns/retrieve.go
Normal file
157
internal/ui/pages/dns/retrieve.go
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/paginator"
|
||||||
|
"github.com/charmbracelet/bubbles/spinner"
|
||||||
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
|
||||||
|
"git.juancwu.dev/juancwu/porkbacon/internal/porkbun"
|
||||||
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/messages"
|
||||||
|
"git.juancwu.dev/juancwu/porkbacon/internal/ui/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RetrieveModel struct {
|
||||||
|
client *porkbun.Client
|
||||||
|
loading bool
|
||||||
|
records []string
|
||||||
|
|
||||||
|
spinner spinner.Model
|
||||||
|
paginator paginator.Model
|
||||||
|
textinput textinput.Model
|
||||||
|
|
||||||
|
stderr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRetrieveModel(client *porkbun.Client) RetrieveModel {
|
||||||
|
p := paginator.New()
|
||||||
|
p.Type = paginator.Dots
|
||||||
|
p.PerPage = 1
|
||||||
|
p.ActiveDot = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "235", Dark: "252"}).Render("•")
|
||||||
|
p.InactiveDot = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "250", Dark: "238"}).Render("•")
|
||||||
|
|
||||||
|
s := spinner.New()
|
||||||
|
s.Spinner = spinner.Dot
|
||||||
|
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
|
||||||
|
|
||||||
|
ti := textinput.New()
|
||||||
|
ti.Placeholder = "Enter domain"
|
||||||
|
ti.Width = 80
|
||||||
|
|
||||||
|
return RetrieveModel{
|
||||||
|
client: client,
|
||||||
|
spinner: s,
|
||||||
|
paginator: p,
|
||||||
|
textinput: ti,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m RetrieveModel) Init() tea.Cmd {
|
||||||
|
return tea.Batch(m.spinner.Tick, textinput.Blink)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m RetrieveModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
if m.loading {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.String() == "esc" {
|
||||||
|
hadRecords := len(m.records) > 0
|
||||||
|
m.loading = false
|
||||||
|
m.records = nil
|
||||||
|
return m, func() tea.Msg {
|
||||||
|
if hadRecords {
|
||||||
|
return messages.DNSRetrieveMsg{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages.SwitchPageMsg{Page: messages.PageMenu}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.String() == "enter" {
|
||||||
|
m.loading = true
|
||||||
|
m.records = nil
|
||||||
|
return m, retrieveRecords(m.client, m.textinput.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m.records) > 0 {
|
||||||
|
m.paginator, cmd = m.paginator.Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
m.textinput, cmd = m.textinput.Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
|
||||||
|
case messages.DNSRetrieveMsg:
|
||||||
|
m.textinput.Reset()
|
||||||
|
m.textinput.Focus()
|
||||||
|
|
||||||
|
case *porkbun.DNSRecordsResponse:
|
||||||
|
m.loading = false
|
||||||
|
for _, record := range msg.Records {
|
||||||
|
m.records = append(m.records, renderRecord(&record))
|
||||||
|
}
|
||||||
|
m.paginator.SetTotalPages(len(m.records))
|
||||||
|
m.paginator.Page = 0
|
||||||
|
case messages.ErrorMsg:
|
||||||
|
m.stderr = fmt.Sprintf("Error: %v", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.loading {
|
||||||
|
m.spinner, cmd = m.spinner.Update(msg)
|
||||||
|
return m, tea.Batch(cmd, m.spinner.Tick)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, textinput.Blink
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m RetrieveModel) View() string {
|
||||||
|
if m.stderr != "" {
|
||||||
|
return fmt.Sprintf("%s\n\n(Press ctrl+c to quit)", m.stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.loading {
|
||||||
|
return fmt.Sprintf("\n\n %s Loading... press ctl+c to quit\n\n", m.spinner.View())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m.records) > 0 {
|
||||||
|
return fmt.Sprintf("%s\n\n%s\n\n(Press Esc to go back, arrows to navigate)", m.records[m.paginator.Page], m.paginator.View())
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Enter domain to retrieve records for:\n\n%s\n\n(esc to quit)",
|
||||||
|
m.textinput.View(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func retrieveRecords(client *porkbun.Client, domain string) tea.Cmd {
|
||||||
|
return func() tea.Msg {
|
||||||
|
resp, err := client.RetrieveDNSRecords(domain)
|
||||||
|
if err != nil {
|
||||||
|
return messages.ErrorMsg(err)
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderRecord(item *porkbun.DNSRecord) string {
|
||||||
|
var b strings.Builder
|
||||||
|
b.WriteString("ID: " + item.ID + "\n")
|
||||||
|
b.WriteString("Name: " + item.Name + "\n")
|
||||||
|
b.WriteString("Type: " + item.Type + "\n")
|
||||||
|
b.WriteString(fmt.Sprintln("TTL:", item.TTL))
|
||||||
|
b.WriteString(fmt.Sprintln("Priority:", item.Priority))
|
||||||
|
b.WriteString("Content: ")
|
||||||
|
b.WriteString(utils.WrapText(item.Content, 80))
|
||||||
|
b.WriteString("\n")
|
||||||
|
b.WriteString("Notes: " + item.Notes + "\n")
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
@ -51,10 +51,9 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
if !m.loading && msg.String() == "esc" {
|
if !m.loading && msg.String() == "esc" {
|
||||||
return m, func() tea.Msg {
|
|
||||||
m.loading = false
|
m.loading = false
|
||||||
m.domains = nil
|
m.domains = nil
|
||||||
m.client = nil
|
return m, func() tea.Msg {
|
||||||
return messages.SwitchPageMsg{Page: messages.PageMenu}
|
return messages.SwitchPageMsg{Page: messages.PageMenu}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,6 @@ type pingResultMsg struct {
|
||||||
IP string
|
IP string
|
||||||
}
|
}
|
||||||
|
|
||||||
type dnsRecordListMsg struct {
|
|
||||||
Status string
|
|
||||||
Records []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type menuItem struct {
|
type menuItem struct {
|
||||||
id uint8
|
id uint8
|
||||||
title, desc string
|
title, desc string
|
||||||
|
|
@ -53,7 +48,6 @@ type Model struct {
|
||||||
textInput textinput.Model
|
textInput textinput.Model
|
||||||
loading bool
|
loading bool
|
||||||
state uint8
|
state uint8
|
||||||
records []string
|
|
||||||
client *porkbun.Client
|
client *porkbun.Client
|
||||||
err error
|
err error
|
||||||
output string
|
output string
|
||||||
|
|
@ -109,42 +103,6 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
if m.loading && msg.String() == "ctrl+c" {
|
|
||||||
return m, tea.Quit
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.state == stateDNSRetrieveGetDomain {
|
|
||||||
switch msg.String() {
|
|
||||||
case "enter":
|
|
||||||
domain := m.textInput.Value()
|
|
||||||
m.textInput.SetValue("")
|
|
||||||
m.state = stateNoOp
|
|
||||||
m.loading = true
|
|
||||||
cmd := func() tea.Msg {
|
|
||||||
resp, err := m.client.RetrieveDNSRecords(domain)
|
|
||||||
if err != nil {
|
|
||||||
return messages.ErrorMsg(err)
|
|
||||||
}
|
|
||||||
var records []string
|
|
||||||
for _, record := range resp.Records {
|
|
||||||
records = append(records, renderRecordItem(&record))
|
|
||||||
}
|
|
||||||
return dnsRecordListMsg{
|
|
||||||
Status: resp.Status,
|
|
||||||
Records: records,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m, tea.Batch(cmd, m.spinner.Tick)
|
|
||||||
case "esc":
|
|
||||||
m.state = stateNoOp
|
|
||||||
m.textInput.SetValue("")
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
var cmd tea.Cmd
|
|
||||||
m.textInput, cmd = m.textInput.Update(msg)
|
|
||||||
return m, cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.output != "" {
|
if m.output != "" {
|
||||||
if msg.String() == "esc" {
|
if msg.String() == "esc" {
|
||||||
m.output = ""
|
m.output = ""
|
||||||
|
|
@ -153,16 +111,6 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.records) > 0 {
|
|
||||||
var cmd tea.Cmd
|
|
||||||
m.paginator, cmd = m.paginator.Update(msg)
|
|
||||||
if msg.String() == "esc" {
|
|
||||||
m.records = nil
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
return m, cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg.String() == "enter" {
|
if msg.String() == "enter" {
|
||||||
i, ok := m.list.SelectedItem().(menuItem)
|
i, ok := m.list.SelectedItem().(menuItem)
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -170,13 +118,6 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case dnsRecordListMsg:
|
|
||||||
m.loading = false
|
|
||||||
m.paginator.PerPage = 1
|
|
||||||
m.paginator.SetTotalPages(len(msg.Records))
|
|
||||||
m.paginator.Page = 0
|
|
||||||
return m, nil
|
|
||||||
|
|
||||||
case pingResultMsg:
|
case pingResultMsg:
|
||||||
m.loading = false
|
m.loading = false
|
||||||
m.output = fmt.Sprintf("Ping successful!\nYour IP: %s", msg.IP)
|
m.output = fmt.Sprintf("Ping successful!\nYour IP: %s", msg.IP)
|
||||||
|
|
@ -213,19 +154,15 @@ func (m *Model) View() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.records) > 0 {
|
|
||||||
return fmt.Sprintf("%s\n\n%s\n\n(Press Esc to go back, arrows to navigate)", m.records[m.paginator.Page], m.paginator.View())
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.list.View()
|
return m.list.View()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) handleSelection(i menuItem) (tea.Model, tea.Cmd) {
|
func (m *Model) handleSelection(i menuItem) (tea.Model, tea.Cmd) {
|
||||||
switch i.id {
|
switch i.id {
|
||||||
case dnsRetrieveRecords:
|
case dnsRetrieveRecords:
|
||||||
m.state = stateDNSRetrieveGetDomain
|
return m, func() tea.Msg {
|
||||||
m.textInput.Focus()
|
return messages.DNSRetrieveMsg{}
|
||||||
return m, textinput.Blink
|
}
|
||||||
case domainListAll:
|
case domainListAll:
|
||||||
return m, func() tea.Msg {
|
return m, func() tea.Msg {
|
||||||
return messages.ListDomainsMsg{}
|
return messages.ListDomainsMsg{}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue