Skip to content

Commit

Permalink
feat(api): Added GetMemberActivityLog and GetComments (#3)
Browse files Browse the repository at this point in the history
* feat(workspace): Added GetMemberActivityLog

* feat(comment): Added GetComments

* feat(comment): Added GetComments
  • Loading branch information
flc1125 authored Aug 28, 2024
1 parent 5898e10 commit a862e56
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 4 deletions.
36 changes: 36 additions & 0 deletions .testdata/api/comment/get_comments.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"status": 1,
"data": [
{
"Comment": {
"id": "1123402991001033061",
"title": "title1",
"description": "description1",
"author": "author1",
"entry_type": "bug",
"entry_id": "1123402991001037223",
"reply_id": "0",
"root_id": "0",
"created": "2024-08-28 10:06:24",
"modified": "2024-08-28 10:06:24",
"workspace_id": "11112222"
}
},
{
"Comment": {
"id": "1123402991001033060",
"title": "title2",
"description": "description2",
"author": "author2",
"entry_type": "bug_remark",
"entry_id": "1123402991001037173",
"reply_id": "0",
"root_id": "0",
"created": "2024-08-28 09:38:31",
"modified": "2024-08-28 09:38:31",
"workspace_id": "11112222"
}
}
],
"info": "success"
}
128 changes: 128 additions & 0 deletions api_comment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package tapd

import (
"context"
"net/http"
)

// CommentEntryType 评论类型(取值: bug、 bug_remark (流转缺陷时候的评论)、 stories、 tasks 。多个类型间以竖线隔开)
type CommentEntryType string

// CommentEntryType 评论类型(取值: bug、 bug_remark (流转缺陷时候的评论)、 stories、 tasks 。多个类型间以竖线隔开)
const (
CommentEntryTypeBug CommentEntryType = "bug"
CommentEntryTypeBugRemark CommentEntryType = "bug_remark"
CommentEntryTypeStories CommentEntryType = "stories"
CommentEntryTypeTasks CommentEntryType = "tasks"
CommentEntryTypeWiki CommentEntryType = "wiki"
)

// String CommentEntryType to string
func (t CommentEntryType) String() string {
return string(t)
}

// Comment 评论
type Comment struct {
ID string `json:"id,omitempty"` // 评论ID
Title string `json:"title,omitempty"` // 标题
Description string `json:"description,omitempty"` // 内容
Author string `json:"author,omitempty"` // 评论人
EntryType CommentEntryType `json:"entry_type,omitempty"` // 评论类型
EntryID string `json:"entry_id,omitempty"` // 评论所依附的业务对象实体id
ReplyID string `json:"reply_id,omitempty"` // 评论回复的ID
RootID string `json:"root_id,omitempty"` // 根评论ID
Created string `json:"created,omitempty"` // 创建时间
Modified string `json:"modified,omitempty"` // 最后更改时间
WorkspaceID string `json:"workspace_id,omitempty"` // 项目ID
}

// =====================================================================================================================

// CommentService 评论服务
type CommentService struct {
client *Client
}

func NewCommentService(client *Client) *CommentService {
return &CommentService{client}
}

// 添加评论接口

type GetCommentsRequest struct {
// 评论ID 支持多ID查询
ID *ID `url:"id,omitempty"`

// 标题
Title *string `url:"title,omitempty"`

// 内容
Description *string `url:"description,omitempty"`

// 评论人
Author *string `url:"author,omitempty"`

// 评论类型(取值: bug、 bug_remark (流转缺陷时候的评论)、 stories、 tasks 。多个类型间以竖线隔开) 支持枚举查询
EntryType *CommentEntryType `url:"entry_type,omitempty"`

// 评论所依附的业务对象实体id
EntryID *int `url:"entry_id,omitempty"`

// 创建时间 支持时间查询
Created *string `url:"created,omitempty"`

// 最后更改时间 支持时间查询
Modified *string `url:"modified,omitempty"`

// 项目ID
WorkspaceID *int `url:"workspace_id,omitempty"`

// 根评论ID
RootID *int `url:"root_id,omitempty"`

// 评论回复的ID
ReplyID *int `url:"reply_id,omitempty"`

// 设置返回数量限制,默认为30
Limit *int `url:"limit,omitempty"`

// 返回当前数量限制下第N页的数据,默认为1(第一页)
Page *int `url:"page,omitempty"`

// 排序规则,规则:字段名 ASC或者DESC,然后 urlencode 如按创建时间逆序:order=created%20desc
Order *Order `url:"order,omitempty"`

// 设置获取的字段,多个字段间以','逗号隔开
Fields *Fields `url:"fields,omitempty"`
}

// GetComments 获取评论
//
// https://open.tapd.cn/document/api-doc/API%E6%96%87%E6%A1%A3/api_reference/comment/get_comments.html
func (s *CommentService) GetComments(
ctx context.Context, request *GetCommentsRequest, opts ...RequestOption,
) ([]*Comment, *Response, error) {
req, err := s.client.NewRequest(ctx, http.MethodGet, "comments", request, opts)
if err != nil {
return nil, nil, err
}

var items []struct {
Comment *Comment `json:"Comment"`
}
resp, err := s.client.Do(req, &items)
if err != nil {
return nil, resp, err
}

comments := make([]*Comment, 0, len(items))
for _, item := range items {
comments = append(comments, item.Comment)
}

return comments, resp, nil
}

// 获取评论数量
// 更新评论接口
64 changes: 64 additions & 0 deletions api_comment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package tapd

import (
"net/http"
"testing"

"github.com/stretchr/testify/assert"
)

func TestCommentService_GetComments(t *testing.T) {
_, client := createServerClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, "/comments", r.URL.Path)
assert.Equal(t, "111,222", r.URL.Query().Get("id"))
assert.Equal(t, "title", r.URL.Query().Get("title"))
assert.Equal(t, "description", r.URL.Query().Get("description"))
assert.Equal(t, "author", r.URL.Query().Get("author"))
assert.Equal(t, CommentEntryTypeStories.String(), r.URL.Query().Get("entry_type"))
assert.Equal(t, "123", r.URL.Query().Get("entry_id"))
assert.Equal(t, "created", r.URL.Query().Get("created"))
assert.Equal(t, "modified", r.URL.Query().Get("modified"))
assert.Equal(t, "111", r.URL.Query().Get("workspace_id"))
assert.Equal(t, "222", r.URL.Query().Get("root_id"))
assert.Equal(t, "333", r.URL.Query().Get("reply_id"))
assert.Equal(t, "10", r.URL.Query().Get("limit"))
assert.Equal(t, "1", r.URL.Query().Get("page"))
assert.Equal(t, "id desc", r.URL.Query().Get("order"))
assert.Equal(t, "id,title", r.URL.Query().Get("fields"))

_, _ = w.Write(loadData(t, ".testdata/api/comment/get_comments.json"))
}))

comments, _, err := client.CommentService.GetComments(ctx, &GetCommentsRequest{
ID: NewID(111, 222),
Title: Ptr("title"),
Description: Ptr("description"),
Author: Ptr("author"),
EntryType: Ptr(CommentEntryTypeStories),
EntryID: Ptr(123),
Created: Ptr("created"),
Modified: Ptr("modified"),
WorkspaceID: Ptr(111),
RootID: Ptr(222),
ReplyID: Ptr(333),
Limit: Ptr(10),
Page: Ptr(1),
Order: NewOrder("id", OrderDesc),
Fields: NewFields("id", "title"),
})
assert.NoError(t, err)
assert.NotNil(t, comments)
assert.True(t, len(comments) > 0)
assert.Equal(t, "1123402991001033061", comments[0].ID)
assert.Equal(t, "title1", comments[0].Title)
assert.Equal(t, "description1", comments[0].Description)
assert.Equal(t, "author1", comments[0].Author)
assert.Equal(t, CommentEntryTypeBug, comments[0].EntryType)
assert.Equal(t, "1123402991001037223", comments[0].EntryID)
assert.Equal(t, "0", comments[0].ReplyID)
assert.Equal(t, "0", comments[0].RootID)
assert.Equal(t, "2024-08-28 10:06:24", comments[0].Created)
assert.Equal(t, "2024-08-28 10:06:24", comments[0].Modified)
assert.Equal(t, "11112222", comments[0].WorkspaceID)
}
41 changes: 41 additions & 0 deletions api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,44 @@ const (
EntityTypeStory EntityType = "story"
EntityTypeBug EntityType = "bug"
)

// -----------------------------------------------------------------------------
// OperateType is a type for operate types.
//
// 操作类型,默认为所有,可以填写add,delete,download,upload中的一个
// -----------------------------------------------------------------------------

type OperateType string

const (
OperateTypeAdd OperateType = "add"
OperateTypeDelete OperateType = "delete"
OperateTypeDownload OperateType = "download"
OperateTypeUpload OperateType = "upload"
)

// -----------------------------------------------------------------------------
// OperateObject is a type for operate objects.
//
// 操作对象,默认为所有,可以填写attachment,board,bug,document,
// iteration,launch,member_activity_log,
// release,story,task,tcase,testplan,wiki中的一个
// -----------------------------------------------------------------------------

type OperateObject string

const (
OperateObjectAttachment OperateObject = "attachment"
OperateObjectBoard OperateObject = "board"
OperateObjectBug OperateObject = "bug"
OperateObjectDocument OperateObject = "document"
OperateObjectIteration OperateObject = "iteration"
OperateObjectLaunch OperateObject = "launch"
OperateObjectMemberActivityLog OperateObject = "member_activity_log"
OperateObjectRelease OperateObject = "release"
OperateObjectStory OperateObject = "story"
OperateObjectTask OperateObject = "task"
OperateObjectTestCase OperateObject = "tcase"
OperateObjectTestPlan OperateObject = "testplan"
OperateObjectWiki OperateObject = "wiki"
)
121 changes: 121 additions & 0 deletions api_workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package tapd

import (
"context"
"net/http"
)

type WorkspaceService struct {
client *Client
}

func NewWorkspaceService(client *Client) *WorkspaceService {
return &WorkspaceService{client}
}

// 获取子项目信息
// 获取项目信息
// 获取指定项目成员
// 添加项目成员
// 获取公司项目列表
// 获取用户组ID对照关系
// 获取用户参与的项目列表
// 获取项目成员列表
// 获取项目自定义字段
// 更新项目信息
// 获取项目文档

type GetMemberActivityLogRequest struct {
// [必须]项目 id 为公司id则查询所有项目
WorkspaceID *int `url:"workspace_id,omitempty"`

// [可选]为1则仅返回公司级活动日志 要求workspace_id=公司id & company_only=1
CompanyOnly *int `url:"company_only,omitempty"`

// [可选]设置返回数量限制,默认为20
Limit *int `url:"limit,omitempty"`

// [可选]返回当前数量限制下第N页的数据,默认为1(第一页)
Page *int `url:"page,omitempty"`

// [可选]起始时间,精确到分钟,格式为Y-m-d H:i 只能查最近半年内的数据
StartTime *string `url:"start_time,omitempty"`

// [可选]终止时间,精确到分钟,格式为Y-m-d H:i 只能查最近半年内的数据
EndTime *string `url:"end_time,omitempty"`

// [可选]操作人昵称
Operator *string `url:"operator,omitempty"`

// [可选]操作类型,默认为所有,可以填写add,delete,download,upload中的一个
OperateType *OperateType `url:"operate_type,omitempty"`

// [可选]操作对象,默认为所有,可以填写attachment,board,bug,document,iteration,
// launch,member_activity_log,release,story,task,tcase,testplan,wiki中的一个
OperatorObject *OperateObject `url:"operator_object,omitempty"`

// [可选]请求IP条件,严格匹配
IP *string `url:"ip,omitempty"`
}

type MemberActivityLog struct {
ID string `json:"id,omitempty"`
Action string `json:"action,omitempty"`
Created string `json:"created,omitempty"`
Creator string `json:"creator,omitempty"`
ProjectName string `json:"project_name,omitempty"`
OperateType OperateType `json:"operate_type,omitempty"`
OperateObject OperateObject `json:"operate_object,omitempty"`
Title string `json:"title,omitempty"`
URL string `json:"url,omitempty"`
IP string `json:"ip,omitempty"`
UA string `json:"ua,omitempty"`
}

type GetMemberActivityLogResponse struct {
PerPage string `json:"perPage"`
TotalItems int `json:"totalItems"`
CurrentPage string `json:"currentPage"`
Records []*MemberActivityLog `json:"records"`
OperateTypes struct {
Add string `json:"add"`
Delete string `json:"delete"`
Upload string `json:"upload"`
Download string `json:"download"`
} `json:"operate_types"`
OperateObjects struct {
Board string `json:"board"`
Story string `json:"story"`
Bug string `json:"bug"`
Iteration string `json:"iteration"`
Wiki string `json:"wiki"`
Document string `json:"document"`
Attachment string `json:"attachment"`
Task string `json:"task"`
Tcase string `json:"tcase"`
Testplan string `json:"testplan"`
Launch string `json:"launch"`
Release string `json:"release"`
MemberActivityLog string `json:"member_activity_log"`
} `json:"operate_objects"`
}

// GetMemberActivityLog 获取成员活动日志
//
// https://open.tapd.cn/document/api-doc/API%E6%96%87%E6%A1%A3/api_reference/workspace/member_activity_log.html
func (s *WorkspaceService) GetMemberActivityLog(
ctx context.Context, request *GetMemberActivityLogRequest, opts ...RequestOption,
) (*GetMemberActivityLogResponse, *Response, error) {
req, err := s.client.NewRequest(ctx, http.MethodGet, "workspaces/member_activity_log", request, opts)
if err != nil {
return nil, nil, err
}

response := new(GetMemberActivityLogResponse)
resp, err := s.client.Do(req, &response)
if err != nil {
return nil, resp, err
}

return response, resp, nil
}
Loading

0 comments on commit a862e56

Please sign in to comment.