Add multiselect board filters and letter-jump on picker menus.
Persist comma-separated list filters per project, toggle with space, and jump by first letter in board and project pickers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+27
-11
@@ -52,7 +52,7 @@ type Model struct {
|
||||
projectList list.Model
|
||||
statusMenu views.StatusMenu
|
||||
boardMenu views.BoardMenu
|
||||
boardList ticket.BoardList
|
||||
boardFilter ticket.BoardFilter
|
||||
input textinput.Model
|
||||
width int
|
||||
height int
|
||||
@@ -80,7 +80,7 @@ func New(cfg *config.Config, store ticket.Store, projects project.Store, exec co
|
||||
projects: projects,
|
||||
exec: exec,
|
||||
mode: ModeList,
|
||||
boardList: ticket.ParseBoardList(cfg.ActiveBoardList(cfg.ActiveProject)),
|
||||
boardFilter: ticket.ParseBoardLists(cfg.ActiveBoardLists(cfg.ActiveProject)),
|
||||
tickets: views.TicketList{
|
||||
Styles: views.TicketListStyles{
|
||||
Card: styles.Card,
|
||||
@@ -208,7 +208,7 @@ func (m Model) updateList(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
|
||||
case key.Matches(msg, m.keys.Board):
|
||||
m.clearStatus()
|
||||
m.boardMenu = views.NewBoardMenu(m.boardList, m.width, views.StatusMenuStyles{
|
||||
m.boardMenu = views.NewBoardMenu(m.boardFilter, m.width, views.StatusMenuStyles{
|
||||
Box: m.styles.StatusMenuBox,
|
||||
Title: m.styles.StatusMenuTitle,
|
||||
Selected: m.styles.StatusMenuSelected,
|
||||
@@ -329,13 +329,17 @@ func (m Model) updateBoard(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.Enter):
|
||||
if err := m.applyBoardList(m.boardMenu.Selected()); err != nil {
|
||||
if err := m.applyBoardFilter(m.boardMenu.Selected()); err != nil {
|
||||
m.setError(err)
|
||||
return m, nil
|
||||
}
|
||||
m.mode = ModeList
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.Toggle):
|
||||
m.boardMenu.Toggle()
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.Down):
|
||||
m.boardMenu.MoveDown()
|
||||
return m, nil
|
||||
@@ -344,6 +348,12 @@ func (m Model) updateBoard(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
m.boardMenu.MoveUp()
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if msg.Type == tea.KeyRunes && len(msg.Runes) == 1 {
|
||||
if m.boardMenu.JumpToShortcut(msg.Runes[0]) {
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
@@ -475,6 +485,12 @@ func (m Model) updateProjects(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if msg.Type == tea.KeyRunes && len(msg.Runes) == 1 {
|
||||
if views.JumpProjectByLetter(&m.projectList, msg.Runes[0]) {
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
m.projectList, cmd = m.projectList.Update(msg)
|
||||
return m, cmd
|
||||
@@ -575,7 +591,7 @@ func (m *Model) createTicket(title, description string) error {
|
||||
Title: title,
|
||||
Description: description,
|
||||
ProjectID: m.cfg.ActiveProject,
|
||||
Status: m.boardList.DefaultStatus(),
|
||||
Status: m.boardFilter.DefaultStatus(),
|
||||
},
|
||||
}
|
||||
if err := m.exec.Do(cmd); err != nil {
|
||||
@@ -661,14 +677,14 @@ func (m *Model) redo() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Model) applyBoardList(bl ticket.BoardList) error {
|
||||
m.boardList = bl
|
||||
m.cfg.SetActiveBoardList(m.cfg.ActiveProject, string(bl))
|
||||
func (m *Model) applyBoardFilter(f ticket.BoardFilter) error {
|
||||
m.boardFilter = ticket.NormalizeFilter(f)
|
||||
m.cfg.SetActiveBoardLists(m.cfg.ActiveProject, ticket.FormatBoardLists(m.boardFilter))
|
||||
if err := config.Save(m.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
m.applyFilter()
|
||||
m.setStatus(fmt.Sprintf("list → %s", bl.Label()))
|
||||
m.setStatus(fmt.Sprintf("list → %s", m.boardFilter.Label()))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -677,7 +693,7 @@ func (m *Model) switchProject(id string) error {
|
||||
return err
|
||||
}
|
||||
m.cfg.ActiveProject = id
|
||||
m.boardList = ticket.ParseBoardList(m.cfg.ActiveBoardList(id))
|
||||
m.boardFilter = ticket.ParseBoardLists(m.cfg.ActiveBoardLists(id))
|
||||
if err := config.Save(m.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -721,7 +737,7 @@ func (m *Model) reloadTickets() error {
|
||||
func (m *Model) applyFilter() {
|
||||
filtered := make([]ticket.Ticket, 0, len(m.allTickets))
|
||||
for _, t := range m.allTickets {
|
||||
if m.boardList.Matches(t.Status) {
|
||||
if m.boardFilter.Matches(t.Status) {
|
||||
filtered = append(filtered, t)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user