Skip to content

Commit f8e8e6a

Browse files
author
nukosuke
authored
Merge pull request #262 from pierce-m/ticket-comment-list-pagination
Add cursor pagination for list ticket comments.
2 parents b3a7d08 + 3f19b8a commit f8e8e6a

File tree

6 files changed

+104
-17
lines changed

6 files changed

+104
-17
lines changed

fixture/GET/ticket_comments.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,10 @@
2222
"attachments": [],
2323
"created_at": "2019-06-03T02:23:47Z"
2424
}
25-
]
25+
],
26+
"meta": {
27+
"has_more": true,
28+
"after_cursor": "xxx",
29+
"before_cursor": "yyy"
30+
}
2631
}

zendesk/cursor.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package zendesk
22

3+
// DEPRECATED -- This file describes Zendesk API's "legacy" cursor pagination.
4+
// PLEASE USE CursorPagination IN zendesk.go INSTEAD!
5+
36
// Cursor is struct for cursor-based pagination
47
type Cursor struct {
58
AfterURL string `json:"after_url"`

zendesk/mock/client.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zendesk/ticket_comment.go

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
// TicketCommentAPI is an interface containing all ticket comment related API methods
1111
type TicketCommentAPI interface {
1212
CreateTicketComment(ctx context.Context, ticketID int64, ticketComment TicketComment) (TicketComment, error)
13-
ListTicketComments(ctx context.Context, ticketID int64) ([]TicketComment, error)
13+
ListTicketComments(ctx context.Context, ticketID int64, opts *ListTicketCommentsOptions) (*ListTicketCommentsResult, error)
1414
MakeCommentPrivate(ctx context.Context, ticketID int64, ticketCommentID int64) error
1515
}
1616

@@ -89,25 +89,65 @@ func (z *Client) CreateTicketComment(ctx context.Context, ticketID int64, ticket
8989
return result, err
9090
}
9191

92+
type listTicketCommentsSort string
93+
94+
const (
95+
// TicketCommentCreatedAtAsc defines ASC sort val.
96+
TicketCommentCreatedAtAsc listTicketCommentsSort = "created_at"
97+
98+
// TicketCommentCreatedAtDesc defines DESC sort val.
99+
TicketCommentCreatedAtDesc listTicketCommentsSort = "-created_at"
100+
101+
// ListTicketCommentsMaxPageSize contains the max page size.
102+
ListTicketCommentsMaxPageSize int = 100
103+
)
104+
105+
// ListTicketCommentOptions contains all the options supported by ListTicketComments endpoint.
106+
type ListTicketCommentsOptions struct {
107+
CursorPagination
108+
109+
Include string `url:"include,omitempty"`
110+
IncludeInlineImages string `url:"include_inline_images,omitempty"`
111+
Sort listTicketCommentsSort `url:"sort,omitempty"`
112+
}
113+
114+
// ListTicketCommentsResult contains the resulting ticket comments
115+
// and cursor pagination metadata.
116+
type ListTicketCommentsResult struct {
117+
TicketComments []TicketComment `json:"comments"`
118+
Meta CursorPaginationMeta `json:"meta"`
119+
}
120+
92121
// ListTicketComments gets a list of comment for a specified ticket
93122
//
94123
// ref: https://developer.zendesk.com/rest_api/docs/support/ticket_comments#list-comments
95-
func (z *Client) ListTicketComments(ctx context.Context, ticketID int64) ([]TicketComment, error) {
96-
var result struct {
97-
TicketComments []TicketComment `json:"comments"`
124+
func (z *Client) ListTicketComments(
125+
ctx context.Context,
126+
ticketID int64,
127+
opts *ListTicketCommentsOptions,
128+
) (*ListTicketCommentsResult, error) {
129+
url := fmt.Sprintf("/tickets/%d/comments.json", ticketID)
130+
131+
var err error
132+
if opts != nil {
133+
url, err = addOptions(url, opts)
134+
if err != nil {
135+
return nil, err
136+
}
98137
}
99138

100-
body, err := z.get(ctx, fmt.Sprintf("/tickets/%d/comments.json", ticketID))
139+
body, err := z.get(ctx, url)
101140
if err != nil {
102-
return []TicketComment{}, err
141+
return nil, err
103142
}
104143

144+
var result ListTicketCommentsResult
105145
err = json.Unmarshal(body, &result)
106146
if err != nil {
107-
return []TicketComment{}, err
147+
return nil, err
108148
}
109149

110-
return result.TicketComments, err
150+
return &result, err
111151
}
112152

113153
// MakeCommentPrivate converts an existing ticket comment to an internal note that is not publicly viewable.

zendesk/ticket_comment_test.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,26 @@ func TestListTicketComments(t *testing.T) {
4343
client := newTestClient(mockAPI)
4444
defer mockAPI.Close()
4545

46-
ticketComments, err := client.ListTicketComments(ctx, 2)
46+
result, err := client.ListTicketComments(ctx, 2, nil)
4747
if err != nil {
4848
t.Fatalf("Failed to list ticket comments: %s", err)
4949
}
5050

5151
expectedLength := 2
52-
if len(ticketComments) != expectedLength {
53-
t.Fatalf("Returned ticket comments does not have the expected length %d. Ticket comments length is %d", expectedLength, len(ticketComments))
52+
if len(result.TicketComments) != expectedLength {
53+
t.Fatalf("Returned ticket comments does not have the expected length %d. Ticket comments length is %d", expectedLength, len(result.TicketComments))
54+
}
55+
56+
expectedPaginationMeta := CursorPaginationMeta{
57+
HasMore: true,
58+
AfterCursor: "xxx",
59+
BeforeCursor: "yyy",
60+
}
61+
62+
if result.Meta != expectedPaginationMeta {
63+
t.Fatalf(`Failed to return correct cursor options.
64+
Expected: %+v
65+
Received: %+v`, expectedPaginationMeta, result.Meta)
5466
}
5567
}
5668

zendesk/zendesk.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,33 @@ type (
4040
Put(ctx context.Context, path string, data interface{}) ([]byte, error)
4141
Delete(ctx context.Context, path string) error
4242
}
43+
44+
// CursorPagination contains options for using cursor pagination.
45+
// Cursor pagination is preferred where possible.
46+
CursorPagination struct {
47+
// PageSize sets the number of results per page.
48+
// Most endpoints support up to 100 records per page.
49+
PageSize int `url:"page[size],omitempty"`
50+
51+
// PageAfter provides the "next" cursor.
52+
PageAfter string `url:"page[after],omitempty"`
53+
54+
// PageBefore provides the "previous" cursor.
55+
PageBefore string `url:"page[before],omitempty"`
56+
}
57+
58+
// CursorPaginationMeta contains information concerning how to fetch
59+
// next and previous results, and if next results exist.
60+
CursorPaginationMeta struct {
61+
// HasMore is true if more results exist in the endpoint.
62+
HasMore bool `json:"has_more,omitempty"`
63+
64+
// AfterCursor contains the cursor of the next result set.
65+
AfterCursor string `json:"after_cursor,omitempty"`
66+
67+
// BeforeCursor contains the cursor of the previous result set.
68+
BeforeCursor string `json:"before_cursor,omitempty"`
69+
}
4370
)
4471

4572
// NewClient creates new Zendesk API client

0 commit comments

Comments
 (0)