Skip to content

Commit

Permalink
Merge pull request #58 from jonathanschmittcs/main
Browse files Browse the repository at this point in the history
Update comment ID type and Time Tracking 2.0
  • Loading branch information
w-haibara authored Jul 2, 2024
2 parents 937912e + ac90cf7 commit 599bb23
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 12 deletions.
2 changes: 2 additions & 0 deletions clickup/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Client struct {
Tasks *TasksService
TaskTemplates *TaskTemplatesService
Teams *TeamsService
TimeTrackings *TimeTrackingsService
SharedHierarchy *SharedHierarchyService
Spaces *SpacesService
Folders *FoldersService
Expand Down Expand Up @@ -138,6 +139,7 @@ func NewClient(httpClient *http.Client, APIKey string) *Client {
c.Tasks = (*TasksService)(&c.common)
c.TaskTemplates = (*TaskTemplatesService)(&c.common)
c.Teams = (*TeamsService)(&c.common)
c.TimeTrackings = (*TimeTrackingsService)(&c.common)
c.SharedHierarchy = (*SharedHierarchyService)(&c.common)
c.Spaces = (*SpacesService)(&c.common)
c.Folders = (*FoldersService)(&c.common)
Expand Down
4 changes: 2 additions & 2 deletions clickup/comments.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type UpdateCommentRequest struct {
}

type CreateCommentResponse struct {
ID string `json:"id"`
ID int `json:"id"`
HistId string `json:"hist_id"`
Date *Date `json:"date"`
}
Expand All @@ -35,7 +35,7 @@ type TaskCommentOptions struct {
}

type Comment struct {
ID string `json:"id"`
ID int `json:"id"`
Comment []CommentInComment `json:"comment"`
CommentText string `json:"comment_text"`
User User `json:"user"`
Expand Down
8 changes: 4 additions & 4 deletions clickup/comments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestCommentsService_CreateTaskComment(t *testing.T) {

fmt.Fprint(w,
`{
"id": "458",
"id": 458,
"hist_id": "26508",
"date": 1568036964079
}`,
Expand All @@ -44,7 +44,7 @@ func TestCommentsService_CreateTaskComment(t *testing.T) {
t.Errorf("Actions.ListArtifacts returned error: %v", err)
}

want := &CreateCommentResponse{ID: "458", HistId: "26508", Date: NewDateWithUnixTime(1568036964079)}
want := &CreateCommentResponse{ID: 458, HistId: "26508", Date: NewDateWithUnixTime(1568036964079)}
if !cmp.Equal(artifacts, want) {
t.Errorf("Actions.ListArtifacts returned %+v, want %+v", artifacts, want)
}
Expand All @@ -60,7 +60,7 @@ func TestCommentsService_GetTaskComments(t *testing.T) {
`{
"comments": [
{
"id": "458",
"id": 458,
"comment": [
{
"text": "Task comment content"
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestCommentsService_GetTaskComments(t *testing.T) {
ProfilePicture: "https://attachments-public.clickup.com/profilePictures/183_abc.jpg",
}
comment := Comment{
ID: "458",
ID: 458,
Comment: []CommentInComment{{Text: "Task comment content"}},
CommentText: "Task comment content",
User: user,
Expand Down
28 changes: 27 additions & 1 deletion clickup/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,31 @@ type TaskRequest struct {
CustomItemId int `json:"custom_item_id,omitempty"` // To create a task that doesn't use a custom task type, either don't include this field in the request body, or send 'null'. To create this task as a Milestone, send a value of 1. To use a custom task type, send the custom task type ID as defined in your Workspace, such as 2.
}

type TaskUpdateRequest struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Assignees TaskAssigneeUpdateRequest `json:"assignees,omitempty"`
Tags []string `json:"tags,omitempty"`
Status string `json:"status,omitempty"`
Priority int `json:"priority,omitempty"`
DueDate *Date `json:"due_date,omitempty"`
DueDateTime bool `json:"due_date_time,omitempty"`
TimeEstimate int `json:"time_estimate,omitempty"`
StartDate *Date `json:"start_date,omitempty"`
StartDateTime bool `json:"start_date_time,omitempty"`
NotifyAll bool `json:"notify_all,omitempty"`
Parent string `json:"parent,omitempty"`
LinksTo string `json:"links_to,omitempty"`
CheckRequiredCustomFields bool `json:"check_required_custom_fields,omitempty"`
CustomFields []CustomFieldInTaskRequest `json:"custom_fields,omitempty"`
CustomItemId int `json:"custom_item_id,omitempty"` // To create a task that doesn't use a custom task type, either don't include this field in the request body, or send 'null'. To create this task as a Milestone, send a value of 1. To use a custom task type, send the custom task type ID as defined in your Workspace, such as 2.
}

type TaskAssigneeUpdateRequest struct {
Add []int `json:"add,omitempty"`
Rem []int `json:"rem,omitempty"`
}

type CustomFieldInTaskRequest struct {
ID string `json:"id"`
Value interface{} `json:"value"`
Expand Down Expand Up @@ -129,6 +154,7 @@ type TasksInStatus struct {
}

type TaskStatus struct {
ID string `json:"id"`
Status string `json:"status"`
Color string `json:"color"`
Type string `json:"type"`
Expand Down Expand Up @@ -282,7 +308,7 @@ func (s *TasksService) CreateTask(ctx context.Context, listID string, tr *TaskRe
}

// FIXME: assignees add/rem
func (s *TasksService) UpdateTask(ctx context.Context, taskID string, opts *GetTaskOptions, tr *TaskRequest) (*Task, *Response, error) {
func (s *TasksService) UpdateTask(ctx context.Context, taskID string, opts *GetTaskOptions, tr *TaskUpdateRequest) (*Task, *Response, error) {
u := fmt.Sprintf("task/%v/", taskID)
u, err := addOptions(u, opts)
if err != nil {
Expand Down
110 changes: 110 additions & 0 deletions clickup/time_tracking.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package clickup

import (
"context"
"fmt"
)

type TimeTrackingsService service

type GetTimeTrackingResponse struct {
Data TimeTrackingData `json:"data"`
}

type CreateTimeTrackingResponse struct {
Data TimeTrackingData `json:"data"`
}

// See https://clickup.com/api/clickupreference/operation/Createatimeentry/
type TimeTrackingRequest struct {
Description string `json:"description,omitempty"`
Tags []TimeTrackingTag `json:"tags,omitempty"`
Start int64 `json:"start"`
End int64 `json:"end,omitempty"`
Stop int64 `json:"stop,omitempty"`
Billable bool `json:"billable,omitempty"`
Duration int32 `json:"duration"`
Assignee int `json:"assignee,omitempty"`
Tid string `json:"tid,omitempty"`
}

type TimeTrackingTag struct {
Name string `json:"name"`
TagBg string `json:"tag_bg"`
TagFg string `json:"tag_fg"`
Creator int `json:"creator"`
}

type TimeTrackingData struct {
ID string `json:"id"`
Wid string `json:"wid"`
User User `json:"user"`
Billable bool `json:"billable"`
Start int `json:"start"`
End string `json:"end"`
Duration int `json:"duration"`
Description string `json:"description"`
Source string `json:"source"`
At int `json:"at"`
IsLocked bool `json:"is_locked"`
TaskLocation TaskLocation `json:"task_location"`
Task Task `json:"task"`
Tags []TimeTrackingTag `json:"tags"`
TaskURL string `json:"task_url"`
}

type TaskLocation struct {
ListID int `json:"list_id"`
FolderID int `json:"folder_id"`
SpaceID int `json:"space_id"`
ListName string `json:"list_name"`
FolderName string `json:"folder_name"`
SpaceName string `json:"space_name"`
}

type CreateTimeTrackingOptions struct {
CustomTaskIDs bool `url:"custom_task_ids,omitempty"`
TeamID int `url:"team_id,omitempty"`
}

func (s *TimeTrackingsService) CreateTimeTracking(ctx context.Context, teamID string, opts *CreateTimeTrackingOptions, ttr *TimeTrackingRequest) (*CreateTimeTrackingResponse, *Response, error) {
u := fmt.Sprintf("team/%s/time_entries", teamID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("POST", u, ttr)
if err != nil {
return nil, nil, err
}

timeTracking := new(CreateTimeTrackingResponse)
resp, err := s.client.Do(ctx, req, timeTracking)
if err != nil {
return nil, resp, err
}

return timeTracking, resp, nil
}

func (s *TimeTrackingsService) GetTimeTracking(ctx context.Context, teamID string, timerID string, opts *CreateTimeTrackingOptions, ttr *TimeTrackingRequest) (*GetTimeTrackingResponse, *Response, error) {
u := fmt.Sprintf("team/%s/time_entries/%s", teamID, timerID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}

req, err := s.client.NewRequest("GET", u, ttr)
if err != nil {
return nil, nil, err
}

getTimeTrackingResponse := new(GetTimeTrackingResponse)
resp, err := s.client.Do(ctx, req, getTimeTrackingResponse)
if err != nil {
return nil, resp, err
}

return getTimeTrackingResponse, resp, nil
}
98 changes: 98 additions & 0 deletions clickup/time_tracking_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package clickup

import (
"context"
"encoding/json"
"fmt"
"net/http"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestTimeTrackingService_CreateTimeTracking(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

input := &TimeTrackingRequest{
Description: "description",
Start: 1719595398,
Duration: 120000,
Assignee: 99999999,
Tid: "9hz",
Billable: true,
}

mux.HandleFunc("/team/123/time_entries", func(w http.ResponseWriter, r *http.Request) {
v := new(TimeTrackingRequest)
json.NewDecoder(r.Body).Decode(v)

testMethod(t, r, "POST")
if !cmp.Equal(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}

fmt.Fprint(w,
`{
"data": {
"id": "4090130922962924695",
"task": {
"id": "9hz",
"name": "Test",
"status": {
"status": "in progress",
"id": "p99999999999_99asdhAS",
"color": "#5f55ee",
"type": "custom",
"orderindex": 1
}
},
"wid": "9999999999",
"user": {
"id": 99999999,
"username": "John",
"email": "john@mail.com",
"color": "#afb42b",
"initials": "J",
"profilePicture": "https://attachments.clickup.com/profilePictures/99999999_tX9.jpg"
},
"billable": true,
"start": 1719595398,
"end": "1719715398",
"duration": 120000,
"description": "description",
"tags": [],
"at": 1719586940375,
"is_locked": false,
"task_location": {}
}
}`,
)
})

ctx := context.Background()
artifacts, _, err := client.TimeTrackings.CreateTimeTracking(ctx, "123", nil, input)
if err != nil {
t.Errorf("Actions.ListArtifacts returned error: %v", err)
}

want := &CreateTimeTrackingResponse{Data: TimeTrackingData{
ID: "4090130922962924695",
Wid: "9999999999",
User: User{ID: 99999999, Username: "John", Email: "john@mail.com", Color: "#afb42b", Initials: "J", ProfilePicture: "https://attachments.clickup.com/profilePictures/99999999_tX9.jpg"},
Billable: true,
Start: 1719595398,
End: "1719715398",
Duration: 120000,
Description: "description",
Tags: []TimeTrackingTag{},
At: 1719586940375,
IsLocked: false,
TaskLocation: TaskLocation{},
Task: Task{ID: "9hz", Name: "Test", Status: TaskStatus{ID: "p99999999999_99asdhAS", Status: "in progress", Color: "#5f55ee", Type: "custom", Orderindex: json.Number("1")}},
}}
if !cmp.Equal(artifacts, want) {
t.Errorf("Actions.ListArtifacts returned %+v, want %+v", artifacts, want)
}

}
8 changes: 4 additions & 4 deletions example/update-duedate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ func main() {
getTask(ctx, client, taskId)

fmt.Println("\nUpdate due date of the task to 2122/01/02 03:04:05:06")
updateTask(ctx, client, taskId, &clickup.TaskRequest{
updateTask(ctx, client, taskId, &clickup.TaskUpdateRequest{
DueDate: clickup.NewDate(
time.Date(2122, 1, 2, 3, 4, 5, 6, time.Now().Location()),
),
})

fmt.Println("\nUpdate the task with empty TaskRequest")
updateTask(ctx, client, taskId, &clickup.TaskRequest{})
updateTask(ctx, client, taskId, &clickup.TaskUpdateRequest{})

fmt.Println("\nRemove task due date with NullDate()")
updateTask(ctx, client, taskId, &clickup.TaskRequest{
updateTask(ctx, client, taskId, &clickup.TaskUpdateRequest{
DueDate: clickup.NullDate(),
})
}
Expand All @@ -50,7 +50,7 @@ func getTask(ctx context.Context, client *clickup.Client, taskID string) {
fmt.Println(task.Name, task.DueDate)
}

func updateTask(ctx context.Context, client *clickup.Client, taskID string, tr *clickup.TaskRequest) {
func updateTask(ctx context.Context, client *clickup.Client, taskID string, tr *clickup.TaskUpdateRequest) {
task, _, err := client.Tasks.UpdateTask(ctx, taskID, &clickup.GetTaskOptions{}, tr)
if err != nil {
log.Fatalln(err)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/raksul/go-clickup

go 1.21.1
go 1.22.3

require (
github.com/google/go-cmp v0.5.8
Expand Down

0 comments on commit 599bb23

Please sign in to comment.