Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
shuntaka9576 committed Mar 19, 2024
1 parent 286f8db commit 8240e36
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 18 deletions.
33 changes: 33 additions & 0 deletions cli/ls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cli

import (
"encoding/json"
"fmt"
"os"

ghp2 "github.com/shuntaka9576/gh-p2"
)

type LsParamas struct {
ProjectId string
Field string
}

func (c *Cmd) Ls(params *LsParamas) error {
res, err := c.Client.GetProjectItems(&ghp2.GetProjectItemsParams{
ProjectId: params.ProjectId,
})

if err != nil {
return err
}

json, err := json.Marshal(res)
if err != nil {
return err
}

fmt.Fprintf(os.Stdout, "%s\n", json)

return nil
}
65 changes: 47 additions & 18 deletions cmd/p2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ var CLI struct {
Draft bool `short:"d" name:"draft" help:"Due to GitHub specifications, the --label and --repo options cannot be used together."`
Assignees []string `short:"a" name:"assignees" help:"Specify the GitHub account ID to be assigned."`
} `cmd:"" help:"Option to create an issue or draft issue directly in Project V2."`
Ls struct {
ProjectTitle string `short:"p" required:"" name:"project-title" help:"Specify the title of ProjectV2."`
Field string `short:"f" name:"Specify ProjectV2 custom fields in the format {keyName}:{valueName}. e.g. Status:Todo, Point:3, date:2022-08-29."`
} `cmd:"" help:"Option to view an issue or draft issue in Project V2. Support only SingleSelectValue."`
}

func main() {
Expand Down Expand Up @@ -58,28 +62,29 @@ func main() {
}

var projectId string
for _, project := range res.Projects() {
if project.Title == CLI.Create.ProjectTitle {
projectId = project.Id
}
}

if projectId == "" {
fmt.Fprintf(os.Stderr, "Not found project name: %s\n", CLI.Create.ProjectTitle)
if len(res.Projects()) > 0 {
fmt.Fprintf(os.Stderr, "The following project names are available and can be specified in the project-title(-p) flag.\n")
for _, project := range res.Projects() {
fmt.Fprintf(os.Stderr, " * %s\n", project.Title)
switch kontext.Command() {
case "create":
for _, project := range res.Projects() {
if project.Title == CLI.Create.ProjectTitle {
projectId = project.Id
}
} else {
fmt.Fprintf(os.Stderr, "There are no ProjectV2 resources available for this organization or user.\n")
}

os.Exit(1)
}
if projectId == "" {
fmt.Fprintf(os.Stderr, "Not found project name: %s\n", CLI.Create.ProjectTitle)
if len(res.Projects()) > 0 {
fmt.Fprintf(os.Stderr, "The following project names are available and can be specified in the project-title(-p) flag.\n")
for _, project := range res.Projects() {
fmt.Fprintf(os.Stderr, " * %s\n", project.Title)
}
} else {
fmt.Fprintf(os.Stderr, "There are no ProjectV2 resources available for this organization or user.\n")
}

os.Exit(1)
}

switch kontext.Command() {
case "create":
err = c.Create(&cli.CreateParamas{
ProjectId: projectId,
Title: CLI.Create.Title,
Expand All @@ -90,8 +95,32 @@ func main() {
Draft: CLI.Create.Draft,
Assignees: CLI.Create.Assignees,
})
}
case "ls":
for _, project := range res.Projects() {
if project.Title == CLI.Ls.ProjectTitle {
projectId = project.Id
}
}

if projectId == "" {
fmt.Fprintf(os.Stderr, "Not found project name: %s\n", CLI.Create.ProjectTitle)
if len(res.Projects()) > 0 {
fmt.Fprintf(os.Stderr, "The following project names are available and can be specified in the project-title(-p) flag.\n")
for _, project := range res.Projects() {
fmt.Fprintf(os.Stderr, " * %s\n", project.Title)
}
} else {
fmt.Fprintf(os.Stderr, "There are no ProjectV2 resources available for this organization or user.\n")
}

os.Exit(1)
}

err = c.Ls(&cli.LsParamas{
ProjectId: projectId,
Field: CLI.Ls.Field,
})
}
if err != nil {
fmt.Fprintf(os.Stderr, "%s", err)

Expand Down
24 changes: 24 additions & 0 deletions gh/p2_items.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gh

import (
"github.com/cli/go-gh"
)

type GetProjectItemsParams struct {
ProjectId string
Cursor *string
}

func GetProjectItems(params *GetProjectItemsParams) (*[]byte, error) {
ghql := "query=" + GetProjectItemsQuery(params.ProjectId, params.Cursor)
args := append(graphqlArgs, ghql)

stdOut, _, err := gh.Exec(args...)
if err != nil {
return nil, err
}

bytes := stdOut.Bytes()

return &bytes, nil
}
54 changes: 54 additions & 0 deletions gh/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,60 @@ func GetListQuery(clientType ClientType, name string) string {
return query
}

func GetProjectItemsQuery(projectId string, cursor *string) string {
var afterClause string
if cursor != nil {
afterClause = fmt.Sprintf(`, after: "%s"`, *cursor)
}

query := fmt.Sprintf(`query{
node(id: "%s") {
... on ProjectV2 {
title
items(first: 20%s) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
createdAt
updatedAt
isArchived
content {
__typename
}
fieldValues(first: 20) {
nodes {
__typename
... on ProjectV2ItemFieldSingleSelectValue {
name
optionId
field {
... on ProjectV2SingleSelectField {
id
name
}
}
}
}
}
content {
... on Issue {
title
state
url
}
}
}
}
}
}
}`, projectId, afterClause)

return query
}

func GetProjectFieldsQuery(projectId string) string {
query := fmt.Sprintf(`query{
node(id: "%s") {
Expand Down
7 changes: 7 additions & 0 deletions gh/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,10 @@ const (
TITLE PROJECT_V2_DATA_TYPE = "TITLE"
TRACKS PROJECT_V2_DATA_TYPE = "TRACKS"
)

type ITEM_TYPE = string

const (
ISSUE ITEM_TYPE = "ISSUE"
DRAFT_ISSUE ITEM_TYPE = "DRAFT_ISSUE"
)
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ require (
github.com/cli/safeexec v1.0.0 // indirect
github.com/cli/shurcooL-graphql v0.0.2 // indirect
github.com/henvic/httpretty v0.0.6 // indirect
github.com/k0kubun/pp v3.0.1+incompatible // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/muesli/termenv v0.12.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs=
github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo=
github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand Down
121 changes: 121 additions & 0 deletions p2_items.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package ghp2

import (
"encoding/json"

"github.com/shuntaka9576/gh-p2/gh"
)

type GetProjectItemsParams struct {
ProjectId string
}

type GetProjectItemsGhRes struct {
Data struct {
Node struct {
Title string `json:"title"`
Items struct {
PageInfo struct {
HasNextPage bool `json:"hasNextPage"`
EndCursor string `json:"endCursor"`
} `json:"pageInfo"`
Nodes []struct {
ID string `json:"id"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
IsArchived bool `json:"isArchived"`
Content struct {
TypeName string `json:"__typename,omitempty"`
Title string `json:"title,omitempty"`
State string `json:"state,omitempty"`
URL string `json:"url,omitempty"`
Body string `json:"body,omitempty"`
} `json:"content"`
FieldValues struct {
Nodes []struct {
TypeName string `json:"__typename,omitempty"`
Name string `json:"name,omitempty"`
Filed struct {
Name string `json:"name,omitempty"`
} `json:"field"`
} `json:"nodes"`
} `json:"fieldValues"`
} `json:"nodes"`
} `json:"items"`
} `json:"node"`
} `json:"data"`
}

type GetProjectItemsRes struct {
Title string `json:"title"`
IssueItems []IssueItem `json:"items"`
}

type IssueItem struct {
Title string `json:"title"`
SingleSelectValues map[string]string `json:"singleFiledValues"`
ItemType gh.ITEM_TYPE `json:"type"`
Body string `json:"body"`
}

func (c *Client) GetProjectItems(params *GetProjectItemsParams) (*GetProjectItemsRes, error) {
var cursor *string
res := &GetProjectItemsRes{}

for {
payload, err := gh.GetProjectItems(&gh.GetProjectItemsParams{
ProjectId: params.ProjectId,
Cursor: cursor,
})
if err != nil {
return nil, err
}

parsed := &GetProjectItemsGhRes{}
err = json.Unmarshal(*payload, parsed)
if err != nil {
return nil, err
}

if res.Title == "" { // Set the title only once
res.Title = parsed.Data.Node.Title
}

for _, node := range parsed.Data.Node.Items.Nodes {
if node.IsArchived {
continue
}

item := IssueItem{
Title: node.Content.Title,
Body: node.Content.Body,
}

switch node.Content.TypeName {
case "DraftIssue":
item.ItemType = gh.DRAFT_ISSUE
case "Issue":
item.ItemType = gh.ISSUE
default:
return nil, err
}

singleSelectValues := map[string]string{}
for _, fieldValue := range node.FieldValues.Nodes {
if fieldValue.TypeName == "ProjectV2ItemFieldSingleSelectValue" {
singleSelectValues[fieldValue.Filed.Name] = fieldValue.Name
}
}
item.SingleSelectValues = singleSelectValues

res.IssueItems = append(res.IssueItems, item)
}

if !parsed.Data.Node.Items.PageInfo.HasNextPage {
break
}
cursor = &parsed.Data.Node.Items.PageInfo.EndCursor
}

return res, nil
}

0 comments on commit 8240e36

Please sign in to comment.