github.com/wtfutil/wtf@v0.43.0/modules/gitlabtodo/widget.go (about) 1 package gitlabtodo 2 3 import ( 4 "fmt" 5 6 "github.com/rivo/tview" 7 "github.com/wtfutil/wtf/utils" 8 "github.com/wtfutil/wtf/view" 9 gitlab "github.com/xanzy/go-gitlab" 10 ) 11 12 type Widget struct { 13 view.ScrollableWidget 14 15 todos []*gitlab.Todo 16 gitlabClient *gitlab.Client 17 settings *Settings 18 err error 19 } 20 21 func NewWidget(tviewApp *tview.Application, redrawChan chan bool, pages *tview.Pages, settings *Settings) *Widget { 22 widget := &Widget{ 23 ScrollableWidget: view.NewScrollableWidget(tviewApp, redrawChan, pages, settings.Common), 24 25 settings: settings, 26 } 27 28 widget.gitlabClient, _ = gitlab.NewClient(settings.apiKey, gitlab.WithBaseURL(settings.domain)) 29 30 widget.SetRenderFunction(widget.Render) 31 widget.initializeKeyboardControls() 32 33 return widget 34 } 35 36 /* -------------------- Exported Functions -------------------- */ 37 38 func (widget *Widget) Refresh() { 39 if widget.Disabled() { 40 return 41 } 42 43 todos, err := widget.getTodos() 44 widget.todos = todos 45 widget.err = err 46 widget.SetItemCount(len(todos)) 47 48 widget.Render() 49 } 50 51 // Render sets up the widget data for redrawing to the screen 52 func (widget *Widget) Render() { 53 widget.Redraw(widget.content) 54 } 55 56 /* -------------------- Unexported Functions -------------------- */ 57 58 func (widget *Widget) content() (string, string, bool) { 59 title := fmt.Sprintf("GitLab ToDos (%d)", len(widget.todos)) 60 61 if widget.err != nil { 62 return title, widget.err.Error(), true 63 } 64 65 if widget.todos == nil { 66 return title, "No ToDos to display", false 67 } 68 69 str := widget.contentFrom(widget.todos) 70 71 return title, str, false 72 } 73 74 func (widget *Widget) getTodos() ([]*gitlab.Todo, error) { 75 opts := gitlab.ListTodosOptions{} 76 77 todos, _, err := widget.gitlabClient.Todos.ListTodos(&opts) 78 if err != nil { 79 return nil, err 80 } 81 82 return todos, nil 83 } 84 85 // trim the todo body so it fits on a single line 86 func (widget *Widget) trimTodoBody(body string) string { 87 r := []rune(body) 88 89 // Cut at first occurrence of a newline 90 for i, a := range r { 91 if a == '\n' { 92 return string(r[:i]) 93 } 94 } 95 96 return body 97 } 98 99 func (widget *Widget) contentFrom(todos []*gitlab.Todo) string { 100 var str string 101 102 for idx, todo := range todos { 103 row := fmt.Sprintf(`[%s]%2d. `, widget.RowColor(idx), idx+1) 104 if widget.settings.showProject { 105 row = fmt.Sprintf(`%s%s `, row, todo.Project.Path) 106 } 107 row = fmt.Sprintf(`%s[mediumpurple](%s)[%s] %s`, 108 row, 109 todo.Author.Username, 110 widget.RowColor(idx), 111 widget.trimTodoBody(todo.Body), 112 ) 113 114 str += utils.HighlightableHelper(widget.View, row, idx, len(todo.Body)) 115 } 116 117 return str 118 } 119 120 func (widget *Widget) markAsDone() { 121 sel := widget.GetSelected() 122 if sel >= 0 && widget.todos != nil && sel < len(widget.todos) { 123 todo := widget.todos[sel] 124 _, err := widget.gitlabClient.Todos.MarkTodoAsDone(todo.ID) 125 if err == nil { 126 widget.Refresh() 127 } 128 } 129 } 130 131 func (widget *Widget) openTodo() { 132 sel := widget.GetSelected() 133 if sel >= 0 && widget.todos != nil && sel < len(widget.todos) { 134 todo := widget.todos[sel] 135 utils.OpenFile(todo.TargetURL) 136 } 137 }