1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

Create generalized todo module (#982)

* Create generalized todo module

Makes existing modules "backends"
This gives us a consistent interface

* Fix check issues

* Fix lint errors

* Make changes to stay on wtfutil todoist fork
This commit is contained in:
Sean Smith 2020-10-07 17:58:24 -04:00 committed by GitHub
parent 38e21605a4
commit 3c63eee8d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 511 additions and 459 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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()
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}

View File

@ -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
}

View File

@ -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()
}

View File

@ -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()
}
}

View File

@ -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
}

View File

@ -1,13 +0,0 @@
package trello
type TrelloCard struct {
ID string
Name string
List string
Description string
}
type TrelloList struct {
ID string
Name string
}

View File

@ -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
}

View File

@ -1,6 +0,0 @@
package trello
type SearchResult struct {
Total int
TrelloCards map[string][]TrelloCard
}

View File

@ -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
}

View File

@ -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
}