Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use type.setClient(c) for consistency and ... #77

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions action.go
Expand Up @@ -14,6 +14,7 @@ import (
// Actions are immutable event traces generated whenever an action occurs in Trello.
// See https://developers.trello.com/reference/#actions.
type Action struct {
client *Client
ID string `json:"id"`
IDMemberCreator string `json:"idMemberCreator"`
Type string `json:"type"`
Expand Down Expand Up @@ -194,3 +195,8 @@ func ListAfterAction(a *Action) *List {
}
return nil
}

// setClient on Action for interface consistency
func (a *Action) setClient(client *Client) {
a.client = client
}
16 changes: 16 additions & 0 deletions arguments.go
Expand Up @@ -7,6 +7,7 @@ package trello

import (
"net/url"
"strconv"
)

// Arguments are used for passing URL parameters to the client for making API calls.
Expand All @@ -17,6 +18,21 @@ func Defaults() Arguments {
return make(Arguments)
}

// DefaultsWithCache is just like Defaults() but with cache enabled
func DefaultsWithCache() (args Arguments) {
args = make(Arguments)
args["EnableCache"] = "true"
return
}

// IsCacheEnabled returns a boolean true if EnableCache is set to something truthy
func (args Arguments) IsCacheEnabled() (cacheEnabled bool) {
if arg, ok := args["EnableCache"]; ok { // if "EnableCache" arg is not present cacheEnabled will be false anyhow
cacheEnabled, _ = strconv.ParseBool(arg) // if parsing err's cacheEnabled will be false anyhow
}
return
}

// ToURLValues returns the argument's URL value representation.
func (args Arguments) ToURLValues() url.Values {
v := url.Values{}
Expand Down
7 changes: 7 additions & 0 deletions attachment.go
Expand Up @@ -8,6 +8,8 @@ package trello
// Attachment represent the attachments of cards. This is a nested resource of Card.
// https://developers.trello.com/reference/#attachments
type Attachment struct {
client *Client
Card *Card
ID string `json:"id"`
Name string `json:"name"`
Pos float32 `json:"pos"`
Expand All @@ -30,3 +32,8 @@ type AttachmentPreview struct {
Bytes int `json:"bytes"`
Scaled bool `json:"scaled"`
}

// setClient on Attachment for interface consistency
func (a *Attachment) setClient(client *Client) {
a.client = client
}
56 changes: 39 additions & 17 deletions board.go
Expand Up @@ -124,23 +124,31 @@ func (c *Client) CreateBoard(board *Board, extraArgs ...Arguments) error {

err := c.Post(path, args, &board)
if err == nil {
board.client = c
board.setClient(c)
}
return err
}

// Update PUTs the supported board attributes remote and updates
// the struct from the returned values.
func (b *Board) Update(extraArgs ...Arguments) error {
func (b *Board) Update(extraArgs ...Arguments) (err error) {
args := flattenArguments(extraArgs)
return b.client.PutBoard(b, args)
err = b.client.PutBoard(b, args)
if args.IsCacheEnabled() {
b.client.cache.SetBoard(b.ID, b)
}
return
}

// Delete makes a DELETE call for the receiver Board.
func (b *Board) Delete(extraArgs ...Arguments) error {
func (b *Board) Delete(extraArgs ...Arguments) (err error) {
args := flattenArguments(extraArgs)
path := fmt.Sprintf("boards/%s", b.ID)
return b.client.Delete(path, args, b)
err = b.client.Delete(path, Arguments{}, b)
if args.IsCacheEnabled() {
b.client.cache.RemoveBoard(b.ID)
}
return
}

// AddedMembersResponse represents a response after adding a new member.
Expand All @@ -167,10 +175,19 @@ func (b *Board) AddMember(member *Member, extraArgs ...Arguments) (response *Add
// GetBoard retrieves a Trello board by its ID.
func (c *Client) GetBoard(boardID string, extraArgs ...Arguments) (board *Board, err error) {
args := flattenArguments(extraArgs)
path := fmt.Sprintf("boards/%s", boardID)
err = c.Get(path, args, &board)
if args.IsCacheEnabled() {
var found bool
if board, found = c.cache.GetBoard(boardID); !found { // Not Found, Query without cache
args["CacheEnabled"] = "false"
board, err = c.GetBoard(boardID, args)
c.cache.SetBoard(boardID, board)
}
} else {
path := fmt.Sprintf("boards/%s", boardID)
err = c.Get(path, args, &board)
}
if board != nil {
board.client = c
board.setClient(c)
}
return
}
Expand All @@ -180,8 +197,8 @@ func (c *Client) GetMyBoards(extraArgs ...Arguments) (boards []*Board, err error
args := flattenArguments(extraArgs)
path := "members/me/boards"
err = c.Get(path, args, &boards)
for i := range boards {
boards[i].client = c
for _, board := range boards {
board.setClient(c)
}
return
}
Expand All @@ -191,12 +208,8 @@ func (m *Member) GetBoards(extraArgs ...Arguments) (boards []*Board, err error)
args := flattenArguments(extraArgs)
path := fmt.Sprintf("members/%s/boards", m.ID)
err = m.client.Get(path, args, &boards)
for i := range boards {
boards[i].client = m.client

for j := range boards[i].Lists {
boards[i].Lists[j].client = m.client
}
for _, board := range boards {
board.setClient(m.client)
}
return
}
Expand Down Expand Up @@ -237,7 +250,16 @@ func (c *Client) PutBoard(board *Board, extraArgs ...Arguments) error {

err := c.Put(path, args, &board)
if err == nil {
board.client = c
board.setClient(c)
}
return err
}

// setclient on board and any sub-objects
func (b *Board) setClient(client *Client) {
b.client = client
for _, list := range b.Lists {
list.setClient(client)
list.Board = b // Set Parent
}
}
4 changes: 2 additions & 2 deletions board_test.go
Expand Up @@ -165,13 +165,13 @@ func testBoard(t *testing.T) *Board {

func TestBoardUpdate(t *testing.T) {
expected := map[string]map[string]string{
"created": map[string]string{
"created": {
"id": "5d2ccd3015468d3df508f10d",
"name": "test-board-for-update",
"description": "Some description",
"cardAging": "regular",
},
"updated": map[string]string{
"updated": {
"id": "5d2ccd3015468d3df508f10d",
"name": "test-board-for-update plus",
"description": "Some other description",
Expand Down
58 changes: 50 additions & 8 deletions card.go
Expand Up @@ -237,7 +237,7 @@ func (c *Client) CreateCard(card *Card, extraArgs ...Arguments) error {
args.flatten(extraArgs)
err := c.Post(path, args, &card)
if err == nil {
card.client = c
card.setClient(c)
}
return err
}
Expand All @@ -259,7 +259,8 @@ func (l *List) AddCard(card *Card, extraArgs ...Arguments) error {

err := l.client.Post(path, args, &card)
if err == nil {
card.client = l.client
card.setClient(l.client)
card.List = l
} else {
err = errors.Wrapf(err, "Error adding card to list %s", l.ID)
}
Expand All @@ -282,7 +283,7 @@ func (c *Card) CopyToList(listID string, extraArgs ...Arguments) (*Card, error)
args.flatten(extraArgs)
err := c.client.Post(path, args, &newCard)
if err == nil {
newCard.client = c.client
newCard.setClient(c.client)
} else {
err = errors.Wrapf(err, "Error copying card '%s' to list '%s'.", c.ID, listID)
}
Expand Down Expand Up @@ -342,6 +343,7 @@ func (c *Card) GetParentCard(extraArgs ...Arguments) (*Card, error) {

if action != nil && action.Data != nil && action.Data.CardSource != nil {
card, err := c.client.GetCard(action.Data.CardSource.ID, args)
card.setClient(c.client)
return card, err
}

Expand Down Expand Up @@ -460,7 +462,7 @@ func (c *Client) GetCard(cardID string, extraArgs ...Arguments) (card *Card, err
path := fmt.Sprintf("cards/%s", cardID)
err = c.Get(path, args, &card)
if card != nil {
card.client = c
card.setClient(c)
}
return card, err
}
Expand Down Expand Up @@ -488,8 +490,9 @@ func (b *Board) GetCards(extraArgs ...Arguments) (cards []*Card, err error) {
}
}

for i := range cards {
cards[i].client = b.client
for _, card := range cards {
card.Board = b // Set this hear to avoid the lookup
card.setClient(b.client)
}

return
Expand All @@ -500,8 +503,11 @@ func (l *List) GetCards(extraArgs ...Arguments) (cards []*Card, err error) {
args := flattenArguments(extraArgs)
path := fmt.Sprintf("lists/%s/cards", l.ID)
err = l.client.Get(path, args, &cards)
for i := range cards {
cards[i].client = l.client
for _, card := range cards {
// Set these here before setClient to avoid lookup
card.Board = l.Board
card.List = l
card.setClient(l.client)
}
return
}
Expand All @@ -518,3 +524,39 @@ func earliestCardID(cards []*Card) string {
}
return earliest
}

// setClient on card and sub-objects
func (c *Card) setClient(client *Client) {
c.client = client
if c.Board == nil { // Retrieve and Set Board
board, err := c.client.GetBoard(c.IDBoard, DefaultsWithCache())
if err == nil {
c.Board = board
}
}
if c.List == nil { // Retrieve and Set List
list, err := c.client.GetList(c.IDList, DefaultsWithCache())
if err == nil {
c.List = list
}
}
for _, action := range c.Actions {
action.setClient(client)
}
for _, attachment := range c.Attachments {
attachment.setClient(client)
attachment.Card = c // Set Parent
}
for _, checklist := range c.Checklists {
checklist.setClient(client)
checklist.Card = c // Set Parent
}
for _, label := range c.Labels {
label.setClient(client)
label.Board = c.Board // Set Parent
}
for _, member := range c.Members {
member.setClient(client)
}

}
36 changes: 28 additions & 8 deletions checklist.go
Expand Up @@ -11,17 +11,20 @@ import "fmt"
// A card can have one zero or more checklists.
// https://developers.trello.com/reference/#checklist-object
type Checklist struct {
ID string `json:"id"`
Name string `json:"name"`
IDBoard string `json:"idBoard,omitempty"`
IDCard string `json:"idCard,omitempty"`
Pos float64 `json:"pos,omitempty"`
CheckItems []CheckItem `json:"checkItems,omitempty"`
client *Client
Card *Card
ID string `json:"id"`
Name string `json:"name"`
IDBoard string `json:"idBoard,omitempty"`
IDCard string `json:"idCard,omitempty"`
Pos float64 `json:"pos,omitempty"`
CheckItems []*CheckItem `json:"checkItems,omitempty"`
}

// CheckItem is a nested resource representing an item in Checklist.
type CheckItem struct {
client *Client
Checklist *Checklist
ID string `json:"id"`
Name string `json:"name"`
State string `json:"state"`
Expand Down Expand Up @@ -52,7 +55,8 @@ func (c *Client) CreateChecklist(card *Card, name string, extraArgs ...Arguments
checklist = &Checklist{}
err = c.Post(path, args, &checklist)
if err == nil {
checklist.client = c
checklist.setClient(c)
checklist.Card = card
checklist.IDCard = card.ID
card.Checklists = append(card.Checklists, checklist)
}
Expand Down Expand Up @@ -87,7 +91,9 @@ func (c *Client) CreateCheckItem(checklist *Checklist, name string, extraArgs ..
item = &CheckItem{}
err = c.Post(path, args, item)
if err == nil {
checklist.CheckItems = append(checklist.CheckItems, *item)
checklist.CheckItems = append(checklist.CheckItems, item)
item.setClient(c)
item.Checklist = checklist
}
return
}
Expand All @@ -103,3 +109,17 @@ func (c *Client) GetChecklist(checklistID string, args Arguments) (checklist *Ch
}
return checklist, err
}

// setClient on checkList and sub-objects
func (cl *Checklist) setClient(client *Client) {
cl.client = client
for _, checkitem := range cl.CheckItems {
checkitem.setClient(client)
checkitem.Checklist = cl // Set Parent
}
}

// setClient on checkItem (for interface consistency)
func (ci *CheckItem) setClient(client *Client) {
ci.client = client
}
4 changes: 2 additions & 2 deletions checklist_test.go
Expand Up @@ -81,8 +81,8 @@ func TestCreateCheckItem(t *testing.T) {
t.Errorf("Expected checklist to pick up the created checkitem. Instead got '%v'.", len(cl.CheckItems))
}

if cl.CheckItems[0] != *item {
t.Errorf("Expected the returned item and the checkitem inside the checklist to be equal.\n got: %#v\nwant: %#v", cl.CheckItems[0], *item)
if cl.CheckItems[0] != item {
t.Errorf("Expected the returned item and the checkitem inside the checklist to be equal.\n got: %#v\nwant: %#v", cl.CheckItems[0], item)
}
if item.Pos != 35 {
t.Errorf("Expected the returned item to pick up a position. Instead got '%v'.", item.Pos)
Expand Down