From e6d45e4eebfb8908866557ed4f5b0610a5f3e4f0 Mon Sep 17 00:00:00 2001 From: retgits Date: Mon, 18 Jun 2018 13:38:24 -0700 Subject: [PATCH] Added trello widget --- _site/content/posts/modules/trello.md | 87 +++++++++++++++++++++++ _site/static/imgs/modules/trello.png | Bin 0 -> 26077 bytes trello/card.go | 8 +++ trello/client.go | 98 ++++++++++++++++++++++++++ trello/search_result.go | 6 ++ trello/widget.go | 81 +++++++++++++++++++++ wtf.go | 3 + 7 files changed, 283 insertions(+) create mode 100644 _site/content/posts/modules/trello.md create mode 100644 _site/static/imgs/modules/trello.png create mode 100644 trello/card.go create mode 100644 trello/client.go create mode 100644 trello/search_result.go create mode 100644 trello/widget.go diff --git a/_site/content/posts/modules/trello.md b/_site/content/posts/modules/trello.md new file mode 100644 index 00000000..c8649b69 --- /dev/null +++ b/_site/content/posts/modules/trello.md @@ -0,0 +1,87 @@ +--- +title: "Trello" +date: 2018-05-10T10:44:35-07:00 +draft: false +--- + +Displays all Trello cards on specified lists. + +trello screenshot + +## Source Code + +```bash +wtf/trello/ +``` + +## Required ENV Variables + +Key: `WTF_TRELLO_APP_KEY`
+Value: Your Trello App Key.
+Key: `WTF_TRELLO_ACCESS_TOKEN`
+Value: Your Trello Access Token.
+ +_You can get your API key at: trello.com/app-key._ + +## Keyboard Commands + +None. + +## Configuration + +### Single Trello List + +```yaml +trello: + board: Main + enabled: true + list: "Todo" + position: + height: 1 + left: 2 + top: 0 + width: 1 + refreshInterval: 3600 + username: myname +``` + +### Multiple Trello Lists + +If you want to monitor multiple Trello lists, use the following +configuration (note the difference in `list`): + +```yaml +trello: + board: Main + enabled: true + list: ["Todo", "Done"] + position: + height: 1 + left: 2 + top: 0 + width: 1 + refreshInterval: 3600 + username: myname +``` + +### Attributes + +`board`
+The name of the Trello board.
+ +`enabled`
+Determines whether or not this module is executed and if its data displayed onscreen.
+Values: `true`, `false`. + +`list`
+The Trello lists to fetch cards from.
+ +`refreshInterval`
+How often, in seconds, this module will update its data.
+Values: A positive integer, `0..n`. + +`username`
+Your Trello username.
+ +`position`
+Where in the grid this module's widget will be displayed.
diff --git a/_site/static/imgs/modules/trello.png b/_site/static/imgs/modules/trello.png new file mode 100644 index 0000000000000000000000000000000000000000..79fa69651d5adad3a126f8c47ddb8a2c0ad335d5 GIT binary patch literal 26077 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 akZRJ&HOqumg@rs#S?@PPt*09HcmD^)2nclm literal 0 HcmV?d00001 diff --git a/trello/card.go b/trello/card.go new file mode 100644 index 00000000..e1487c94 --- /dev/null +++ b/trello/card.go @@ -0,0 +1,8 @@ +package trello + +type TrelloCard struct { + ID string + Name string + List string + Description string +} diff --git a/trello/client.go b/trello/client.go new file mode 100644 index 00000000..dcccaf55 --- /dev/null +++ b/trello/client.go @@ -0,0 +1,98 @@ +package trello + +import ( + "fmt" + + "github.com/adlio/trello" + "github.com/senorprogrammer/wtf/wtf" +) + +func GetCards(client *trello.Client, lists map[string]string) (*SearchResult, error) { + boardID, err := getBoardID(client) + if err != nil { + return nil, err + } + + lists, err = getListIDs(client, boardID, lists) + if err != nil { + return nil, err + } + + searchResult := &SearchResult{Total: 0} + searchResult.TrelloCards = make(map[string][]TrelloCard) + + for listName, listID := range lists { + cards, err := getCardsOnList(client, listID) + if err != nil { + return nil, err + } + searchResult.Total = searchResult.Total + len(cards) + cardArray := make([]TrelloCard, 0) + for _, card := range cards { + trelloCard := TrelloCard{ + ID: card.ID, + List: listName, + Name: card.Name, + Description: card.Desc, + } + cardArray = append(cardArray, trelloCard) + } + searchResult.TrelloCards[listName] = cardArray + } + + return searchResult, nil +} + +func getBoardID(client *trello.Client) (string, error) { + member, err := client.GetMember(wtf.Config.UString("wtf.mods.trello.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 == wtf.Config.UString("wtf.mods.trello.board") { + return board.ID, nil + } + } + + return "", fmt.Errorf("could not find board with name %s", wtf.Config.UString("wtf.mods.trello.board")) +} + +func getListIDs(client *trello.Client, boardID string, lists map[string]string) (map[string]string, error) { + 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 := lists[list.Name]; ok { + lists[list.Name] = list.ID + } + } + + return lists, 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/trello/search_result.go b/trello/search_result.go new file mode 100644 index 00000000..44ca8dc7 --- /dev/null +++ b/trello/search_result.go @@ -0,0 +1,6 @@ +package trello + +type SearchResult struct { + Total int + TrelloCards map[string][]TrelloCard +} diff --git a/trello/widget.go b/trello/widget.go new file mode 100644 index 00000000..99c1b64a --- /dev/null +++ b/trello/widget.go @@ -0,0 +1,81 @@ +package trello + +import ( + "fmt" + "os" + + "github.com/adlio/trello" + "github.com/senorprogrammer/wtf/wtf" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" Trello ", "trello", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + client := trello.NewClient(os.Getenv("WTF_TRELLO_APP_KEY"), os.Getenv("WTF_TRELLO_ACCESS_TOKEN")) + + // Get the cards + searchResult, err := GetCards(client, getLists()) + widget.UpdateRefreshedAt() + + if err != nil { + widget.View.SetWrap(true) + widget.View.SetTitle(fmt.Sprintf("%s", widget.Name)) + fmt.Fprintf(widget.View, "%v", err) + } else { + widget.View.SetWrap(false) + widget.View.SetTitle( + fmt.Sprintf( + "[white]%s: [green]%s ", + widget.Name, + wtf.Config.UString("wtf.mods.trello.board"), + ), + ) + widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(searchResult))) + } +} + +/* -------------------- Unexported Functions -------------------- */ +func (widget *Widget) contentFrom(searchResult *SearchResult) string { + str := "" + + for list, cardArray := range searchResult.TrelloCards { + str = fmt.Sprintf("%s [red]Cards in %s[white]\n", str, list) + for _, card := range cardArray { + str = fmt.Sprintf("%s [green]%s[white]\n", str, card.Name) + } + str = fmt.Sprintf("%s\n", str) + } + + return str +} + +func getLists() map[string]string { + list := make(map[string]string) + // see if project is set to a single string + configPath := "wtf.mods.trello.list" + singleList, err := wtf.Config.String(configPath) + if err == nil { + list[singleList] = "" + return list + } + // else, assume list + multiList := wtf.Config.UList(configPath) + for _, proj := range multiList { + if str, ok := proj.(string); ok { + list[str] = "" + } + } + return list +} diff --git a/wtf.go b/wtf.go index 3c89731e..92450c0d 100644 --- a/wtf.go +++ b/wtf.go @@ -38,6 +38,7 @@ import ( "github.com/senorprogrammer/wtf/system" "github.com/senorprogrammer/wtf/textfile" "github.com/senorprogrammer/wtf/todo" + "github.com/senorprogrammer/wtf/trello" "github.com/senorprogrammer/wtf/weatherservices/prettyweather" "github.com/senorprogrammer/wtf/weatherservices/weather" "github.com/senorprogrammer/wtf/wtf" @@ -213,6 +214,8 @@ func addWidget(app *tview.Application, pages *tview.Pages, widgetName string) { Widgets = append(Widgets, textfile.NewWidget(app, pages)) case "todo": Widgets = append(Widgets, todo.NewWidget(app, pages)) + case "trello": + Widgets = append(Widgets, trello.NewWidget()) case "weather": Widgets = append(Widgets, weather.NewWidget(app, pages)) default: