|
7 | 7 | "io"
|
8 | 8 | "io/ioutil"
|
9 | 9 | "mime/multipart"
|
| 10 | + "net/http" |
10 | 11 | "net/url"
|
11 | 12 | "reflect"
|
12 | 13 | "strings"
|
@@ -295,6 +296,10 @@ type Parent struct {
|
295 | 296 | // Time represents the Time definition of JIRA as a time.Time of go
|
296 | 297 | type Time time.Time
|
297 | 298 |
|
| 299 | +func (t Time) Equal(u Time) bool { |
| 300 | + return time.Time(t).Equal(time.Time(u)) |
| 301 | +} |
| 302 | + |
298 | 303 | // Date represents the Date definition of JIRA as a time.Time of go
|
299 | 304 | type Date time.Time
|
300 | 305 |
|
@@ -394,17 +399,23 @@ type Worklog struct {
|
394 | 399 |
|
395 | 400 | // WorklogRecord represents one entry of a Worklog
|
396 | 401 | type WorklogRecord struct {
|
397 |
| - Self string `json:"self,omitempty" structs:"self,omitempty"` |
398 |
| - Author *User `json:"author,omitempty" structs:"author,omitempty"` |
399 |
| - UpdateAuthor *User `json:"updateAuthor,omitempty" structs:"updateAuthor,omitempty"` |
400 |
| - Comment string `json:"comment,omitempty" structs:"comment,omitempty"` |
401 |
| - Created *Time `json:"created,omitempty" structs:"created,omitempty"` |
402 |
| - Updated *Time `json:"updated,omitempty" structs:"updated,omitempty"` |
403 |
| - Started *Time `json:"started,omitempty" structs:"started,omitempty"` |
404 |
| - TimeSpent string `json:"timeSpent,omitempty" structs:"timeSpent,omitempty"` |
405 |
| - TimeSpentSeconds int `json:"timeSpentSeconds,omitempty" structs:"timeSpentSeconds,omitempty"` |
406 |
| - ID string `json:"id,omitempty" structs:"id,omitempty"` |
407 |
| - IssueID string `json:"issueId,omitempty" structs:"issueId,omitempty"` |
| 402 | + Self string `json:"self,omitempty" structs:"self,omitempty"` |
| 403 | + Author *User `json:"author,omitempty" structs:"author,omitempty"` |
| 404 | + UpdateAuthor *User `json:"updateAuthor,omitempty" structs:"updateAuthor,omitempty"` |
| 405 | + Comment string `json:"comment,omitempty" structs:"comment,omitempty"` |
| 406 | + Created *Time `json:"created,omitempty" structs:"created,omitempty"` |
| 407 | + Updated *Time `json:"updated,omitempty" structs:"updated,omitempty"` |
| 408 | + Started *Time `json:"started,omitempty" structs:"started,omitempty"` |
| 409 | + TimeSpent string `json:"timeSpent,omitempty" structs:"timeSpent,omitempty"` |
| 410 | + TimeSpentSeconds int `json:"timeSpentSeconds,omitempty" structs:"timeSpentSeconds,omitempty"` |
| 411 | + ID string `json:"id,omitempty" structs:"id,omitempty"` |
| 412 | + IssueID string `json:"issueId,omitempty" structs:"issueId,omitempty"` |
| 413 | + Properties []EntityProperty `json:"properties,omitempty"` |
| 414 | +} |
| 415 | + |
| 416 | +type EntityProperty struct { |
| 417 | + Key string `json:"key"` |
| 418 | + Value interface{} `json:"value"` |
408 | 419 | }
|
409 | 420 |
|
410 | 421 | // TimeTracking represents the timetracking fields of a JIRA issue.
|
@@ -527,6 +538,22 @@ type GetQueryOptions struct {
|
527 | 538 | ProjectKeys string `url:"projectKeys,omitempty"`
|
528 | 539 | }
|
529 | 540 |
|
| 541 | +// GetWorklogsQueryOptions specifies the optional parameters for the Get Worklogs method |
| 542 | +type GetWorklogsQueryOptions struct { |
| 543 | + StartAt int64 `url:"startAt,omitempty"` |
| 544 | + MaxResults int32 `url:"maxResults,omitempty"` |
| 545 | + Expand string `url:"expand,omitempty"` |
| 546 | +} |
| 547 | + |
| 548 | +type AddWorklogQueryOptions struct { |
| 549 | + NotifyUsers bool `url:"notifyUsers,omitempty"` |
| 550 | + AdjustEstimate string `url:"adjustEstimate,omitempty"` |
| 551 | + NewEstimate string `url:"newEstimate,omitempty"` |
| 552 | + ReduceBy string `url:"reduceBy,omitempty"` |
| 553 | + Expand string `url:"expand,omitempty"` |
| 554 | + OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"` |
| 555 | +} |
| 556 | + |
530 | 557 | // CustomFields represents custom fields of JIRA
|
531 | 558 | // This can heavily differ between JIRA instances
|
532 | 559 | type CustomFields map[string]string
|
@@ -626,19 +653,42 @@ func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentNam
|
626 | 653 | // This method is especially important if you need to read all the worklogs, not just the first page.
|
627 | 654 | //
|
628 | 655 | // https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-getIssueWorklog
|
629 |
| -func (s *IssueService) GetWorklogs(issueID string) (*Worklog, *Response, error) { |
| 656 | +func (s *IssueService) GetWorklogs(issueID string, options ...func(*http.Request) error) (*Worklog, *Response, error) { |
630 | 657 | apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID)
|
631 | 658 |
|
632 | 659 | req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
633 | 660 | if err != nil {
|
634 | 661 | return nil, nil, err
|
635 | 662 | }
|
636 | 663 |
|
| 664 | + for _, option := range options { |
| 665 | + err = option(req) |
| 666 | + if err != nil { |
| 667 | + return nil, nil, err |
| 668 | + } |
| 669 | + } |
| 670 | + |
637 | 671 | v := new(Worklog)
|
638 | 672 | resp, err := s.client.Do(req, v)
|
639 | 673 | return v, resp, err
|
640 | 674 | }
|
641 | 675 |
|
| 676 | +// Applies query options to http request. |
| 677 | +// This helper is meant to be used with all "QueryOptions" structs. |
| 678 | +func WithQueryOptions(options interface{}) func(*http.Request) error { |
| 679 | + q, err := query.Values(options) |
| 680 | + if err != nil { |
| 681 | + return func(*http.Request) error { |
| 682 | + return err |
| 683 | + } |
| 684 | + } |
| 685 | + |
| 686 | + return func(r *http.Request) error { |
| 687 | + r.URL.RawQuery = q.Encode() |
| 688 | + return nil |
| 689 | + } |
| 690 | +} |
| 691 | + |
642 | 692 | // Create creates an issue or a sub-task from a JSON representation.
|
643 | 693 | // Creating a sub-task is similar to creating a regular issue, with two important differences:
|
644 | 694 | // The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue.
|
@@ -787,13 +837,20 @@ func (s *IssueService) DeleteComment(issueID, commentID string) error {
|
787 | 837 | // AddWorklogRecord adds a new worklog record to issueID.
|
788 | 838 | //
|
789 | 839 | // https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-worklog-post
|
790 |
| -func (s *IssueService) AddWorklogRecord(issueID string, record *WorklogRecord) (*WorklogRecord, *Response, error) { |
| 840 | +func (s *IssueService) AddWorklogRecord(issueID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { |
791 | 841 | apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID)
|
792 | 842 | req, err := s.client.NewRequest("POST", apiEndpoint, record)
|
793 | 843 | if err != nil {
|
794 | 844 | return nil, nil, err
|
795 | 845 | }
|
796 | 846 |
|
| 847 | + for _, option := range options { |
| 848 | + err = option(req) |
| 849 | + if err != nil { |
| 850 | + return nil, nil, err |
| 851 | + } |
| 852 | + } |
| 853 | + |
797 | 854 | responseRecord := new(WorklogRecord)
|
798 | 855 | resp, err := s.client.Do(req, responseRecord)
|
799 | 856 | if err != nil {
|
|
0 commit comments