Skip to content

Commit

Permalink
Added trello widget
Browse files Browse the repository at this point in the history
  • Loading branch information
retgits committed Jun 18, 2018
1 parent f879cb1 commit e6d45e4
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 0 deletions.
87 changes: 87 additions & 0 deletions _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.

<img src="/imgs/modules/trello.png" width="640" height="188" alt="trello screenshot" />

## Source Code

```bash
wtf/trello/
```

## Required ENV Variables

<span class="caption">Key:</span> `WTF_TRELLO_APP_KEY` <br />
<span class="caption">Value:</span> Your Trello App Key. <br />
<span class="caption">Key:</span> `WTF_TRELLO_ACCESS_TOKEN` <br />
<span class="caption">Value:</span> Your Trello Access Token. <br />

_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` <br />
The name of the Trello board. <br />

`enabled` <br />
Determines whether or not this module is executed and if its data displayed onscreen. <br />
Values: `true`, `false`.

`list` <br />
The Trello lists to fetch cards from. <br />

`refreshInterval` <br />
How often, in seconds, this module will update its data. <br />
Values: A positive integer, `0..n`.

`username` <br />
Your Trello username. <br />

`position` <br />
Where in the grid this module's widget will be displayed. <br />
Binary file added _site/static/imgs/modules/trello.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions trello/card.go
@@ -0,0 +1,8 @@
package trello

type TrelloCard struct {
ID string
Name string
List string
Description string
}
98 changes: 98 additions & 0 deletions 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
}
6 changes: 6 additions & 0 deletions trello/search_result.go
@@ -0,0 +1,6 @@
package trello

type SearchResult struct {
Total int
TrelloCards map[string][]TrelloCard
}
81 changes: 81 additions & 0 deletions 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
}
3 changes: 3 additions & 0 deletions wtf.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit e6d45e4

Please sign in to comment.