Add interactive mode for `tea milestone create` (#310)

Implement interactive milestone creation

Return fmt.Errorf when title is empty

Incorporate deadline functionality

Use dateparse and cleanup CreateMilestone task

Signed-off-by: Martin Reboredo <yakoyoku@gmail.com>
Co-authored-by: Martin Reboredo <yakoyoku@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/310
Reviewed-by: Norwin <noerw@noreply.gitea.io>
Reviewed-by: 6543 <6543@obermui.de>
Co-Authored-By: Martin Reboredo <yakoyakoyokuyoku@noreply.gitea.io>
Co-Committed-By: Martin Reboredo <yakoyakoyokuyoku@noreply.gitea.io>
This commit is contained in:
Martin Reboredo 2020-12-18 02:50:07 +08:00 committed by 6543
parent 8b588f5313
commit 43e9943757
6 changed files with 146 additions and 18 deletions

2
.gitignore vendored
View File

@ -4,3 +4,5 @@ tea
.idea/ .idea/
.history/ .history/
dist/ dist/
.vscode/

View File

@ -5,13 +5,15 @@
package milestones package milestones
import ( import (
"fmt" "time"
"code.gitea.io/tea/cmd/flags" "code.gitea.io/tea/cmd/flags"
"code.gitea.io/tea/modules/context" "code.gitea.io/tea/modules/context"
"code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/interact"
"code.gitea.io/tea/modules/task"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"github.com/araddon/dateparse"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -33,6 +35,11 @@ var CmdMilestonesCreate = cli.Command{
Aliases: []string{"d"}, Aliases: []string{"d"},
Usage: "milestone description to create", Usage: "milestone description to create",
}, },
&cli.StringFlag{
Name: "deadline",
Aliases: []string{"expires", "x"},
Usage: "set milestone deadline (default is no due date)",
},
&cli.StringFlag{ &cli.StringFlag{
Name: "state", Name: "state",
Usage: "set milestone state (default is open)", Usage: "set milestone state (default is open)",
@ -43,12 +50,15 @@ var CmdMilestonesCreate = cli.Command{
func runMilestonesCreate(cmd *cli.Context) error { func runMilestonesCreate(cmd *cli.Context) error {
ctx := context.InitCommand(cmd) ctx := context.InitCommand(cmd)
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
title := ctx.String("title") date := ctx.String("deadline")
if len(title) == 0 { deadline := &time.Time{}
fmt.Printf("Title is required\n") if date != "" {
return nil t, err := dateparse.ParseAny(date)
if err == nil {
return err
}
deadline = &t
} }
state := gitea.StateOpen state := gitea.StateOpen
@ -56,15 +66,17 @@ func runMilestonesCreate(cmd *cli.Context) error {
state = gitea.StateClosed state = gitea.StateClosed
} }
mile, _, err := ctx.Login.Client().CreateMilestone(ctx.Owner, ctx.Repo, gitea.CreateMilestoneOption{ if ctx.NumFlags() == 0 {
Title: title, return interact.CreateMilestone(ctx.Login, ctx.Owner, ctx.Repo)
Description: ctx.String("description"),
State: state,
})
if err != nil {
return err
} }
print.MilestoneDetails(mile) return task.CreateMilestone(
return nil ctx.Login,
ctx.Owner,
ctx.Repo,
ctx.String("title"),
ctx.String("description"),
deadline,
state,
)
} }

View File

@ -11,7 +11,7 @@ import (
"github.com/AlecAivazis/survey/v2" "github.com/AlecAivazis/survey/v2"
) )
// CreateIssue interactively creates a PR // CreateIssue interactively creates an issue
func CreateIssue(login *config.Login, owner, repo string) error { func CreateIssue(login *config.Login, owner, repo string) error {
var title, description string var title, description string

View File

@ -0,0 +1,77 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package interact
import (
"fmt"
"time"
"code.gitea.io/tea/modules/config"
"code.gitea.io/tea/modules/task"
"code.gitea.io/sdk/gitea"
"github.com/AlecAivazis/survey/v2"
"github.com/araddon/dateparse"
)
// CreateMilestone interactively creates a milestone
func CreateMilestone(login *config.Login, owner, repo string) error {
var title, description, dueDate string
var deadline *time.Time
// owner, repo
owner, repo, err := promptRepoSlug(owner, repo)
if err != nil {
return err
}
// title
promptOpts := survey.WithValidator(survey.Required)
promptI := &survey.Input{Message: "Milestone title:"}
if err := survey.AskOne(promptI, &title, promptOpts); err != nil {
return err
}
// description
promptM := &survey.Multiline{Message: "Milestone description:"}
if err := survey.AskOne(promptM, &description); err != nil {
return err
}
// deadline
promptI = &survey.Input{Message: "Milestone deadline [no due date]:"}
err = survey.AskOne(
promptI,
&dueDate,
survey.WithValidator(func(input interface{}) error {
if str, ok := input.(string); ok {
if len(str) == 0 {
return nil
}
t, err := dateparse.ParseAny(str)
if err != nil {
return err
}
deadline = &t
} else {
return fmt.Errorf("invalid result type")
}
return nil
}),
)
if err != nil {
return err
}
return task.CreateMilestone(
login,
owner,
repo,
title,
description,
deadline,
gitea.StateOpen)
}

View File

@ -12,7 +12,7 @@ import (
"code.gitea.io/tea/modules/print" "code.gitea.io/tea/modules/print"
) )
// CreateIssue creates a PR in the given repo and prints the result // CreateIssue creates an issue in the given repo and prints the result
func CreateIssue(login *config.Login, repoOwner, repoName, title, description string) error { func CreateIssue(login *config.Login, repoOwner, repoName, title, description string) error {
// title is required // title is required

View File

@ -0,0 +1,37 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package task
import (
"fmt"
"time"
"code.gitea.io/tea/modules/config"
"code.gitea.io/tea/modules/print"
"code.gitea.io/sdk/gitea"
)
// CreateMilestone creates a milestone in the given repo and prints the result
func CreateMilestone(login *config.Login, repoOwner, repoName, title, description string, deadline *time.Time, state gitea.StateType) error {
// title is required
if len(title) == 0 {
return fmt.Errorf("Title is required")
}
mile, _, err := login.Client().CreateMilestone(repoOwner, repoName, gitea.CreateMilestoneOption{
Title: title,
Description: description,
Deadline: deadline,
State: state,
})
if err != nil {
return err
}
print.MilestoneDetails(mile)
return nil
}