diff --git a/app/widget_maker.go b/app/widget_maker.go index 9b9d9766..6f7275a8 100644 --- a/app/widget_maker.go +++ b/app/widget_maker.go @@ -59,10 +59,9 @@ import ( "github.com/wtfutil/wtf/modules/subreddit" "github.com/wtfutil/wtf/modules/textfile" "github.com/wtfutil/wtf/modules/todo" - "github.com/wtfutil/wtf/modules/todoist" + "github.com/wtfutil/wtf/modules/todo_plus" "github.com/wtfutil/wtf/modules/transmission" "github.com/wtfutil/wtf/modules/travisci" - "github.com/wtfutil/wtf/modules/trello" "github.com/wtfutil/wtf/modules/twitch" "github.com/wtfutil/wtf/modules/twitter" "github.com/wtfutil/wtf/modules/twitterstats" @@ -269,9 +268,12 @@ func MakeWidget( case "todo": settings := todo.NewSettingsFromYAML(moduleName, moduleConfig, config) widget = todo.NewWidget(app, pages, settings) + case "todo_plus": + settings := todo_plus.NewSettingsFromYAML(moduleName, moduleConfig, config) + widget = todo_plus.NewWidget(app, pages, settings) case "todoist": - settings := todoist.NewSettingsFromYAML(moduleName, moduleConfig, config) - widget = todoist.NewWidget(app, pages, settings) + settings := todo_plus.FromTodoist(moduleName, moduleConfig, config) + widget = todo_plus.NewWidget(app, pages, settings) case "transmission": settings := transmission.NewSettingsFromYAML(moduleName, moduleConfig, config) widget = transmission.NewWidget(app, pages, settings) @@ -279,8 +281,8 @@ func MakeWidget( settings := travisci.NewSettingsFromYAML(moduleName, moduleConfig, config) widget = travisci.NewWidget(app, pages, settings) case "trello": - settings := trello.NewSettingsFromYAML(moduleName, moduleConfig, config) - widget = trello.NewWidget(app, settings) + settings := todo_plus.FromTrello(moduleName, moduleConfig, config) + widget = todo_plus.NewWidget(app, pages, settings) case "twitch": settings := twitch.NewSettingsFromYAML(moduleName, moduleConfig, config) widget = twitch.NewWidget(app, pages, settings) diff --git a/modules/todo_plus/backend/backend.go b/modules/todo_plus/backend/backend.go new file mode 100644 index 00000000..7f116a54 --- /dev/null +++ b/modules/todo_plus/backend/backend.go @@ -0,0 +1,16 @@ +package backend + +import ( + "github.com/olebedev/config" +) + +type Backend interface { + Title() string + Setup(*config.Config) + BuildProjects() []*Project + GetProject(string) *Project + LoadTasks(string) ([]Task, error) + CloseTask(*Task) error + DeleteTask(*Task) error + Sources() []string +} diff --git a/modules/todo_plus/backend/project.go b/modules/todo_plus/backend/project.go new file mode 100644 index 00000000..8280900c --- /dev/null +++ b/modules/todo_plus/backend/project.go @@ -0,0 +1,66 @@ +package backend + +type Task struct { + ID string + Completed bool + Name string +} + +type Project struct { + ID string + Name string + + Index int + Tasks []Task + Err error + backend Backend +} + +func (proj *Project) IsLast() bool { + return proj.Index >= len(proj.Tasks)-1 +} + +func (proj *Project) loadTasks() { + Tasks, err := proj.backend.LoadTasks(proj.ID) + proj.Err = err + proj.Tasks = Tasks +} + +func (proj *Project) LongestLine() int { + maxLen := 0 + + for _, task := range proj.Tasks { + if len(task.Name) > maxLen { + maxLen = len(task.Name) + } + } + + return maxLen +} + +func (proj *Project) currentTask() *Task { + if proj.Index < 0 { + return nil + } + + return &proj.Tasks[proj.Index] +} + +func (proj *Project) CloseSelectedTask() { + currTask := proj.currentTask() + + if currTask != nil { + _ = proj.backend.CloseTask(currTask) + proj.loadTasks() + } +} + +func (proj *Project) DeleteSelectedTask() { + currTask := proj.currentTask() + + if currTask != nil { + _ = proj.backend.DeleteTask(currTask) + + proj.loadTasks() + } +} diff --git a/modules/todo_plus/backend/todoist.go b/modules/todo_plus/backend/todoist.go new file mode 100644 index 00000000..a49b1f4f --- /dev/null +++ b/modules/todo_plus/backend/todoist.go @@ -0,0 +1,108 @@ +package backend + +import ( + "strconv" + + "github.com/olebedev/config" + "github.com/wtfutil/todoist" +) + +type Todoist struct { + projects []interface{} +} + +func (todo *Todoist) Title() string { + return "Todoist" +} + +func (todo *Todoist) Setup(config *config.Config) { + todoist.Token = config.UString("apiKey") + todo.projects = config.UList("projects") +} + +func (todo *Todoist) BuildProjects() []*Project { + projects := []*Project{} + + for _, id := range todo.projects { + i := strconv.Itoa(id.(int)) + proj := todo.GetProject(i) + projects = append(projects, proj) + } + return projects +} + +func (todo *Todoist) GetProject(id string) *Project { + // Todoist seems to experience a lot of network issues on their side + // If we can't connect, handle it with an empty project until we can + proj := &Project{ + Index: -1, + backend: todo, + } + i64, _ := strconv.ParseUint(id, 10, 32) + i := uint(i64) + project, err := todoist.GetProject(i) + if err != nil { + proj.Err = err + return proj + } + + proj.ID = strconv.FormatUint(uint64(project.ID), 10) + proj.Name = project.Name + + tasks, err := todo.LoadTasks(proj.ID) + proj.Err = err + proj.Tasks = tasks + + return proj +} + +func toTask(task todoist.Task) Task { + id := strconv.FormatUint(uint64(task.ID), 10) + return Task{ + ID: id, + Completed: task.Completed, + Name: task.Content, + } +} + +func (todo *Todoist) LoadTasks(id string) ([]Task, error) { + tasks, err := todoist.ListTask(todoist.QueryParam{"project_id": id}) + + if err != nil { + return nil, err + } + var finalTasks []Task + for _, item := range tasks { + finalTasks = append(finalTasks, toTask(item)) + } + return finalTasks, nil +} + +func (todo *Todoist) CloseTask(task *Task) error { + if task != nil { + i64, _ := strconv.ParseUint(task.ID, 10, 32) + i := uint(i64) + internal := todoist.Task{ID: i} + return internal.Close() + } + return nil +} + +func (todo *Todoist) DeleteTask(task *Task) error { + if task != nil { + i64, _ := strconv.ParseUint(task.ID, 10, 32) + i := uint(i64) + internal := todoist.Task{ID: i} + return internal.Delete() + } + return nil +} + +func (todo *Todoist) Sources() []string { + var result []string + for _, id := range todo.projects { + i := strconv.Itoa(id.(int)) + result = append(result, i) + } + return result +} diff --git a/modules/todo_plus/backend/trello.go b/modules/todo_plus/backend/trello.go new file mode 100644 index 00000000..2ace375a --- /dev/null +++ b/modules/todo_plus/backend/trello.go @@ -0,0 +1,170 @@ +package backend + +import ( + "fmt" + "log" + + "github.com/adlio/trello" + "github.com/olebedev/config" +) + +type Trello struct { + username string + boardName string + client *trello.Client + board string + projects []interface{} +} + +func (todo *Trello) Title() string { + return "Trello" +} + +func (todo *Trello) Setup(config *config.Config) { + todo.username = config.UString("username") + todo.boardName = config.UString("board") + todo.client = trello.NewClient( + config.UString("apiKey"), + config.UString("accessToken"), + ) + board, err := getBoardID(todo.client, todo.username, todo.boardName) + if err != nil { + log.Fatal(err) + } + todo.board = board + todo.projects = config.UList("lists") +} + +func getBoardID(client *trello.Client, username, boardName string) (string, error) { + member, err := client.GetMember(username, trello.Defaults()) + if err != nil { + return "", err + } + + boards, err := member.GetBoards(trello.Defaults()) + if err != nil { + return "", err + } + + for _, board := range boards { + if board.Name == boardName { + return board.ID, nil + } + } + + return "", fmt.Errorf("could not find board with name %s", boardName) +} + +func getListId(client *trello.Client, boardID string, listName string) (string, error) { + board, err := client.GetBoard(boardID, trello.Defaults()) + if err != nil { + return "", err + } + + boardLists, err := board.GetLists(trello.Defaults()) + if err != nil { + return "", err + } + + for _, list := range boardLists { + if list.Name == listName { + return list.ID, nil + } + } + + return "", nil +} + +func getCardsOnList(client *trello.Client, listID string) ([]*trello.Card, error) { + list, err := client.GetList(listID, trello.Defaults()) + if err != nil { + return nil, err + } + + cards, err := list.GetCards(trello.Defaults()) + if err != nil { + return nil, err + } + + return cards, nil +} + +func (todo *Trello) BuildProjects() []*Project { + projects := []*Project{} + + for _, id := range todo.projects { + proj := todo.GetProject(id.(string)) + projects = append(projects, proj) + } + return projects +} + +func (todo *Trello) GetProject(id string) *Project { + proj := &Project{ + Index: -1, + backend: todo, + } + + listId, err := getListId(todo.client, todo.board, id) + if err != nil { + proj.Err = err + return proj + } + proj.ID = listId + proj.Name = id + + tasks, err := todo.LoadTasks(listId) + proj.Err = err + proj.Tasks = tasks + + return proj +} + +func fromTrello(task *trello.Card) Task { + return Task{ + ID: task.ID, + Completed: task.Closed, + Name: task.Name, + } +} + +func (todo *Trello) LoadTasks(id string) ([]Task, error) { + tasks, err := getCardsOnList(todo.client, id) + + if err != nil { + return nil, err + } + var finalTasks []Task + for _, item := range tasks { + finalTasks = append(finalTasks, fromTrello(item)) + } + return finalTasks, nil +} + +func (todo *Trello) CloseTask(task *Task) error { + args := trello.Arguments{ + "closed": "true", + } + if task != nil { + // Card has an internal client rep which we can't access + // Just force a lookup + internal, err := todo.client.GetCard(task.ID, trello.Arguments{}) + if err != nil { + return err + } + return internal.Update(args) + } + return nil +} + +func (todo *Trello) DeleteTask(task *Task) error { + return nil +} + +func (todo *Trello) Sources() []string { + var result []string + for _, id := range todo.projects { + result = append(result, id.(string)) + } + return result +} diff --git a/modules/todoist/display.go b/modules/todo_plus/display.go similarity index 75% rename from modules/todoist/display.go rename to modules/todo_plus/display.go index 49caa56d..9ca1f86a 100644 --- a/modules/todoist/display.go +++ b/modules/todo_plus/display.go @@ -1,4 +1,4 @@ -package todoist +package todo_plus import ( "fmt" @@ -14,27 +14,26 @@ func (widget *Widget) content() (string, string, bool) { return widget.CommonSettings().Title, "", false } - if proj.err != nil { - return widget.CommonSettings().Title, proj.err.Error(), true + if proj.Err != nil { + return widget.CommonSettings().Title, proj.Err.Error(), true } title := fmt.Sprintf( "[%s]%s[white]", widget.settings.common.Colors.TextTheme.Title, - proj.Project.Name, - ) + proj.Name) str := "" - for idx, item := range proj.tasks { + for idx, item := range proj.Tasks { row := fmt.Sprintf( `[%s]| | %s[%s]`, widget.RowColor(idx), - tview.Escape(item.Content), + tview.Escape(item.Name), widget.RowColor(idx), ) - str += utils.HighlightableHelper(widget.View, row, idx, len(item.Content)) + str += utils.HighlightableHelper(widget.View, row, idx, len(item.Name)) } return title, str, false } diff --git a/modules/todoist/keyboard.go b/modules/todo_plus/keyboard.go similarity index 98% rename from modules/todoist/keyboard.go rename to modules/todo_plus/keyboard.go index 05ccd93b..282b2a28 100644 --- a/modules/todoist/keyboard.go +++ b/modules/todo_plus/keyboard.go @@ -1,21 +1,21 @@ -package todoist +package todo_plus import "github.com/gdamore/tcell" func (widget *Widget) initializeKeyboardControls() { widget.InitializeCommonControls(widget.Refresh) - widget.SetKeyboardChar("c", widget.Close, "Close item") widget.SetKeyboardChar("d", widget.Delete, "Delete item") - widget.SetKeyboardChar("h", widget.PrevSource, "Select previous project") widget.SetKeyboardChar("j", widget.Prev, "Select previous item") widget.SetKeyboardChar("k", widget.Next, "Select next item") + widget.SetKeyboardChar("h", widget.PrevSource, "Select previous project") + widget.SetKeyboardChar("c", widget.Close, "Close item") widget.SetKeyboardChar("l", widget.NextSource, "Select next project") widget.SetKeyboardChar("u", widget.Unselect, "Clear selection") widget.SetKeyboardKey(tcell.KeyDown, widget.Next, "Select next item") + widget.SetKeyboardKey(tcell.KeyUp, widget.Prev, "Select previous item") widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect, "Clear selection") widget.SetKeyboardKey(tcell.KeyLeft, widget.PrevSource, "Select previous project") widget.SetKeyboardKey(tcell.KeyRight, widget.NextSource, "Select next project") - widget.SetKeyboardKey(tcell.KeyUp, widget.Prev, "Select previous item") } diff --git a/modules/todo_plus/settings.go b/modules/todo_plus/settings.go new file mode 100644 index 00000000..686e8a63 --- /dev/null +++ b/modules/todo_plus/settings.go @@ -0,0 +1,81 @@ +package todo_plus + +import ( + "os" + + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +const ( + defaultTitle = "Todo" + defaultFocusable = true +) + +type Settings struct { + common *cfg.Common + + backendType string + backendSettings *config.Config +} + +func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { + + backend, _ := ymlConfig.Get("backendSettings") + + settings := Settings{ + common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig), + + backendType: ymlConfig.UString("backendType"), + backendSettings: backend, + } + + return &settings +} + +func FromTodoist(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { + apiKey := ymlConfig.UString("apiKey", ymlConfig.UString("apikey", os.Getenv("WTF_TODOIST_TOKEN"))) + cfg.ModuleSecret(name, globalConfig, &apiKey).Load() + projects := ymlConfig.UList("projects") + backend, _ := config.ParseYaml("apiKey: " + apiKey) + _ = backend.Set(".projects", projects) + + settings := Settings{ + common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig), + + backendType: "todoist", + backendSettings: backend, + } + + return &settings +} + +func FromTrello(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { + + accessToken := ymlConfig.UString("accessToken", ymlConfig.UString("apikey", os.Getenv("WTF_TRELLO_ACCESS_TOKEN"))) + apiKey := ymlConfig.UString("apiKey", os.Getenv("WTF_TRELLO_API_KEY")) + cfg.ModuleSecret(name, globalConfig, &apiKey).Load() + board := ymlConfig.UString("board") + username := ymlConfig.UString("username") + var lists []interface{} + list, err := ymlConfig.String("list") + if err == nil { + lists = append(lists, list) + } else { + lists = ymlConfig.UList("list") + } + backend, _ := config.ParseYaml("apiKey: " + apiKey) + _ = backend.Set(".accessToken", accessToken) + _ = backend.Set(".board", board) + _ = backend.Set(".username", username) + _ = backend.Set(".lists", lists) + + settings := Settings{ + common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig), + + backendType: "trello", + backendSettings: backend, + } + + return &settings +} diff --git a/modules/todoist/widget.go b/modules/todo_plus/widget.go similarity index 53% rename from modules/todoist/widget.go rename to modules/todo_plus/widget.go index afa920cc..5a23b5b1 100644 --- a/modules/todoist/widget.go +++ b/modules/todo_plus/widget.go @@ -1,8 +1,10 @@ -package todoist +package todo_plus import ( + "log" + "github.com/rivo/tview" - "github.com/wtfutil/todoist" + "github.com/wtfutil/wtf/modules/todo_plus/backend" "github.com/wtfutil/wtf/view" ) @@ -12,8 +14,9 @@ type Widget struct { view.MultiSourceWidget view.ScrollableWidget - projects []*Project + projects []*backend.Project settings *Settings + backend backend.Backend } // NewWidget creates a new instance of a widget @@ -26,8 +29,9 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) * settings: settings, } - widget.loadAPICredentials() - widget.loadProjects() + widget.backend = getBackend(settings.backendType) + widget.backend.Setup(settings.backendSettings) + widget.CommonSettings().Title = widget.backend.Title() widget.SetRenderFunction(widget.display) widget.initializeKeyboardControls() @@ -39,13 +43,28 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) * return &widget } +func getBackend(backendType string) backend.Backend { + switch backendType { + case "trello": + backend := &backend.Trello{} + return backend + case "todoist": + backend := &backend.Todoist{} + return backend + default: + log.Fatal(backendType + " is not a supported backend") + return nil + } + +} + /* -------------------- Exported Functions -------------------- */ -func (widget *Widget) CurrentProject() *Project { +func (widget *Widget) CurrentProject() *backend.Project { return widget.ProjectAt(widget.Idx) } -func (widget *Widget) ProjectAt(idx int) *Project { +func (widget *Widget) ProjectAt(idx int) *backend.Project { if len(widget.projects) == 0 { return nil } @@ -54,14 +73,13 @@ func (widget *Widget) ProjectAt(idx int) *Project { } func (widget *Widget) Refresh() { - if widget.Disabled() || widget.CurrentProject() == nil { - widget.SetItemCount(0) + if widget.Disabled() { return } - widget.loadProjects() - - widget.SetItemCount(len(widget.CurrentProject().tasks)) + widget.projects = widget.backend.BuildProjects() + widget.Sources = widget.backend.Sources() + widget.SetItemCount(len(widget.CurrentProject().Tasks)) widget.display() } @@ -71,74 +89,57 @@ func (widget *Widget) HelpText() string { func (widget *Widget) NextSource() { widget.MultiSourceWidget.NextSource() - widget.Selected = widget.CurrentProject().index - widget.SetItemCount(len(widget.CurrentProject().tasks)) + widget.Selected = widget.CurrentProject().Index + widget.SetItemCount(len(widget.CurrentProject().Tasks)) widget.RenderFunction() } func (widget *Widget) PrevSource() { widget.MultiSourceWidget.PrevSource() - widget.Selected = widget.CurrentProject().index - widget.SetItemCount(len(widget.CurrentProject().tasks)) + widget.Selected = widget.CurrentProject().Index + widget.SetItemCount(len(widget.CurrentProject().Tasks)) widget.RenderFunction() } func (widget *Widget) Prev() { widget.ScrollableWidget.Prev() - widget.CurrentProject().index = widget.Selected + widget.CurrentProject().Index = widget.Selected } func (widget *Widget) Next() { widget.ScrollableWidget.Next() - widget.CurrentProject().index = widget.Selected + widget.CurrentProject().Index = widget.Selected } func (widget *Widget) Unselect() { widget.ScrollableWidget.Unselect() - widget.CurrentProject().index = -1 + widget.CurrentProject().Index = -1 widget.RenderFunction() } /* -------------------- Keyboard Movement -------------------- */ // Close closes the currently-selected task in the currently-selected project -func (widget *Widget) Close() { - widget.CurrentProject().closeSelectedTask() - widget.SetItemCount(len(widget.CurrentProject().tasks)) +func (w *Widget) Close() { + w.CurrentProject().CloseSelectedTask() + w.SetItemCount(len(w.CurrentProject().Tasks)) - if widget.CurrentProject().isLast() { - widget.Prev() + if w.CurrentProject().IsLast() { + w.Prev() return } - widget.CurrentProject().index = widget.Selected - widget.RenderFunction() + w.CurrentProject().Index = w.Selected + w.RenderFunction() } // Delete deletes the currently-selected task in the currently-selected project -func (widget *Widget) Delete() { - widget.CurrentProject().deleteSelectedTask() - widget.SetItemCount(len(widget.CurrentProject().tasks)) +func (w *Widget) Delete() { + w.CurrentProject().DeleteSelectedTask() + w.SetItemCount(len(w.CurrentProject().Tasks)) - if widget.CurrentProject().isLast() { - widget.Prev() + if w.CurrentProject().IsLast() { + w.Prev() } - widget.CurrentProject().index = widget.Selected - widget.RenderFunction() -} - -/* -------------------- Unexported Functions -------------------- */ - -func (widget *Widget) loadAPICredentials() { - todoist.Token = widget.settings.apiKey -} - -func (widget *Widget) loadProjects() { - projects := []*Project{} - - for _, id := range widget.settings.projects { - proj := NewProject(id) - projects = append(projects, proj) - } - - widget.projects = projects + w.CurrentProject().Index = w.Selected + w.RenderFunction() } diff --git a/modules/todoist/project.go b/modules/todoist/project.go deleted file mode 100644 index ae2919c4..00000000 --- a/modules/todoist/project.go +++ /dev/null @@ -1,93 +0,0 @@ -package todoist - -import ( - "fmt" - - "github.com/wtfutil/todoist" -) - -type Project struct { - todoist.Project - - index int - tasks []todoist.Task - err error -} - -func NewProject(id uint) *Project { - // Todoist seems to experience a lot of network issues on their side - // If we can't connect, handle it with an empty project until we can - project, err := todoist.GetProject(id) - proj := &Project{ - index: -1, - } - if err != nil { - proj.err = err - return proj - } - - proj.Project = project - - proj.loadTasks() - - return proj -} - -func (proj *Project) isLast() bool { - return proj.index >= len(proj.tasks)-1 -} - -func (proj *Project) loadTasks() { - tasks, err := todoist.ListTask(todoist.QueryParam{"project_id": fmt.Sprintf("%d", proj.ID)}) - if err != nil { - proj.err = err - proj.tasks = nil - } else { - proj.err = nil - proj.tasks = tasks - } -} - -func (proj *Project) LongestLine() int { - maxLen := 0 - - for _, task := range proj.tasks { - if len(task.Content) > maxLen { - maxLen = len(task.Content) - } - } - - return maxLen -} - -func (proj *Project) currentTask() *todoist.Task { - if proj.index < 0 { - return nil - } - - return &proj.tasks[proj.index] -} - -func (proj *Project) closeSelectedTask() { - currTask := proj.currentTask() - - if currTask != nil { - if err := currTask.Close(); err != nil { - return - } - - proj.loadTasks() - } -} - -func (proj *Project) deleteSelectedTask() { - currTask := proj.currentTask() - - if currTask != nil { - if err := currTask.Delete(); err != nil { - return - } - - proj.loadTasks() - } -} diff --git a/modules/todoist/settings.go b/modules/todoist/settings.go deleted file mode 100644 index 3dc100dc..00000000 --- a/modules/todoist/settings.go +++ /dev/null @@ -1,36 +0,0 @@ -package todoist - -import ( - "os" - - "github.com/olebedev/config" - "github.com/wtfutil/wtf/cfg" - "github.com/wtfutil/wtf/utils" -) - -const ( - defaultFocusable = true - defaultTitle = "Todoist" -) - -// Settings defines the configuration properties for this module -type Settings struct { - common *cfg.Common - - apiKey string `help:"Your Todoist API key"` - projects []uint -} - -// NewSettingsFromYAML creates a new settings instance from a YAML config block -func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { - settings := Settings{ - common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig), - - apiKey: ymlConfig.UString("apiKey", ymlConfig.UString("apikey", os.Getenv("WTF_TODOIST_TOKEN"))), - projects: utils.IntsToUints(utils.ToInts(ymlConfig.UList("projects"))), - } - - cfg.ModuleSecret(name, globalConfig, &settings.apiKey).Load() - - return &settings -} diff --git a/modules/trello/card.go b/modules/trello/card.go deleted file mode 100644 index 31f3467c..00000000 --- a/modules/trello/card.go +++ /dev/null @@ -1,13 +0,0 @@ -package trello - -type TrelloCard struct { - ID string - Name string - List string - Description string -} - -type TrelloList struct { - ID string - Name string -} diff --git a/modules/trello/client.go b/modules/trello/client.go deleted file mode 100644 index 6df6cc22..00000000 --- a/modules/trello/client.go +++ /dev/null @@ -1,106 +0,0 @@ -package trello - -import ( - "fmt" - - "github.com/adlio/trello" -) - -func GetCards(client *trello.Client, username string, boardName string, listNames []string) (*SearchResult, error) { - boardID, err := getBoardID(client, username, boardName) - if err != nil { - return nil, err - } - - lists, err := getLists(client, boardID, listNames) - if err != nil { - return nil, err - } - - searchResult := &SearchResult{Total: 0} - searchResult.TrelloCards = make(map[string][]TrelloCard) - - for _, list := range lists { - cards, err := getCardsOnList(client, list.ID) - if err != nil { - return nil, err - } - - searchResult.Total += len(cards) - cardArray := make([]TrelloCard, 0) - - for _, card := range cards { - trelloCard := TrelloCard{ - ID: card.ID, - List: list.Name, - Name: card.Name, - Description: card.Desc, - } - cardArray = append(cardArray, trelloCard) - } - - searchResult.TrelloCards[list.Name] = cardArray - } - - return searchResult, nil -} - -func getBoardID(client *trello.Client, username, boardName string) (string, error) { - member, err := client.GetMember(username, trello.Defaults()) - if err != nil { - return "", err - } - - boards, err := member.GetBoards(trello.Defaults()) - if err != nil { - return "", err - } - - for _, board := range boards { - if board.Name == boardName { - return board.ID, nil - } - } - - return "", fmt.Errorf("could not find board with name %s", boardName) -} - -func getLists(client *trello.Client, boardID string, listNames []string) ([]TrelloList, error) { - comparison := make(map[string]string, len(listNames)) - results := []TrelloList{} - //convert to a map for comparison - for _, item := range listNames { - comparison[item] = "" - } - board, err := client.GetBoard(boardID, trello.Defaults()) - if err != nil { - return nil, err - } - - boardLists, err := board.GetLists(trello.Defaults()) - if err != nil { - return nil, err - } - - for _, list := range boardLists { - if _, ok := comparison[list.Name]; ok { - results = append(results, TrelloList{ID: list.ID, Name: list.Name}) - } - } - - return results, nil -} - -func getCardsOnList(client *trello.Client, listID string) ([]*trello.Card, error) { - list, err := client.GetList(listID, trello.Defaults()) - if err != nil { - return nil, err - } - - cards, err := list.GetCards(trello.Defaults()) - if err != nil { - return nil, err - } - - return cards, nil -} diff --git a/modules/trello/search_result.go b/modules/trello/search_result.go deleted file mode 100644 index 44ca8dc7..00000000 --- a/modules/trello/search_result.go +++ /dev/null @@ -1,6 +0,0 @@ -package trello - -type SearchResult struct { - Total int - TrelloCards map[string][]TrelloCard -} diff --git a/modules/trello/settings.go b/modules/trello/settings.go deleted file mode 100644 index 341915b2..00000000 --- a/modules/trello/settings.go +++ /dev/null @@ -1,62 +0,0 @@ -package trello - -import ( - "os" - - "github.com/olebedev/config" - "github.com/wtfutil/wtf/cfg" -) - -const ( - defaultFocusable = false - defaultTitle = "Trello" -) - -type Settings struct { - common *cfg.Common - - accessToken string - apiKey string - board string - list []string - username string -} - -func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { - settings := Settings{ - common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig), - - accessToken: ymlConfig.UString("accessToken", ymlConfig.UString("apikey", os.Getenv("WTF_TRELLO_ACCESS_TOKEN"))), - apiKey: ymlConfig.UString("apiKey", os.Getenv("WTF_TRELLO_API_KEY")), - board: ymlConfig.UString("board"), - username: ymlConfig.UString("username"), - } - - cfg.ModuleSecret(name+"-api", globalConfig, &settings.apiKey).Load() - cfg.ModuleSecret(name+"-access", globalConfig, &settings.accessToken).Load() - - settings.list = buildLists(ymlConfig, globalConfig) - - return &settings -} - -func buildLists(ymlConfig *config.Config, globalConfig *config.Config) []string { - lists := []string{} - - // Single list - list, err := ymlConfig.String("list") - if err == nil { - lists = append(lists, list) - return lists - } - - // Array of lists - listList := ymlConfig.UList("list") - for _, listName := range listList { - if list, ok := listName.(string); ok { - lists = append(lists, list) - } - } - - return lists -} diff --git a/modules/trello/widget.go b/modules/trello/widget.go deleted file mode 100644 index 01bb706d..00000000 --- a/modules/trello/widget.go +++ /dev/null @@ -1,75 +0,0 @@ -package trello - -import ( - "fmt" - - "github.com/adlio/trello" - "github.com/rivo/tview" - "github.com/wtfutil/wtf/view" -) - -type Widget struct { - view.TextWidget - - settings *Settings -} - -func NewWidget(app *tview.Application, settings *Settings) *Widget { - widget := Widget{ - TextWidget: view.NewTextWidget(app, settings.common), - - settings: settings, - } - - return &widget -} - -/* -------------------- Exported Functions -------------------- */ - -func (widget *Widget) Refresh() { - widget.Redraw(widget.content) -} - -/* -------------------- Unexported Functions -------------------- */ - -func (widget *Widget) content() (string, string, bool) { - - client := trello.NewClient( - widget.settings.apiKey, - widget.settings.accessToken, - ) - - // Get the cards - searchResult, err := GetCards( - client, - widget.settings.username, - widget.settings.board, - widget.settings.list, - ) - - var title string - content := "" - - wrap := false - if err != nil { - wrap = true - title = widget.CommonSettings().Title - content = err.Error() - } else { - title = fmt.Sprintf( - "[white]%s: [green]%s ", - widget.CommonSettings().Title, - widget.settings.board, - ) - for list, cardArray := range searchResult.TrelloCards { - content += fmt.Sprintf(" [%s]%s[white]\n", widget.settings.common.Colors.Subheading, list) - - for _, card := range cardArray { - content += fmt.Sprintf(" %s[white]\n", card.Name) - } - content = fmt.Sprintf("%s\n", content) - } - } - - return title, content, wrap -}