jirashell/actions.go
Sebastiaan de Schaetzen d71e38f5db
All checks were successful
/ build (push) Successful in 22s
Fix #5
2024-10-18 11:19:35 +02:00

409 lines
9.1 KiB
Go

package main
import (
"context"
"fmt"
jira "github.com/andygrunwald/go-jira/v2/cloud"
"github.com/charmbracelet/huh"
"github.com/fatih/color"
"github.com/spf13/viper"
"os"
"strconv"
)
var red = color.New(color.FgRed).SprintFunc()
var yellow = color.New(color.FgYellow).SprintFunc()
var blue = color.New(color.FgBlue).SprintFunc()
var green = color.New(color.FgGreen).SprintFunc()
func printError(msg string, err error) {
if err == nil {
fmt.Printf("Error: %s\n", msg)
} else {
fmt.Printf("Error: %s: %v\n", msg, err)
}
}
func ActionExit(_ []string) {
promptRunner.Close()
os.Exit(0)
}
func ActionLogout(_ []string) {
viper.Set("token", nil)
err := viper.WriteConfig()
if err != nil {
printError("Failed to write config", err)
}
ensureLoggedIn()
}
func ActionListProjects(_ []string) {
projects, err := GetAllProjects()
if err != nil {
printError("Failed to list projects", err)
return
}
for _, project := range *projects {
fmt.Printf(" - %s: %s\n", project.Key, project.Name)
}
}
func ActionUseProject(args []string) {
var projectId string
if len(args) == 0 {
println("Fetching projects...")
projects, err := GetAllProjects()
if err != nil {
printError("Failed to list projects", err)
return
}
options := []huh.Option[string]{}
for _, p := range *projects {
name := fmt.Sprintf("%s - %s", red(p.Key), p.Name)
options = append(options, huh.NewOption(name, p.ID))
}
err = huh.NewSelect[string]().
Title("Choose a project").
Options(options...).
Value(&projectId).
Run()
if err != nil {
printError("Failed to choose project", err)
return
}
} else if len(args) == 1 {
projectId = args[0]
} else {
printError("Need a project ID", nil)
return
}
project, _, err := jiraClient.Project.Get(context.Background(), projectId)
if err != nil {
printError("Failed to get project", err)
return
}
fmt.Printf("Using project %s (%s)\n", project.Name, project.Key)
SetProject(project)
SaveConfig()
UpdatePrompt()
}
func ActionListBoards(_ []string) {
if !HasProject() {
printError("Please select a project first", nil)
return
}
list, err := GetAllBoardsForProject(GetProjectId())
if err != nil {
printError("Failed to list boards", err)
return
}
for _, board := range list.Values {
fmt.Printf(" - %s (%d)\n", board.Name, board.ID)
}
}
func ActionUseBoard(args []string) {
if !HasProject() {
printError("Please select a project first", nil)
return
}
var boardId int64
var err error
if len(args) == 0 {
println("Fetching boards...")
boards, err := GetAllBoardsForProject(GetProjectId())
if err != nil {
printError("Failed to list boards", err)
return
}
options := []huh.Option[int64]{}
for _, board := range boards.Values {
name := fmt.Sprintf("%s (%s)", board.Name, board.Type)
options = append(options, huh.NewOption(name, int64(board.ID)))
}
err = huh.NewSelect[int64]().
Title("Choose a board").
Options(options...).
Value(&boardId).
Run()
if err != nil {
printError("Failed to choose a board", err)
return
}
} else if len(args) == 1 {
boardId, err = strconv.ParseInt(args[0], 10, 64)
if err != nil {
printError("Invalid board ID", nil)
return
}
} else {
printError("Invalid number of arguments", nil)
}
board, err := GetBoardConfiguration(int(boardId))
if err != nil {
printError("Failed to get project", err)
return
}
fmt.Printf("Using board %s (%d)\n", board.Name, board.ID)
SetBoard(board.ID, board.Name)
SaveConfig()
UpdatePrompt()
}
func ActionUseCurrentSprint(_ []string) {
if !HasBoard() {
printError("Please select a board first", nil)
return
}
boardId := GetBoardId()
sprint, err := GetCurrentSprint(boardId)
if err != nil {
printError("Failed to get current sprint", err)
return
}
fmt.Printf("Using sprint %s (%d)\n", sprint.Name, sprint.ID)
SetSprint(sprint)
SaveConfig()
UpdatePrompt()
}
func ActionUseIssue(args []string) {
actionUseIssueWithFilter(args, func(_ *jira.Issue) bool {
return true
})
}
func ActionUseMyIssue(args []string) {
actionUseIssueWithFilter(args, func(issue *jira.Issue) bool {
assignee := issue.Fields.Assignee
if assignee == nil {
return false
}
return assignee.AccountID == jiraUser.AccountID
})
}
func actionUseIssueWithFilter(args []string, allowIssue func(issue *jira.Issue) bool) {
if !HasSprint() {
printError("No sprint selected", nil)
return
}
sprintId := GetSprintId()
var issueKey string
var err error
if len(args) == 0 {
issues, err := GetIssuesForSprint(sprintId)
if err != nil {
printError("Failed to fetch issues", err)
return
}
options := []huh.Option[string]{}
for _, issue := range issues {
if allowIssue(&issue) {
key := issue.Key
summary := issue.Fields.Summary
status := issue.Fields.Status.Name
assignee := "Unassigned"
if issue.Fields.Assignee != nil {
if issue.Fields.Assignee.AccountID == jiraUser.AccountID {
assignee = green(issue.Fields.Assignee.DisplayName)
} else {
assignee = yellow(issue.Fields.Assignee.DisplayName)
}
}
name := fmt.Sprintf("%s - %s (%s, %s)", red(key), summary, blue(status), assignee)
options = append(options, huh.NewOption(name, issue.Key))
}
}
err = huh.NewSelect[string]().
Title("Choose an issue").
Options(options...).
Value(&issueKey).
Run()
if err != nil {
printError("Failed to choose an issue", err)
return
}
} else if len(args) == 1 {
issueKey = args[0]
} else {
printError("Invalid number of arguments", nil)
}
issue, err := GetIssue(issueKey)
if err != nil {
printError("Failed to get issue", err)
return
}
fmt.Printf("Using issue %s - %s\n", issue.Key, issue.Fields.Summary)
SetIssue(issue.Key)
SaveConfig()
UpdatePrompt()
}
func ActionListIssues(_ []string) {
sprintId := GetSprintId()
if sprintId == 0 {
printError("No sprint selected", nil)
return
}
issues, err := GetIssuesForSprint(sprintId)
if err != nil {
printError("Failed to list issues", err)
}
description := ""
for _, issue := range issues {
description += fmt.Sprintf("%s - %s (%s)\n", red(issue.Key), issue.Fields.Summary, yellow(issue.Fields.Status.Name))
}
}
func ActionBack(_ []string) {
if HasIssue() {
UnsetIssue()
} else if HasSprint() {
UnsetSprint()
} else if HasBoard() {
UnsetBoard()
} else if HasProject() {
UnsetProject()
}
SaveConfig()
UpdatePrompt()
}
func ActionViewCard(_ []string) {
if !HasIssue() {
printError("No issue selected", nil)
return
}
issue, err := GetIssue(GetIssueKey())
if err != nil {
printError("Failed to get issue", err)
return
}
fmt.Printf("Key: %s\n", issue.Key)
fmt.Printf("Summary: %s\n", issue.Fields.Summary)
fmt.Printf("Type: %s\n", issue.Fields.Type.Name)
fmt.Printf("Status: %s\n", issue.Fields.Status.Name)
if issue.Fields.Assignee != nil {
fmt.Printf("Assignee: %s\n", issue.Fields.Assignee.DisplayName)
} else {
fmt.Printf("Assignee: Unassigned\n")
}
fmt.Printf("Number of comments: %d\n", len(issue.Fields.Comments.Comments))
}
func ActionViewDescription(_ []string) {
if !HasIssue() {
printError("No issue selected", nil)
return
}
issue, err := GetIssue(GetIssueKey())
if err != nil {
printError("Failed to get issue", err)
return
}
println(issue.Fields.Description)
}
func ActionViewComments(_ []string) {
if !HasIssue() {
printError("No issue selected", nil)
return
}
issue, err := GetIssue(GetIssueKey())
if err != nil {
printError("Failed to get issue", err)
return
}
if len(issue.Fields.Comments.Comments) == 0 {
println("This issue has no comments")
}
for i, comment := range issue.Fields.Comments.Comments {
if i != 0 {
println()
}
fmt.Printf("%s at %s:\n", red(comment.Author.DisplayName), blue(comment.Created))
fmt.Printf(" %s\n", comment.Body)
}
}
func ActionSetStatus(_ []string) {
if !HasIssue() {
printError("No issue selected", nil)
return
}
issueKey := GetIssueKey()
issue, err := GetIssue(issueKey)
if err != nil {
printError("Failed to fetch issue", err)
return
}
transitions, err := GetIssueTransitions(issueKey)
if err != nil {
printError("Could not fetch issue transitions", err)
return
}
options := []huh.Option[string]{}
var selected string
for _, transition := range transitions {
options = append(options, huh.Option[string]{Key: transition.Name, Value: transition.ID})
if transition.To.ID == issue.Fields.Status.ID {
selected = transition.ID
}
}
err = huh.NewSelect[string]().
Title("Select Option").
Options(options...).
Value(&selected).
Run()
if err != nil {
printError("Failed to select status", err)
return
}
err = UpdateIssueTransition(issueKey, selected)
if err != nil {
printError("Failed to update status", err)
}
}
func ActionSetTitle(_ []string) {
if !HasIssue() {
printError("No issue selected", nil)
return
}
issue, err := GetIssue(GetIssueKey())
if err != nil {
printError("Failed to get issue", err)
return
}
summary := issue.Fields.Summary
err = huh.NewInput().
Title("Enter a title:").
Value(&summary).
Run()
if err != nil {
printError("Failed to set title", err)
return
}
err = UpdateIssueTitle(issue.Key, summary)
if err != nil {
printError("Failed to set title", err)
return
}
println("Title changed!")
}