Skip to content

Commit

Permalink
feat: refresh topics list after topic creation
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas-grgt committed Jan 24, 2025
1 parent 5e08db4 commit d75e7e4
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 105 deletions.
34 changes: 20 additions & 14 deletions ktea.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"flag"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
Expand All @@ -19,7 +20,6 @@ import (
"ktea/ui/tabs/sr_tab"
"ktea/ui/tabs/topics_tab"
"os"
"reflect"
"time"
)

Expand Down Expand Up @@ -75,8 +75,6 @@ func (m *Model) View() string {
}

func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
log.Debug("Update ktea", "msg", reflect.TypeOf(msg))

var cmds []tea.Cmd

switch msg := msg.(type) {
Expand Down Expand Up @@ -293,24 +291,32 @@ func NewModel(kai kadmin.Instantiator, configIO config.IO) *Model {
}

func main() {
var debug bool
flag.BoolVar(&debug, "debug", false, "enable debug")
flag.Parse()

p := tea.NewProgram(
NewModel(
kadmin.SaramaInstantiator(),
config.NewDefaultIO(),
),
tea.WithAltScreen(),
)
var fileErr error
newConfigFile, fileErr := os.OpenFile("debug.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if fileErr == nil {
log.SetOutput(newConfigFile)
log.SetTimeFormat(time.Kitchen)
log.SetReportCaller(true)
log.SetLevel(log.DebugLevel)
log.Debug("Logging to debug.log")
log.Info("started")
if _, err := p.Run(); err != nil {
log.Fatal("Failed starting the TUI", err)

if debug {
var fileErr error
debugFile, fileErr := os.OpenFile("debug.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if fileErr == nil {
log.SetOutput(debugFile)
log.SetTimeFormat(time.Kitchen)
log.SetReportCaller(true)
log.SetLevel(log.DebugLevel)
log.Debug("Logging to debug.log")
log.Info("started")
}
}

if _, err := p.Run(); err != nil {
log.Fatal("Failed starting the TUI", err)
}
}
29 changes: 2 additions & 27 deletions tests/keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keys
import (
"fmt"
tea "github.com/charmbracelet/bubbletea"
"ktea/tests"
"ktea/ui"
"ktea/ui/pages/nav"
)
Expand Down Expand Up @@ -57,7 +58,7 @@ func Submit(page nav.Page) []tea.Msg {
cmd = page.Update(cmd())
// next group and submit
cmd = page.Update(cmd())
return executeBatchCmd(cmd)
return tests.ExecuteBatchCmd(cmd)
}

func NextGroup(page nav.Page, cmd tea.Cmd) {
Expand All @@ -66,29 +67,3 @@ func NextGroup(page nav.Page, cmd tea.Cmd) {
// next group
cmd = page.Update(cmd())
}

func executeBatchCmd(cmd tea.Cmd) []tea.Msg {
var msgs []tea.Msg
if cmd == nil {
return msgs
}

msg := cmd()
if msg == nil {
return msgs
}

// If the message is a batch, process its commands
if batch, ok := msg.(tea.BatchMsg); ok {
for _, subCmd := range batch {
if subCmd != nil {
msgs = append(msgs, executeBatchCmd(subCmd)...)
}
}
return msgs
}

// Otherwise, it's a normal message
msgs = append(msgs, msg)
return msgs
}
16 changes: 9 additions & 7 deletions ui/pages/create_topic_page/create_topic_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ const (
)

type Model struct {
shortcuts []statusbar.Shortcut
form *huh.Form
notifier *notifier.Model
topicCreator kadmin.TopicCreator
formValues topicFormValues
formState formState
shortcuts []statusbar.Shortcut
form *huh.Form
notifier *notifier.Model
topicCreator kadmin.TopicCreator
formValues topicFormValues
formState formState
createdAtLeastOneTopic bool
}

type config struct {
Expand Down Expand Up @@ -74,7 +75,7 @@ func (m *Model) Update(msg tea.Msg) tea.Cmd {
return cmd
case tea.KeyMsg:
if msg.String() == "esc" && m.formState != loading {
return ui.PublishMsg(nav.LoadTopicsPageMsg{})
return ui.PublishMsg(nav.LoadTopicsPageMsg{Refresh: m.createdAtLeastOneTopic})
} else if msg.String() == "ctrl+r" {
m.formValues.name = ""
m.formValues.cleanupPolicy = ""
Expand All @@ -97,6 +98,7 @@ func (m *Model) Update(msg tea.Msg) tea.Cmd {
m.formValues.config = ""
m.formValues.numPartitions = ""
m.formValues.configs = []config{}
m.createdAtLeastOneTopic = true
m.initForm(initial)
return nil
default:
Expand Down
87 changes: 32 additions & 55 deletions ui/pages/create_topic_page/create_topic_page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,38 @@ func (m *MockTopicCreator) CreateTopic(tcd kadmin.TopicCreationDetails) tea.Msg
return nil
}

var ktx = &kontext.ProgramKtx{
WindowWidth: 100,
WindowHeight: 100,
AvailableHeight: 100,
}

func TestCreateTopic(t *testing.T) {

type CapturedTopicCreationDetails struct {
kadmin.TopicCreationDetails
}
t.Run("esc goes back to topic list page", func(t *testing.T) {
m := New(&MockTopicCreator{})

cmd := m.Update(keys.Key(tea.KeyEsc))
t.Run("esc", func(t *testing.T) {
mockCreator := MockTopicCreator{
CreateTopicFunc: func(details kadmin.TopicCreationDetails) tea.Msg {
if details.Name == "" {
return errors.New("topic name cannot be empty")
}
return CapturedTopicCreationDetails{details}
},
}
m := New(&mockCreator)

t.Run("goes back to topic list page", func(t *testing.T) {
cmd := m.Update(keys.Key(tea.KeyEsc))

assert.Equal(t, nav.LoadTopicsPageMsg{Refresh: false}, cmd())
})

t.Run("after at least one created topic refreshes topics list", func(t *testing.T) {
m = New(&mockCreator)

m.Update(kadmin.TopicCreatedMsg{})

cmd := m.Update(keys.Key(tea.KeyEsc))

assert.IsType(t, nav.LoadTopicsPageMsg{}, cmd())
assert.Equal(t, nav.LoadTopicsPageMsg{Refresh: true}, cmd())
})
})

t.Run("c-r resets form", func(t *testing.T) {
Expand All @@ -88,12 +103,12 @@ func TestCreateTopic(t *testing.T) {
// next group
cmd = m.Update(cmd())

render := m.View(ktx, ui.TestRenderer)
render := m.View(ui.NewTestKontext(), ui.TestRenderer)

assert.Contains(t, render, "Custom Topic configurations:")

m.Update(tea.KeyMsg{Type: tea.KeyCtrlR})
render = m.View(ktx, ui.TestRenderer)
render = m.View(ui.NewTestKontext(), ui.TestRenderer)

assert.NotContains(t, render, "Custom Topic configurations:")
})
Expand Down Expand Up @@ -122,13 +137,8 @@ func TestCreateTopic(t *testing.T) {
m.Update(keys.Key(tea.KeyDown))
cmd = m.Update(keys.Key(tea.KeyEnter))
m.Update(cmd())
// config
cmd = m.Update(keys.Key(tea.KeyEnter))
// next field
cmd = m.Update(cmd())
// next group
cmd = m.Update(cmd())
msgs := executeBatchCmd(cmd)
// config - submit
msgs := keys.Submit(m)

var capturedDetails CapturedTopicCreationDetails
for _, msg := range msgs {
Expand Down Expand Up @@ -223,7 +233,7 @@ func TestCreateTopic_Validation(t *testing.T) {
t.Run("When field is not a number", func(t *testing.T) {
m := CreateTopicSectionWithCursorAtPartitionsField()

cmd := m.Update(key('a'))
cmd := m.Update(keys.Key('a'))
batchUpdate(m, cmd)
cmd = m.Update(tea.KeyMsg{Type: tea.KeyEnter})
batchUpdate(m, cmd)
Expand Down Expand Up @@ -254,7 +264,7 @@ func TestCreateTopic_Validation(t *testing.T) {
keys.UpdateKeys(m, "foo:bar")
cmd = m.Update(tea.KeyMsg{Type: tea.KeyEnter})

render := m.View(ktx, ui.TestRenderer)
render := m.View(ui.NewTestKontext(), ui.TestRenderer)

assert.Contains(t, render, "please enter configurations in the format \"config=value\"")
})
Expand All @@ -278,42 +288,9 @@ func TestCreateTopic_Validation(t *testing.T) {
cmd = m.Update(tea.KeyMsg{Type: tea.KeyEnter})
batchUpdate(m, cmd)

render := m.View(ktx, ui.TestRenderer)
render := m.View(ui.NewTestKontext(), ui.TestRenderer)

assert.NotContains(t, render, "please enter configurations in the format \"config=value\"")
})
})
}

func key(r rune) tea.KeyMsg {
return tea.KeyMsg{
Type: tea.KeyRunes,
Runes: []rune{r},
}
}

func executeBatchCmd(cmd tea.Cmd) []tea.Msg {
var msgs []tea.Msg
if cmd == nil {
return msgs
}

msg := cmd()
if msg == nil {
return msgs
}

// If the message is a batch, process its commands
if batch, ok := msg.(tea.BatchMsg); ok {
for _, subCmd := range batch {
if subCmd != nil {
msgs = append(msgs, executeBatchCmd(subCmd)...)
}
}
return msgs
}

// Otherwise, it's a normal message
msgs = append(msgs, msg)
return msgs
}
2 changes: 1 addition & 1 deletion ui/pages/nav/navigation.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Page interface {
}

type LoadTopicsPageMsg struct {
Reload bool
Refresh bool
}

type LoadCreateTopicPageMsg struct{}
Expand Down
5 changes: 4 additions & 1 deletion ui/pages/topics_page/topics_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ type Model struct {
rows []table.Row
moveCursor func()
lister kadmin.TopicLister
Ctx context.Context
ctx context.Context
}

Expand Down Expand Up @@ -192,6 +191,10 @@ func (m *Model) Shortcuts() []statusbar.Shortcut {
}
}

func (m *Model) Refresh() tea.Cmd {
return m.lister.ListTopics
}

func New(topicDeleter kadmin.TopicDeleter, lister kadmin.TopicLister) (*Model, tea.Cmd) {
var m = Model{}
m.shortcuts = []statusbar.Shortcut{
Expand Down
3 changes: 3 additions & 0 deletions ui/tabs/topics_tab/topics_tab.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func (m *Model) Update(msg tea.Msg) tea.Cmd {
return m.topicsPage.Update(msg)

case nav.LoadTopicsPageMsg:
if msg.Refresh {
cmds = append(cmds, m.topicsPage.Refresh())
}
m.active = m.topicsPage

case nav.LoadConsumptionFormPageMsg:
Expand Down

0 comments on commit d75e7e4

Please sign in to comment.