diff --git a/README.md b/README.md index efe4122..1aaf39a 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,8 @@ If you are new to pull requests, checkout Collaborating on projects using issues - [x] Update Webhook - [x] Delete Webhook - [x] Get Webhooks +- [x] Custom Task Types + - [x] Get Custom Task Types ## License This project is released under the terms of the [MIT license](http://en.wikipedia.org/wiki/MIT_License). diff --git a/clickup/client.go b/clickup/client.go index bdf1799..b18e1e7 100644 --- a/clickup/client.go +++ b/clickup/client.go @@ -49,6 +49,7 @@ type Client struct { Checklists *ChecklistsService Comments *CommentsService CustomFields *CustomFieldsService + CustomTaskTypes *CustomTaskTypesService Dependencies *DependenciesService Goals *GoalsService Tasks *TasksService @@ -131,6 +132,7 @@ func NewClient(httpClient *http.Client, APIKey string) *Client { c.Checklists = (*ChecklistsService)(&c.common) c.Comments = (*CommentsService)(&c.common) c.CustomFields = (*CustomFieldsService)(&c.common) + c.CustomTaskTypes = (*CustomTaskTypesService)(&c.common) c.Dependencies = (*DependenciesService)(&c.common) c.Goals = (*GoalsService)(&c.common) c.Tasks = (*TasksService)(&c.common) diff --git a/clickup/custom_task_types.go b/clickup/custom_task_types.go new file mode 100644 index 0000000..4261b51 --- /dev/null +++ b/clickup/custom_task_types.go @@ -0,0 +1,47 @@ +package clickup + +import ( + "context" + "fmt" +) + +type CustomTaskTypesService service + +// See https://clickup.com/api/clickupreference/operation/GetCustomItems/ +type GetCustomTaskTypesResponse struct { + CustomItems []CustomItem `json:"custom_items,omitempty"` // Array of custom task types. +} + +// See https://clickup.com/api/clickupreference/operation/GetCustomItems/ +type CustomItem struct { + Id int32 `json:"id,omitempty"` // Custom task type ID. + Name string `json:"name,omitempty"` // Custom task type name. + NamePlural string `json:"name_plural,omitempty"` // Custom task type plural name. + Description string `json:"description,omitempty"` // Custom task type description. + + // Not documented in API explorer + Avatar CustomItemAvatar `json:"avatar,omitempty"` // Custom task icon data. +} + +// Not documented in API explorer. Comments are observations. +type CustomItemAvatar struct { + Source string `json:"source,omitempty"` // null (ClickUp Milestone Glyph), fas (Font Awesome Solid), fab (Font Awesome Brands). + Value string `json:"value,omitempty"` // null is for ClickUp Glyphs, e.g., Task and Milestone. +} + +// See https://clickup.com/api/clickupreference/operation/GetCustomItems/ +func (s *CustomTaskTypesService) GetCustomTaskTypes(ctx context.Context, teamId string) ([]CustomItem, *Response, error) { + u := fmt.Sprintf("team/%s/custom_item", teamId) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gcttr := new(GetCustomTaskTypesResponse) + resp, err := s.client.Do(ctx, req, gcttr) + if err != nil { + return nil, resp, err + } + + return gcttr.CustomItems, resp, nil +} diff --git a/clickup/custom_task_types_test.go b/clickup/custom_task_types_test.go new file mode 100644 index 0000000..505808c --- /dev/null +++ b/clickup/custom_task_types_test.go @@ -0,0 +1,33 @@ +package clickup + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestCustomTaskTypesService_GetCustomTaskTypes(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc(("/team/1234/custom_item"), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"custom_items": [{"id": 1300, "name": "Bug", "name_plural": "Bugs", "description": "Custom item type for bugs.", "avatar": { "source": "fas", "value": "bug" }}]}`) + }) + + ctx := context.Background() + customTaskTypes, _, err := client.CustomTaskTypes.GetCustomTaskTypes(ctx, "1234") + if err != nil { + t.Errorf("CustomTaskTypes.GetCustomTaskTypes returned error: %v", err) + } + + want := []CustomItem{ + {Id: 1300, Name: "Bug", NamePlural: "Bugs", Description: "Custom item type for bugs.", Avatar: CustomItemAvatar{Source: "fas", Value: "bug"}}, + } + if !cmp.Equal(customTaskTypes, want) { + t.Errorf("CustomTaskTypes.GetCustomTaskTypes returned %+v, want %+v", customTaskTypes, want) + } +} diff --git a/clickup/tasks.go b/clickup/tasks.go index d6577eb..d05c6e8 100644 --- a/clickup/tasks.go +++ b/clickup/tasks.go @@ -16,6 +16,7 @@ type GetTasksResponse struct { type GetBulkTasksTimeInStatusResponse map[string]TasksInStatus +// See https://clickup.com/api/clickupreference/operation/CreateTask/ type TaskRequest struct { Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` @@ -33,6 +34,7 @@ type TaskRequest struct { 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 CustomFieldInTaskRequest struct { @@ -43,6 +45,7 @@ type CustomFieldInTaskRequest struct { type Task struct { ID string `json:"id"` CustomID string `json:"custom_id"` + CustomItemId int `json:"custom_item_id"` // A null value means this item is a task. A value of 1 is a Milestone. Any other number is a custom task type. Name string `json:"name"` TextContent string `json:"text_content"` Description string `json:"description"` diff --git a/clickup/tasks_test.go b/clickup/tasks_test.go index a2c692c..05a69a2 100644 --- a/clickup/tasks_test.go +++ b/clickup/tasks_test.go @@ -19,6 +19,7 @@ func TestTasksService_GetTask(t *testing.T) { `{ "id": "9hx", "custom_id":null, + "custom_item_id": null, "name": "Task Name", "text_content": "New Task Description", "description": "New Task Description", @@ -80,10 +81,11 @@ func TestTasksService_GetTask(t *testing.T) { } want := &Task{ - ID: "9hx", - Name: "Task Name", - TextContent: "New Task Description", - Description: "New Task Description", + ID: "9hx", + CustomItemId: 0, + Name: "Task Name", + TextContent: "New Task Description", + Description: "New Task Description", Status: TaskStatus{ Status: "in progress", Color: "#d3d3d3",