diff --git a/actions.go b/actions.go index afd7931..860f5ad 100644 --- a/actions.go +++ b/actions.go @@ -353,3 +353,30 @@ func ActionSetStatus(_ []string) { Options(options...). Run() } + +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!") +} diff --git a/commands.go b/commands.go index 2d9bf87..4d01f59 100644 --- a/commands.go +++ b/commands.go @@ -57,6 +57,7 @@ var CommandTree = []CommandArg{ ).WithHelp("View data about something"), option("set", command("status", ActionSetStatus).WithHelp("Set status of a ticket"), + command("title", ActionSetTitle).WithHelp("Set the title of a ticket"), ).WithHelp("Change something"), command("exit", ActionExit).WithHelp("Exit jirashell"), command("logout", ActionLogout).WithHelp("Logout from Jira"), diff --git a/jira.go b/jira.go index 5b7504f..c0120b7 100644 --- a/jira.go +++ b/jira.go @@ -16,55 +16,68 @@ func CreateSpinner(title string) *spinner.Spinner { Type(spinner.Globe) } -func RunSpinner[T any](title string, callback func() (*T, any, error)) (*T, error) { - var result *T +func RunSpinnerRaw(title string, callback func(ctx context.Context) error) error { var err error + finished := false + ctx, cancel := context.WithCancel(context.Background()) err2 := CreateSpinner(title). Action(func() { - result, _, err = callback() + err = callback(ctx) + finished = true }).Run() if err2 != nil { - return nil, err2 + return err2 } - if result == nil { - return nil, errorAborted + if !finished { + cancel() + return errorAborted } + return err +} + +func RunSpinner[T any](title string, callback func(ctx context.Context) (*T, any, error)) (*T, error) { + var result *T + err := RunSpinnerRaw(title, func(ctx context.Context) error { + var err error + result, _, err = callback(ctx) + return err + }) return result, err } func GetAllStatuses(projectId string) (*jira.IssueTypesWithStatus, error) { - return RunSpinner("Fetching statuses...", func() (*jira.IssueTypesWithStatus, any, error) { - return jiraClient.Project.GetAllStatuses(context.Background(), projectId) + return RunSpinner("Fetching statuses...", func(ctx context.Context) (*jira.IssueTypesWithStatus, any, error) { + return jiraClient.Project.GetAllStatuses(ctx, projectId) }) } func GetUserData() (*jira.User, error) { - return RunSpinner("Fetching user info...", func() (*jira.User, any, error) { - return jiraClient.User.GetCurrentUser(context.Background()) + return RunSpinner("Fetching user info...", func(ctx context.Context) (*jira.User, any, error) { + return jiraClient.User.GetCurrentUser(ctx) }) } func GetAllProjects() (*jira.ProjectList, error) { - return RunSpinner("Fetching all projects...", func() (*jira.ProjectList, any, error) { - return jiraClient.Project.GetAll(context.Background(), nil) + return RunSpinner("Fetching all projects...", func(ctx context.Context) (*jira.ProjectList, any, error) { + return jiraClient.Project.GetAll(ctx, nil) }) } func GetAllBoardsForProject(projectIdOrKey string) (*jira.BoardsList, error) { - return RunSpinner(fmt.Sprintf("Fetching boards for project '%s'...", projectIdOrKey), func() (*jira.BoardsList, any, error) { - return jiraClient.Board.GetAllBoards(context.Background(), &jira.BoardListOptions{ProjectKeyOrID: projectIdOrKey}) + return RunSpinner(fmt.Sprintf("Fetching boards for project '%s'...", projectIdOrKey), func(ctx context.Context) (*jira.BoardsList, any, error) { + return jiraClient.Board.GetAllBoards(ctx, &jira.BoardListOptions{ProjectKeyOrID: projectIdOrKey}) }) } func GetBoardConfiguration(boardId int) (*jira.BoardConfiguration, error) { - return RunSpinner("Fetching board...", func() (*jira.BoardConfiguration, any, error) { - return jiraClient.Board.GetBoardConfiguration(context.Background(), boardId) + return RunSpinner("Fetching board...", func(ctx context.Context) (*jira.BoardConfiguration, any, error) { + return jiraClient.Board.GetBoardConfiguration(ctx, boardId) }) } func GetCurrentSprint(boardId int) (*jira.Sprint, error) { - list, err := RunSpinner("Fetching sprint...", func() (*jira.SprintsList, any, error) { - return jiraClient.Board.GetAllSprints(context.Background(), int64(boardId), &jira.GetAllSprintsOptions{ + list, err := RunSpinner("Fetching sprint...", func(ctx context.Context) (*jira.SprintsList, any, error) { + return jiraClient.Board.GetAllSprints(ctx, int64(boardId), &jira.GetAllSprintsOptions{ State: "active", }) }) @@ -81,8 +94,8 @@ func GetCurrentSprint(boardId int) (*jira.Sprint, error) { } func GetIssuesForSprint(sprintId int) ([]jira.Issue, error) { - issues, err := RunSpinner("Fetching issues...", func() (*[]jira.Issue, any, error) { - list, t, err := jiraClient.Sprint.GetIssuesForSprint(context.Background(), sprintId) + issues, err := RunSpinner("Fetching issues...", func(ctx context.Context) (*[]jira.Issue, any, error) { + list, t, err := jiraClient.Sprint.GetIssuesForSprint(ctx, sprintId) return &list, t, err }) if issues == nil { @@ -93,7 +106,21 @@ func GetIssuesForSprint(sprintId int) ([]jira.Issue, error) { } func GetIssue(issueKey string) (*jira.Issue, error) { - return RunSpinner("Fetching issue...", func() (*jira.Issue, any, error) { - return jiraClient.Issue.Get(context.Background(), issueKey, nil) + return RunSpinner("Fetching issue...", func(ctx context.Context) (*jira.Issue, any, error) { + return jiraClient.Issue.Get(ctx, issueKey, nil) + }) +} + +func UpdateIssueTitle(issue string, title string) error { + return RunSpinnerRaw("Updating issue title...", func(ctx context.Context) error { + resp, err := jiraClient.Issue.UpdateIssue(ctx, issue, map[string]any{ + "fields": map[string]any{ + "summary": title, + }, + }) + if err != nil { + return err + } + return resp.Body.Close() }) }