Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Commit

Permalink
chore: improve list issue UX
Browse files Browse the repository at this point in the history
  • Loading branch information
YCK1130 committed Jul 24, 2024
1 parent 2817bb1 commit bbcdf02
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 52 deletions.
38 changes: 19 additions & 19 deletions application/jira/v0/boards.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,9 @@ func (jiraClient *Client) listBoardsTask(ctx context.Context, props *structpb.St
}

func (jiraClient *Client) listBoards(_ context.Context, opt *ListBoardsInput) (*ListBoardsResp, error) {
var debug DebugSession
debug.SessionStart("listBoards", StaticVerboseLevel)
defer debug.SessionEnd()

apiEndpoint := "rest/agile/1.0/board"

req := jiraClient.Client.R().SetResult(&ListBoardsResp{})
debug.AddMapMessage("opt", *opt)
err := addQueryOptions(req, *opt)
if err != nil {
return nil, err
Expand All @@ -80,30 +75,35 @@ func (jiraClient *Client) listBoards(_ context.Context, opt *ListBoardsInput) (*
if err != nil {
return nil, err
}
debug.AddMessage("GET", apiEndpoint)
debug.AddMapMessage("QueryParam", resp.Request.QueryParam)
debug.AddMessage("Status", resp.Status())
boards := resp.Result().(*ListBoardsResp)
return boards, err
}

func (jiraClient *Client) getBoard(_ context.Context, boardID int) (*Board, error) {
var debug DebugSession
debug.SessionStart("getBoard", StaticVerboseLevel)
defer debug.SessionEnd()
type GetBoardResp struct {
Location struct {
DisplayName string `json:"displayName"`
Name string `json:"name"`
ProjectKey string `json:"projectKey"`
ProjectID int `json:"projectId"`
ProjectName string `json:"projectName"`
ProjectTypeKey string `json:"projectTypeKey"`
UserAccountID string `json:"userAccountId"`
UserID string `json:"userId"`
} `json:"location"`
Board
}

func (jiraClient *Client) getBoard(_ context.Context, boardID int) (*GetBoardResp, error) {
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID)
req := jiraClient.Client.R().SetResult(&Board{})
resp, err := req.Get(apiEndpoint)

req := jiraClient.Client.R().SetResult(&GetBoardResp{})
resp, err := req.Get(apiEndpoint)
if err != nil {
return nil, fmt.Errorf(
err.Error(), errmsg.Message(err),
)
}
debug.AddMessage("GET", apiEndpoint)
debug.AddMapMessage("QueryParam", resp.Request.QueryParam)
debug.AddMessage("Status", resp.Status())
board := resp.Result().(*Board)
return board, err
result := resp.Result().(*GetBoardResp)

return result, err
}
46 changes: 36 additions & 10 deletions application/jira/v0/component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "All",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand Down Expand Up @@ -235,7 +235,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "Epics only",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand Down Expand Up @@ -271,7 +271,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "In backlog only",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand Down Expand Up @@ -307,7 +307,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "Issues without epic assigned",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand Down Expand Up @@ -343,7 +343,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "Issues of an epic",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand All @@ -362,7 +362,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "Issues of an epic(long query)",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand All @@ -381,7 +381,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "Issues of a sprint",
input: ListIssuesInput{
BoardID: 1,
BoardName: "KAN",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand All @@ -400,7 +400,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "Standard Issues",
input: ListIssuesInput{
BoardID: 1,
BoardName: "TST",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand All @@ -418,7 +418,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "ok",
name: "JQL",
input: ListIssuesInput{
BoardID: 1,
BoardName: "TST",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand All @@ -437,7 +437,7 @@ func TestComponent_ListIssuesTask(t *testing.T) {
_type: "nok",
name: "invalid range",
input: ListIssuesInput{
BoardID: 1,
BoardName: "TST",
MaxResults: 10,
StartAt: 0,
Range: Range{
Expand Down Expand Up @@ -493,6 +493,32 @@ func TestComponent_ListSprintsTask(t *testing.T) {
taskTesting(testcases, taskListSprints, t)
}

func TestAuth_nok(t *testing.T) {
c := qt.New(t)
bc := base.Component{Logger: zap.NewNop()}
connector := Init(bc)
c.Run("nok-empty token", func(c *qt.C) {
setup, err := structpb.NewStruct(map[string]any{
"token": "",
"email": email,
"base-url": "url",
})
c.Assert(err, qt.IsNil)
_, err = connector.CreateExecution(nil, setup, "invalid")
c.Assert(err, qt.ErrorMatches, "token not provided")
})
c.Run("nok-empty email", func(c *qt.C) {
setup, err := structpb.NewStruct(map[string]any{
"token": token,
"email": "",
"base-url": "url",
})
c.Assert(err, qt.IsNil)
_, err = connector.CreateExecution(nil, setup, "invalid")
c.Assert(err, qt.ErrorMatches, "email not provided")
})
}

func taskTesting[inType any, outType any](testcases []TaskCase[inType, outType], task string, t *testing.T) {
c := qt.New(t)
ctx := context.Background()
Expand Down
20 changes: 10 additions & 10 deletions application/jira/v0/config/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,25 +359,25 @@
"description": "List issues in Jira",
"instillUIOrder": 0,
"instillEditOnNodeFields": [
"board-id",
"board-name",
"range"
],
"properties": {
"board-id": {
"title": "Board ID",
"description": "The ID of the board",
"instillShortDescription": "The ID of the board",
"board-name": {
"title": "Board Name",
"description": "The name of the board",
"instillShortDescription": "The name of the board",
"instillUIOrder": 0,
"instillFormat": "integer",
"instillFormat": "string",
"instillAcceptFormats": [
"integer"
"string"
],
"instillUpstreamTypes": [
"value",
"reference",
"template"
],
"type": "integer"
"type": "string"
},
"range": {
"title": "Range",
Expand Down Expand Up @@ -546,7 +546,7 @@
},
"jql": {
"title": "JQL",
"description": "The JQL query. For example, `project = JRA AND status = Done`. For more information, see [Advanced searching reference](https://support.atlassian.com/jira-software-cloud/docs/what-is-advanced-search-in-jira-cloud/)",
"description": "The JQL query. For example, `type = \"Task\" AND status = \"Done\"`. For more information, see [Advanced searching](https://support.atlassian.com/jira-software-cloud/docs/what-is-advanced-search-in-jira-cloud/)",
"instillShortDescription": "The JQL query",
"instillUIOrder": 10,
"instillFormat": "string",
Expand Down Expand Up @@ -584,7 +584,7 @@
}
},
"required": [
"board-id"
"board-name"
],
"title": "Input",
"type": "object"
Expand Down
47 changes: 34 additions & 13 deletions application/jira/v0/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,12 @@ type Range struct {
SprintName string `json:"sprint-name,omitempty"`
JQL string `json:"jql,omitempty"`
}

type ListIssuesInput struct {
BoardID int `json:"board-id,omitempty" api:"boardId"`
MaxResults int `json:"max-results,omitempty" api:"maxResults"`
StartAt int `json:"start-at,omitempty" api:"startAt"`
Range Range `json:"range,omitempty"`
BoardName string `json:"board-name,omitempty" api:"boardName"`
MaxResults int `json:"max-results,omitempty" api:"maxResults"`
StartAt int `json:"start-at,omitempty" api:"startAt"`
Range Range `json:"range,omitempty"`
}

type ListIssuesResp struct {
Expand All @@ -137,7 +138,7 @@ type ListIssuesOutput struct {

func (jiraClient *Client) listIssuesTask(ctx context.Context, props *structpb.Struct) (*structpb.Struct, error) {
var debug DebugSession
debug.SessionStart("listIssuesTask", StaticVerboseLevel)
debug.SessionStart("listIssuesTask", DevelopVerboseLevel)
defer debug.SessionEnd()

debug.AddMapMessage("props", props)
Expand All @@ -149,14 +150,34 @@ func (jiraClient *Client) listIssuesTask(ctx context.Context, props *structpb.St
if err := base.ConvertFromStructpb(props, &opt); err != nil {
return nil, err
}
debug.AddMapMessage("ListIssuesInput", opt)
board, err := jiraClient.getBoard(ctx, opt.BoardID)

boards, err := jiraClient.listBoards(ctx, &ListBoardsInput{Name: opt.BoardName})
if err != nil {
return nil, err
}
if len(boards.Values) == 0 {
return nil, errmsg.AddMessage(
fmt.Errorf("board not found"),
fmt.Sprintf("board with name %s not found", opt.BoardName),
)
} else if len(boards.Values) > 1 {
return nil, errmsg.AddMessage(
fmt.Errorf("multiple boards found"),
fmt.Sprintf("multiple boards are found with the partial name \"%s\". Please provide a more specific name", opt.BoardName),
)
}
debug.AddMapMessage("boards", boards)
board := boards.Values[0]

boardDetails, err := jiraClient.getBoard(ctx, board.ID)
if err != nil {
return nil, err
}
debug.AddMapMessage("board", *board)
boardKey := strings.Split(board.Name, " ")[0]
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d", opt.BoardID)
projectKey := boardDetails.Location.ProjectKey
if projectKey == "" {
projectKey = strings.Split(board.Name, "-")[0]
}
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d", board.ID)
switch opt.Range.Range {
case "All":
// https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-issue-get
Expand All @@ -167,11 +188,11 @@ func (jiraClient *Client) listIssuesTask(ctx context.Context, props *structpb.St
case "Issues of an epic":
// API not working: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-epic-epicid-issue-get
// use JQL instead
jql = fmt.Sprintf("project=\"%s\" AND parent=\"%s\"", boardKey, opt.Range.EpicKey)
jql = fmt.Sprintf("project=\"%s\" AND parent=\"%s\"", projectKey, opt.Range.EpicKey)
case "Issues of a sprint":
// API not working: https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-sprint-sprintid-issue-get
// use JQL instead
jql = fmt.Sprintf("project=\"%s\" AND sprint=\"%s\"", boardKey, opt.Range.SprintName)
jql = fmt.Sprintf("project=\"%s\" AND sprint=\"%s\"", projectKey, opt.Range.SprintName)
case "In backlog only":
// https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-rest-agile-1-0-board-boardid-backlog-get
apiEndpoint = apiEndpoint + "/backlog"
Expand All @@ -180,7 +201,7 @@ func (jiraClient *Client) listIssuesTask(ctx context.Context, props *structpb.St
apiEndpoint = apiEndpoint + "/epic/none/issue"
case "Standard Issues":
// https://support.atlassian.com/jira-cloud-administration/docs/what-are-issue-types/
jql = fmt.Sprintf("project=\"%s\" AND issuetype not in (Epic, subtask)", boardKey)
jql = fmt.Sprintf("project=\"%s\" AND issuetype not in (Epic, subtask)", projectKey)
case "JQL query":
jql = opt.Range.JQL
default:
Expand Down

0 comments on commit bbcdf02

Please sign in to comment.