Skip to content

Commit

Permalink
Create add and remove effort for Jira
Browse files Browse the repository at this point in the history
  • Loading branch information
berlam committed Oct 4, 2019
1 parent fddf1f6 commit 7d6f938
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 48 deletions.
47 changes: 42 additions & 5 deletions cmd/add.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,64 @@
package cmd

import (
"eager/internal"
"eager/pkg"
"eager/pkg/cli"
"eager/pkg/jira"
"fmt"
"github.com/spf13/cobra"
"time"
)

func init() {
// TODO mro Reactivate that command after implementing it
//rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(addCmd)
addCmd.AddCommand(addJiraCmd)

addCmd.PersistentFlags().IntVar(&conf.Year, internal.FlagYear, time.Now().Year(), "specify the year")
addCmd.PersistentFlags().IntVar(&conf.Month, internal.FlagMonth, int(time.Now().Month()), "specify the month")
addCmd.PersistentFlags().IntVar(&conf.Day, internal.FlagDay, time.Now().Day(), "specify the day")
addCmd.PersistentFlags().StringVar(&conf.Task, internal.FlagTask, "", "specify the task")
addCmd.PersistentFlags().BoolVar(&conf.Duration.Merge, internal.FlagMerge, false, "merge effort on same day and task")
addCmd.MarkFlagRequired(internal.FlagTask)
}

var addCmd = &cobra.Command{
Use: "add",
Short: "Add worklog item",
Long: "Add a worklog item to your local store.",
Long: "Add a worklog item to the given store.",
Args: cobra.NoArgs,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// Call to root persistent pre run necessary. See https://github.com/spf13/cobra/issues/216
err := cmd.Root().PersistentPreRunE(cmd, args)
if err != nil {
return err
}
return nil
},
}

var addJiraCmd = &cobra.Command{
Use: "jira",
Short: "Add worklog item to Jira",
Long: "Add a worklog item to Atlassian Jira.",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
duration, err := time.ParseDuration(args[0])
if err != nil {
return fmt.Errorf("not a valid duration '%s'", args[0])
}
jira.AddWorklogItem(
pkg.NewHttpClient(),
conf.Server(),
conf.Userinfo(),
conf.Year,
time.Month(conf.Month),
conf.Day,
pkg.Task(conf.Task),
duration,
conf.Duration.Merge,
cli.Confirmation,
)
return nil
},
}
32 changes: 30 additions & 2 deletions cmd/remove.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package cmd

import (
"eager/internal"
"eager/pkg"
"eager/pkg/cli"
"eager/pkg/jira"
"github.com/spf13/cobra"
"time"
)

func init() {
// TODO mro Reactivate that command after implementing it
//rootCmd.AddCommand(removeCmd)
rootCmd.AddCommand(removeCmd)
removeCmd.AddCommand(removeJiraCmd)

removeCmd.PersistentFlags().IntVar(&conf.Year, internal.FlagYear, time.Now().Year(), "specify the year")
removeCmd.PersistentFlags().IntVar(&conf.Month, internal.FlagMonth, int(time.Now().Month()), "specify the month")
removeCmd.PersistentFlags().IntVar(&conf.Day, internal.FlagDay, time.Now().Day(), "specify the day")
removeCmd.PersistentFlags().StringVar(&conf.Task, internal.FlagTask, "", "specify the task")
removeCmd.MarkFlagRequired(internal.FlagTask)
}

var removeCmd = &cobra.Command{
Expand All @@ -16,6 +26,14 @@ var removeCmd = &cobra.Command{
Short: "Remove worklog item",
Long: "Remove a worklog item from your local store.",
Args: cobra.NoArgs,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// Call to root persistent pre run necessary. See https://github.com/spf13/cobra/issues/216
err := cmd.Root().PersistentPreRunE(cmd, args)
if err != nil {
return err
}
return nil
},
}

var removeJiraCmd = &cobra.Command{
Expand All @@ -24,5 +42,15 @@ var removeJiraCmd = &cobra.Command{
Long: "Remove a worklog item from Atlassian Jira.",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
jira.RemoveWorklogItem(
pkg.NewHttpClient(),
conf.Server(),
conf.Userinfo(),
conf.Year,
time.Month(conf.Month),
conf.Day,
pkg.Task(conf.Task),
cli.Confirmation,
)
},
}
2 changes: 1 addition & 1 deletion cmd/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ var showBcsCmd = &cobra.Command{

var showJiraCmd = &cobra.Command{
Use: "jira",
Short: "Show worklog data from Jira",
Short: "Show worklog from Jira",
Long: "Show your worklog data from Atlassian Jira.",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
Expand Down
15 changes: 11 additions & 4 deletions internal/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,42 @@ const (
FlagHost = "host"
FlagUsername = "username"
FlagPassword = "password"
FlagYear = "year"
FlagMonth = "month"
FlagProjects = "project"
FlagUsers = "user"
FlagReport = "report"
FlagSummarize = "summarize"
FlagEmpty = "empty"
FlagDecimal = "decimal"
FlagNegate = "negate"
FlagMerge = "merge"
FlagYear = "year"
FlagMonth = "month"
FlagDay = "day"
FlagTask = "task"
)

type Configuration struct {
Http bool `mapstructure:"http"`
Host string `mapstructure:"host"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Year int `mapstructure:"year"`
Month int `mapstructure:"month"`
Projects []string `mapstructure:"projects"`
Users []string `mapstructure:"users"`
Report string `mapstructure:"report"`
Duration DurationOptions `mapstructure:",squash"`
// These items make no sense to have inside a configuration file
Year int
Month int
Day int
Task string
}

type DurationOptions struct {
Summarize bool `mapstructure:"summarize"`
Empty bool `mapstructure:"empty"`
Decimal bool `mapstructure:"decimal"`
Negate bool `mapstructure:"negate"`
Merge bool `mapstructure:"merge"`
}

func (c *Configuration) Server() *url.URL {
Expand Down
20 changes: 20 additions & 0 deletions pkg/cli/confirmation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cli

import (
"eager/pkg/jira/model"
"fmt"
)

func Confirmation(worklog model.Worklog) bool {
var answer string

fmt.Printf("Remove %s (y/N): ", worklog.String())
_, err := fmt.Scanln(&answer)
if err != nil {
return false
}
if answer == "y" {
return true
}
return false
}
2 changes: 1 addition & 1 deletion pkg/datetime.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "time"
const (
IsoYearMonthDaySlash = "2006/01/02"
IsoYearMonthDay = "2006-01-02"
IsoDateTime = "2006-01-02T15:04:05.999-0700"
IsoDateTime = "2006-01-02T15:04:05.000-0700"
)

func GetTimeRange(year int, month time.Month) (time.Time, time.Time) {
Expand Down
8 changes: 8 additions & 0 deletions pkg/jira/cloud/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,11 @@ func (api Api) Issues(jql model.Jql, issueFunc model.IssueFunc) error {
func (api Api) Worklog(key model.IssueKey, worklogFunc model.WorklogFunc) error {
return api.previousVersion().Worklog(key, worklogFunc)
}

func (api Api) AddWorklog(key model.IssueKey, date time.Time, duration time.Duration) error {
return api.previousVersion().AddWorklog(key, date, duration)
}

func (api Api) RemoveWorklog(key model.IssueKey, id model.WorklogId) error {
return api.previousVersion().RemoveWorklog(key, id)
}
101 changes: 99 additions & 2 deletions pkg/jira/jira.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,102 @@ func GetBulkTimesheet(client *http.Client, server *url.URL, userinfo *url.Userin
return do(api, year, month, projects, accounts)
}

func AddWorklogItem(client *http.Client, server *url.URL, userinfo *url.Userinfo, year int, month time.Month, day int, task pkg.Task, duration time.Duration, merge bool, confirm model.WorklogFunc) {
var err error
api, err := getApiVersion(client, server, userinfo)
if err != nil {
log.Println("Could not get api version.", err)
return
}

account, location, err := api.Me()
if err != nil {
log.Println("Could not get user.", err)
return
}

key := model.IssueKey(task)
date := time.Date(year, month, day, 0, 0, 0, 0, location)

if !merge {
// Add new effort
err = api.AddWorklog(key, date, duration)
if err != nil {
log.Println("Could not add effort.", err)
}
return
}

// Check, if there is already effort inside the worklog
var effort []model.Worklog
err = api.Worklog(key, func(worklog model.Worklog) bool {
wd := worklog.Date().In(location)
if worklog.Author().Id() == account && date.Year() == wd.Year() && date.Month() == wd.Month() && date.Day() == wd.Day() {
effort = append(effort, worklog)
}
return true
})
if err != nil {
log.Println("Could not get worklog.", err)
return
}

// Collect effort for that day
for _, worklog := range effort {
duration += worklog.Duration()
}

// Add new effort
err = api.AddWorklog(key, date, duration)
if err != nil {
log.Println("Could not add effort.", err)
return
}

// Delete old effort
for _, worklog := range effort {
if confirm(worklog) {
err = api.RemoveWorklog(key, worklog.Id())
if err != nil {
log.Println("Could not remove effort.", err)
}
}
}
}

func RemoveWorklogItem(client *http.Client, server *url.URL, userinfo *url.Userinfo, year int, month time.Month, day int, task pkg.Task, confirm model.WorklogFunc) {
var err error
api, err := getApiVersion(client, server, userinfo)
if err != nil {
log.Println("Could not get api version.", err)
return
}

account, location, err := api.Me()
if err != nil {
log.Println("Could not get user.", err)
return
}

key := model.IssueKey(task)
date := time.Date(year, month, day, 0, 0, 0, 0, location)

// Check, if there is already effort inside the worklog
err = api.Worklog(key, func(worklog model.Worklog) bool {
wd := worklog.Date()
if worklog.Author().Id() == account && date.Year() == wd.Year() && date.Month() == wd.Month() && date.Day() == wd.Day() {
if confirm(worklog) {
err = api.RemoveWorklog(key, worklog.Id())
if err != nil {
log.Println("Could not remove effort.", err)
return false
}
}
}
return true
})
}

func do(api model.Api, year int, month time.Month, projects []pkg.Project, accounts map[model.Account]*pkg.User) pkg.Timesheet {
var err error

Expand Down Expand Up @@ -147,11 +243,11 @@ func do(api model.Api, year int, month time.Month, projects []pkg.Project, accou
<-throttle
wg.Done()
}()
err = api.Worklog(issue.Key(), func(worklog model.Worklog) {
err = api.Worklog(issue.Key(), func(worklog model.Worklog) bool {
account := worklog.Author().Id()
user := accounts[account]
if user == nil {
return
return true
}
date := worklog.Date().In(user.TimeZone)
date = time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, time.UTC)
Expand All @@ -165,6 +261,7 @@ func do(api model.Api, year int, month time.Month, projects []pkg.Project, accou
Duration: worklog.Duration(),
}
}
return true
})
if err != nil {
log.Println("Could not get effort for "+issue.Key(), err)
Expand Down
Loading

0 comments on commit 7d6f938

Please sign in to comment.