2016-05-11 09:44:12 -04:00
|
|
|
package jkl
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2016-05-26 15:33:47 -04:00
|
|
|
"fmt"
|
2016-05-11 09:44:12 -04:00
|
|
|
"log"
|
2016-12-14 09:55:09 -05:00
|
|
|
"os"
|
2016-05-11 09:44:12 -04:00
|
|
|
"text/template"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Search struct {
|
2016-12-14 09:55:09 -05:00
|
|
|
Issues []*JiraIssue `json:"issues"`
|
2016-05-11 09:44:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type IssueType struct {
|
2016-12-14 09:55:09 -05:00
|
|
|
Name string `json:"name"`
|
|
|
|
|
Fields map[string]FieldSpec
|
2016-05-11 09:44:12 -04:00
|
|
|
}
|
2016-12-14 09:55:09 -05:00
|
|
|
|
|
|
|
|
type FieldSpec struct {
|
|
|
|
|
Name string
|
|
|
|
|
Required bool
|
|
|
|
|
Schema struct {
|
|
|
|
|
Type string
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-11 09:44:12 -04:00
|
|
|
type Project struct {
|
2016-12-14 09:55:09 -05:00
|
|
|
Key string `json:"key,omitempty"`
|
|
|
|
|
IssueTypes []IssueType
|
2016-05-11 09:44:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Author struct {
|
|
|
|
|
Name string
|
|
|
|
|
DisplayName string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Comment struct {
|
2016-12-14 09:55:09 -05:00
|
|
|
Id string
|
2016-05-11 09:44:12 -04:00
|
|
|
Author *Author
|
|
|
|
|
Body string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type CommentColl struct {
|
|
|
|
|
Comments []Comment
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-25 17:00:44 -04:00
|
|
|
type Status struct {
|
|
|
|
|
Name string
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-26 15:33:47 -04:00
|
|
|
type TimeTracking struct {
|
|
|
|
|
OriginalEstimateSeconds int
|
|
|
|
|
RemainingEstimateSeconds int
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-11 09:44:12 -04:00
|
|
|
type Fields struct {
|
2016-05-26 15:33:47 -04:00
|
|
|
*IssueType `json:"issuetype,omitempty"`
|
|
|
|
|
Assignee *Author `json:",omitempty"`
|
|
|
|
|
Project *Project `json:"project,omitempty"`
|
|
|
|
|
Summary string `json:"summary,omitempty"`
|
|
|
|
|
Description string `json:"description,omitempty"`
|
|
|
|
|
Comment *CommentColl `json:"comment,omitempty"`
|
2016-12-14 09:55:09 -05:00
|
|
|
Parent *JiraIssue `json:",omitempty"`
|
2016-05-26 15:33:47 -04:00
|
|
|
Status *Status `json:",omitempty"`
|
|
|
|
|
TimeTracking *TimeTracking `json:"timetracking,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Fields) PrettyRemaining() string {
|
|
|
|
|
return PrettySeconds(f.TimeTracking.RemainingEstimateSeconds)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Fields) PrettyOriginalEstimate() string {
|
|
|
|
|
return PrettySeconds(f.TimeTracking.OriginalEstimateSeconds)
|
2016-05-11 09:44:12 -04:00
|
|
|
}
|
2016-05-26 15:33:47 -04:00
|
|
|
|
|
|
|
|
func PrettySeconds(seconds int) string {
|
|
|
|
|
//This works because it's an integer division.
|
|
|
|
|
days := seconds / 3600 / 8
|
|
|
|
|
hours := seconds/3600 - (days * 8)
|
|
|
|
|
minutes := (seconds - (hours * 3600) - (days * 8 * 3600)) / 60
|
|
|
|
|
seconds = (seconds - (hours * 3600) - (minutes * 60) - (days * 8 * 3600))
|
|
|
|
|
|
|
|
|
|
return fmt.Sprintf("%dd %2dh %2dm %2ds", days, hours, minutes, seconds)
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-14 09:55:09 -05:00
|
|
|
type JiraIssue struct {
|
2016-05-11 09:44:12 -04:00
|
|
|
Key string `json:"key,omitempty"`
|
|
|
|
|
Fields *Fields `json:"fields"`
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-14 09:55:09 -05:00
|
|
|
func (i *JiraIssue) URL() string {
|
|
|
|
|
return os.Getenv("JIRA_ROOT") + "browse/" + i.Key
|
2016-05-31 12:41:46 -04:00
|
|
|
}
|
|
|
|
|
|
2016-12-14 09:55:09 -05:00
|
|
|
func (i *JiraIssue) String() string {
|
2016-05-11 09:44:12 -04:00
|
|
|
var b = bytes.NewBuffer(nil)
|
2017-01-10 10:25:14 -05:00
|
|
|
var tmpl *template.Template = issueTmpl
|
|
|
|
|
if os.Getenv("JKLNOCOLOR") == "true" {
|
|
|
|
|
tmpl = issueTmplNoColor
|
|
|
|
|
}
|
|
|
|
|
err := tmpl.Execute(b, i)
|
2016-05-11 09:44:12 -04:00
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalln(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.String()
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-14 09:55:09 -05:00
|
|
|
var commentTemplate = `{{if .Fields.Comment }}{{$k := .Key}}{{range .Fields.Comment.Comments}}{{.Author.DisplayName}} ({{$k}}#{{.Id}}):
|
2016-05-11 09:44:12 -04:00
|
|
|
-----------------
|
|
|
|
|
{{.Body}}
|
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
|
{{end}}{{end}}`
|
|
|
|
|
|
2016-05-25 17:00:44 -04:00
|
|
|
var issueTmplTxt = "\x1b[1m{{.Key}}\x1b[0m\t{{if .Fields.IssueType}}[{{.Fields.IssueType.Name}}]{{end}}\t{{.Fields.Summary}}\n\n" +
|
2016-05-26 15:33:47 -04:00
|
|
|
"{{if .Fields.Status}}\x1b[1mStatus\x1b[0m:\t {{.Fields.Status.Name}}\n{{end}}" +
|
|
|
|
|
"{{if .Fields.Assignee}}\x1b[1mAssignee:\x1b[0m\t{{.Fields.Assignee.Name}}\n{{end}}\n" +
|
|
|
|
|
"\x1b[1mTime Remaining/Original Estimate:\x1b[0m\t{{.Fields.PrettyRemaining}} / {{.Fields.PrettyOriginalEstimate}}\n\n" +
|
2016-05-11 09:44:12 -04:00
|
|
|
"\x1b[1mDescription:\x1b[0m {{.Fields.Description}} \n\n" +
|
|
|
|
|
"\x1b[1mComments:\x1b[0m\n\n" + commentTemplate
|
|
|
|
|
|
2017-01-10 10:33:38 -05:00
|
|
|
var issueTmplNoColorTxt = "{{.Key}}\t{{if .Fields.IssueType}}[{{.Fields.IssueType.Name}}]{{end}}\t{{.Fields.Summary}}\n\n" +
|
2017-01-10 10:25:14 -05:00
|
|
|
"{{if .Fields.Status}}Status:\t {{.Fields.Status.Name}}\n{{end}}" +
|
|
|
|
|
"{{if .Fields.Assignee}}Assignee:\t{{.Fields.Assignee.Name}}\n{{end}}\n" +
|
|
|
|
|
"Time Remaining/Original Estimate:\t{{.Fields.PrettyRemaining}} / {{.Fields.PrettyOriginalEstimate}}\n\n" +
|
|
|
|
|
"Description: {{.Fields.Description}} \n\n" +
|
|
|
|
|
"Comments:\n\n" + commentTemplate
|
|
|
|
|
|
2016-05-11 09:44:12 -04:00
|
|
|
var issueTmpl = template.Must(template.New("issueTmpl").Parse(issueTmplTxt))
|
2017-01-10 10:32:16 -05:00
|
|
|
var issueTmplNoColor = template.Must(template.New("issueTmplNoColor").Parse(issueTmplNoColorTxt))
|