Skip to content

Commit

Permalink
feat(718): view issue: json output option
Browse files Browse the repository at this point in the history
  • Loading branch information
Drofff committed Mar 14, 2024
1 parent 170c129 commit 347a9d7
Show file tree
Hide file tree
Showing 3 changed files with 463 additions and 128 deletions.
15 changes: 14 additions & 1 deletion internal/cmd/issue/view/view.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package view

import (
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"

Expand All @@ -16,7 +18,10 @@ const (
examples = `$ jira issue view ISSUE-1
# Show 5 recent comments when viewing the issue
$ jira issue view ISSUE-1 --comments 5`
$ jira issue view ISSUE-1 --comments 5
# Print the contents of the issue as plain JSON
$ jira issue view ISSUE-1 --json`
)

// NewCmdView is a view command.
Expand All @@ -36,6 +41,7 @@ func NewCmdView() *cobra.Command {

cmd.Flags().Uint("comments", 1, "Show N comments")
cmd.Flags().Bool("plain", false, "Display output in plain mode")
cmd.Flags().Bool("json", false, "Print the issue contents as JSON. Set this flag when you want to process the output with a program")

return &cmd
}
Expand All @@ -60,11 +66,18 @@ func view(cmd *cobra.Command, args []string) {
plain, err := cmd.Flags().GetBool("plain")
cmdutil.ExitIfError(err)

printJson, err := cmd.Flags().GetBool("json")
cmdutil.ExitIfError(err)

v := tuiView.Issue{
Server: viper.GetString("server"),
Data: iss,
Display: tuiView.DisplayFormat{Plain: plain},
Options: tuiView.IssueOption{NumComments: comments},
}
if printJson {
cmdutil.ExitIfError(v.RenderJSON(os.Stdout))
return
}
cmdutil.ExitIfError(v.Render())
}
147 changes: 147 additions & 0 deletions internal/view/issue.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package view

import (
"encoding/json"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -457,3 +458,149 @@ func (i Issue) renderPlain(w io.Writer) error {
_, err = fmt.Fprint(w, out)
return err
}

// printableIssue is a jira.Issue that can be marshaled into a format of choice f.e. JSON and
// printed for other programs to consume.
type printableIssue struct {
Key string `json:"key"`
Fields printableIssueFields `json:"fields"`
}

type printableIssueFields struct {
Summary string `json:"summary"`
Description interface{} `json:"description"`
Labels []string `json:"labels"`
Resolution *struct {
Name string `json:"name"`
} `json:"resolution"`
IssueType *jira.IssueType `json:"issueType"`
Parent *struct {
Key string `json:"key"`
} `json:"parent,omitempty"`
Assignee *struct {
Name string `json:"displayName"`
} `json:"assignee"`
Priority *struct {
Name string `json:"name"`
} `json:"priority"`
Reporter *struct {
Name string `json:"displayName"`
} `json:"reporter"`
Watches struct {
IsWatching bool `json:"isWatching"`
WatchCount int `json:"watchCount"`
} `json:"watches"`
Status *struct {
Name string `json:"name"`
} `json:"status"`
Components []struct {
Name string `json:"name"`
} `json:"components"`
FixVersions []struct {
Name string `json:"name"`
} `json:"fixVersions"`
AffectsVersions []struct {
Name string `json:"name"`
} `json:"versions"`
Comment struct {
Comments []struct {
ID string `json:"id"`
Author jira.User `json:"author"`
Body interface{} `json:"body"`
Created string `json:"created"`
} `json:"comments"`
Total int `json:"total"`
} `json:"comment"`
Subtasks []string
IssueLinks []printableIssueLink `json:"issueLinks"`
Created string `json:"created"`
Updated string `json:"updated"`
}

type printableIssueLink struct {
ID string `json:"id"`
LinkType struct {
Name string `json:"name"`
Inward string `json:"inward"`
Outward string `json:"outward"`
} `json:"type"`
InwardIssue string `json:"inwardIssue,omitempty"`
OutwardIssue string `json:"outwardIssue,omitempty"`
}

func toPrintableIssue(issue jira.Issue) printableIssue {
pi := printableIssue{
Key: issue.Key,
Fields: printableIssueFields{
Summary: issue.Fields.Summary,
Description: issue.Fields.Description,
Labels: issue.Fields.Labels,
Parent: issue.Fields.Parent,
Watches: issue.Fields.Watches,
Components: issue.Fields.Components,
FixVersions: issue.Fields.FixVersions,
AffectsVersions: issue.Fields.AffectsVersions,
Comment: issue.Fields.Comment,
Created: issue.Fields.Created,
Updated: issue.Fields.Updated,
},
}
if issue.Fields.Resolution.Name != "" {
pi.Fields.Resolution = &issue.Fields.Resolution
}
if issue.Fields.IssueType.ID != "" || issue.Fields.IssueType.Name != "" {
pi.Fields.IssueType = &issue.Fields.IssueType
}
if issue.Fields.Assignee.Name != "" {
pi.Fields.Assignee = &issue.Fields.Assignee
}
if issue.Fields.Priority.Name != "" {
pi.Fields.Priority = &issue.Fields.Priority
}
if issue.Fields.Reporter.Name != "" {
pi.Fields.Reporter = &issue.Fields.Reporter
}
if issue.Fields.Status.Name != "" {
pi.Fields.Status = &issue.Fields.Status
}

if len(issue.Fields.Subtasks) > 0 {
var subKeys []string
for _, sub := range issue.Fields.Subtasks {
subKeys = append(subKeys, sub.Key)
}
pi.Fields.Subtasks = subKeys
}
if len(issue.Fields.IssueLinks) > 0 {
var piLinks []printableIssueLink
for _, il := range issue.Fields.IssueLinks {
pil := printableIssueLink{
ID: il.ID,
LinkType: il.LinkType,
}
if il.InwardIssue != nil {
pil.InwardIssue = il.InwardIssue.Key
}
if il.OutwardIssue != nil {
pil.OutwardIssue = il.OutwardIssue.Key
}
piLinks = append(piLinks, pil)
}
pi.Fields.IssueLinks = piLinks
}
return pi
}

// RenderJSON prints the issue data as a plain JSON.
func (i Issue) RenderJSON(w io.Writer) error {
if i.Data == nil {
return fmt.Errorf("no issue data available")
}
pi := toPrintableIssue(*i.Data)

err := json.NewEncoder(w).Encode(pi)
if err != nil {
return fmt.Errorf("json encode: %w", err)
}
return nil
}
Loading

0 comments on commit 347a9d7

Please sign in to comment.