Skip to content

Commit

Permalink
Enable pagination and filter (#92)
Browse files Browse the repository at this point in the history
- Enable pagination and filter on the cluster, project, and import selections.
- Use fmt.Sprintf() to fix panic.
  • Loading branch information
xuanyu66 authored Feb 17, 2023
1 parent 39f6dcf commit 1059ddc
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 18 deletions.
18 changes: 15 additions & 3 deletions internal/service/cloud/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ func GetSelectedProject(pageSize int64, client TiDBCloudClient) (*Project, error
if err != nil {
return nil, err
}
itemsPerPage := 6
model.EnablePagination(itemsPerPage)
model.EnableFilter()

p := tea.NewProgram(model)
projectModel, err := p.StartReturningModel()
if err != nil {
Expand All @@ -93,7 +97,7 @@ func GetSelectedProject(pageSize int64, client TiDBCloudClient) (*Project, error
if m, _ := projectModel.(ui.SelectModel); m.Interrupted {
os.Exit(130)
}
res := projectModel.(ui.SelectModel).Choices[projectModel.(ui.SelectModel).Selected].(*Project)
res := projectModel.(ui.SelectModel).GetSelectedItem().(*Project)
return res, nil
}

Expand All @@ -118,6 +122,10 @@ func GetSelectedCluster(projectID string, pageSize int64, client TiDBCloudClient
if err != nil {
return nil, errors.Trace(err)
}
itemsPerPage := 6
model.EnablePagination(itemsPerPage)
model.EnableFilter()

p := tea.NewProgram(model)
clusterModel, err := p.StartReturningModel()
if err != nil {
Expand All @@ -126,7 +134,7 @@ func GetSelectedCluster(projectID string, pageSize int64, client TiDBCloudClient
if m, _ := clusterModel.(ui.SelectModel); m.Interrupted {
os.Exit(130)
}
cluster := clusterModel.(ui.SelectModel).Choices[clusterModel.(ui.SelectModel).Selected].(*Cluster)
cluster := clusterModel.(ui.SelectModel).GetSelectedItem().(*Cluster)
return cluster, nil
}

Expand All @@ -153,6 +161,10 @@ func GetSelectedImport(pID string, cID string, pageSize int64, client TiDBCloudC
if err != nil {
return nil, err
}
itemsPerPage := 6
model.EnablePagination(itemsPerPage)
model.EnableFilter()

p := tea.NewProgram(model)
importModel, err := p.StartReturningModel()
if err != nil {
Expand All @@ -161,7 +173,7 @@ func GetSelectedImport(pID string, cID string, pageSize int64, client TiDBCloudC
if m, _ := importModel.(ui.SelectModel); m.Interrupted {
os.Exit(130)
}
res := importModel.(ui.SelectModel).Choices[importModel.(ui.SelectModel).Selected].(*Import)
res := importModel.(ui.SelectModel).GetSelectedItem().(*Import)
return res, nil
}

Expand Down
90 changes: 75 additions & 15 deletions internal/ui/select_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package ui
import (
"fmt"

"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/paginator"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
Expand All @@ -33,9 +35,9 @@ var (

type SelectModel struct {
Hint string
Choices []interface{} // items on the to-do list
cursor int // which to-do list item our cursor is pointing at
Selected int // which to-do items are Selected
Choices []interface{} // items to be selected, which need implement fmt.Stringer interface
cursor int // which item our cursor is pointing at
Selected int // which items are Selected
Interrupted bool
showPagination bool
showFilter bool
Expand All @@ -44,6 +46,8 @@ type SelectModel struct {
// VisibleChoices is part of Choices and is filtered by user input.
VisibleChoices []interface{}

helper help.Model
keys keyMap
Paginator paginator.Model
FilterInput textinput.Model

Expand All @@ -52,6 +56,57 @@ type SelectModel struct {
ChoiceValue func(choice interface{}) string
}

type keyMap struct {
Up key.Binding
Down key.Binding
Left key.Binding
Right key.Binding
Select key.Binding
Quit key.Binding
}

// ShortHelp returns keybindings to be shown in the mini help view. It's part
// of the key.Map interface.
func (k keyMap) ShortHelp() []key.Binding {
return []key.Binding{k.Left, k.Right}
}

// FullHelp returns keybindings for the expanded help view. It's part of the
// key.Map interface.
func (k keyMap) FullHelp() [][]key.Binding {
return [][]key.Binding{
{k.Up, k.Down, k.Left, k.Right}, // first column
{k.Select, k.Quit}, // second column
}
}

var keys = keyMap{
Up: key.NewBinding(
key.WithKeys("up", "k"),
key.WithHelp("↑/k", "move up"),
),
Down: key.NewBinding(
key.WithKeys("down", "j"),
key.WithHelp("↓/j", "move down"),
),
Left: key.NewBinding(
key.WithKeys("left", "pgup"),
key.WithHelp("←/pgup", "prev page"),
),
Right: key.NewBinding(
key.WithKeys("right", "pgdown"),
key.WithHelp("→/pgdown", "next page"),
),
Select: key.NewBinding(
key.WithKeys("enter"),
key.WithHelp("enter", "select"),
),
Quit: key.NewBinding(
key.WithKeys("esc", "ctrl+c"),
key.WithHelp("esc", "quit"),
),
}

func InitialSelectModel(choices []interface{}, hint string) (*SelectModel, error) {
if len(choices) == 0 {
return nil, errors.New("There are no available choices")
Expand All @@ -78,6 +133,8 @@ func InitialSelectModel(choices []interface{}, hint string) (*SelectModel, error
FilterInput: f,
Paginator: p,
ChoiceValue: df,
keys: keys,
helper: help.New(),
}, nil
}

Expand All @@ -99,7 +156,7 @@ func buildFilterInput() textinput.Model {

func defaultChoicesValueFunc() func(choice interface{}) string {
return func(choice interface{}) string {
return choice.(string)
return fmt.Sprintf("%s", choice)
}
}

Expand All @@ -115,42 +172,42 @@ func (m SelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case tea.KeyMsg:

// Cool, what was the actual key pressed?
switch msg.String() {
switch {

// These keys should exit the program.
case "ctrl+c", "esc":
case key.Matches(msg, m.keys.Quit):
m.Interrupted = true
return m, tea.Quit

// The "up" and "k" keys move the cursor up
case "up", "k":
case key.Matches(msg, m.keys.Up):
if m.cursor > 0 {
m.cursor--
}

// The "down" and "j" keys move the cursor down
case "down", "j":
case key.Matches(msg, m.keys.Down):
if m.cursor < m.ItemsOnPage()-1 {
m.cursor++
}

// The "pgup" and "left" keys skip to the pre page
case "pgup", "left":
// The "h" and "left" keys skip to the pre page
case key.Matches(msg, m.keys.Left):
if m.showPagination {
m.Paginator.PrevPage()
m.ResetCursor()
}

// The "pgdown" and "right" keys skip to the next page
case "pgdown", "right":
// The "j" and "right" keys skip to the next page
case key.Matches(msg, m.keys.Right):
if m.showPagination {
m.Paginator.NextPage()
m.ResetCursor()
}

// The "enter" key and the spacebar (a literal space) toggle
// the selected state for the item that the cursor is pointing at.
case "enter":
case key.Matches(msg, m.keys.Select):
m.Selected = m.Index()
return m, tea.Quit
}
Expand Down Expand Up @@ -190,7 +247,6 @@ func (m SelectModel) View() string {
var start, end int
if m.showPagination {
start, end = m.Paginator.GetSliceBounds(len(m.VisibleChoices))

} else {
start = 0
end = len(m.VisibleChoices)
Expand All @@ -211,7 +267,11 @@ func (m SelectModel) View() string {

// Show paginator dot
if m.showPagination {
s += m.Paginator.View()
// Only show when there are more than one page
if m.Paginator.TotalPages > 1 {
s += m.Paginator.View() + "\n"
s += m.helper.View(m.keys)
}
}

// Send the UI for rendering
Expand Down

0 comments on commit 1059ddc

Please sign in to comment.