Skip to content

Commit

Permalink
feat: config show-client
Browse files Browse the repository at this point in the history
  • Loading branch information
lucassabreu committed May 29, 2024
1 parent 2db3d8a commit 5bd7f37
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 51 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- new config `show-client` that sets the reports/output of time entries to show its client, if exists

## [v0.50.1] - 2024-05-25

### Fixed
Expand Down
2 changes: 2 additions & 0 deletions pkg/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ var validParameters = cmdcompl.ValidArgsMap{
"missing required values",
cmdutil.CONF_SHOW_TASKS: "should show an extra column with the task " +
"description",
cmdutil.CONF_SHOW_CLIENT: "should show an extra column with the client " +
"description",
cmdutil.CONF_DESCR_AUTOCOMP: "autocomplete description looking at " +
"recent time entries",
cmdutil.CONF_DESCR_AUTOCOMP_DAYS: "how many days should be considered " +
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/config/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ func NewCmdInit(f cmdutil.Factory) *cobra.Command {
return err
}

if err := updateFlag(i, config, cmdutil.CONF_SHOW_CLIENT,
`Should show client on time entries as a separated column?`,
); err != nil {
return err

Check warning on line 146 in pkg/cmd/config/init/init.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/config/init/init.go#L146

Added line #L146 was not covered by tests
}

if err := updateFlag(i, config, cmdutil.CONF_SHOW_TOTAL_DURATION,
`Should show a line with the sum of `+
`the time entries duration?`,
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmd/config/init/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func TestInitCmd(t *testing.T) {

setBoolFn(config, cmdutil.CONF_ALLOW_INCOMPLETE, false, false)
setBoolFn(config, cmdutil.CONF_SHOW_TASKS, true, true)
setBoolFn(config, cmdutil.CONF_SHOW_CLIENT, true, true)
setBoolFn(config, cmdutil.CONF_SHOW_TOTAL_DURATION, true, true)
setBoolFn(config, cmdutil.CONF_DESCR_AUTOCOMP, false, true)

Expand Down Expand Up @@ -180,6 +181,10 @@ func TestInitCmd(t *testing.T) {
c.SendLine("")
c.ExpectString("Yes")

c.ExpectString("show client on time entries")
c.SendLine("")
c.ExpectString("Yes")

c.ExpectString("sum of the time entries duration?")
c.SendLine("yes")
c.ExpectString("Yes")
Expand Down
14 changes: 13 additions & 1 deletion pkg/cmd/config/set/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"bytes"
"testing"

"github.com/lucassabreu/clockify-cli/internal/mocks"
"github.com/lucassabreu/clockify-cli/pkg/cmd/config/set"
"github.com/lucassabreu/clockify-cli/pkg/cmdcompl"
"github.com/lucassabreu/clockify-cli/pkg/cmdutil"
"github.com/lucassabreu/clockify-cli/internal/mocks"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -77,6 +77,18 @@ func TestSetCmdRun(t *testing.T) {
return c
},
},
tc{
name: "set show client",
args: []string{cmdutil.CONF_SHOW_CLIENT, "true"},
config: func(t *testing.T) cmdutil.Config {
c := mocks.NewMockConfig(t)
c.On("SetString", cmdutil.CONF_SHOW_CLIENT,
"true").
Return(nil).Once()
c.On("Save").Once().Return(nil)
return c
},
},
}

for _, tc := range ts {
Expand Down
14 changes: 9 additions & 5 deletions pkg/cmd/time-entry/util/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,21 @@ func PrintTimeEntries(
case of.DurationFormatted:
return output.TimeEntriesTotalDurationOnlyFormatted(tes, out)
default:
opts := []output.TimeEntryOutputOpt{
output.WithTimeFormat(of.TimeFormat)}
opts := output.NewTimeEntryOutputOptions().
WithTimeFormat(of.TimeFormat)

Check warning on line 123 in pkg/cmd/time-entry/util/report.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/time-entry/util/report.go#L122-L123

Added lines #L122 - L123 were not covered by tests

if config.GetBool(cmdutil.CONF_SHOW_TASKS) {
opts = append(opts, output.WithShowTasks())
opts = opts.WithShowTasks()

Check warning on line 126 in pkg/cmd/time-entry/util/report.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/time-entry/util/report.go#L126

Added line #L126 was not covered by tests
}

if config.GetBool(cmdutil.CONF_SHOW_CLIENT) {
opts = opts.WithShowClients()

Check warning on line 130 in pkg/cmd/time-entry/util/report.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/time-entry/util/report.go#L129-L130

Added lines #L129 - L130 were not covered by tests
}

if config.GetBool(cmdutil.CONF_SHOW_TOTAL_DURATION) {
opts = append(opts, output.WithTotalDuration())
opts = opts.WithTotalDuration()

Check warning on line 134 in pkg/cmd/time-entry/util/report.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/time-entry/util/report.go#L134

Added line #L134 was not covered by tests
}

return output.TimeEntriesPrint(opts...)(tes, out)
return output.TimeEntriesPrint(opts)(tes, out)

Check warning on line 137 in pkg/cmd/time-entry/util/report.go

View check run for this annotation

Codecov / codecov/patch

pkg/cmd/time-entry/util/report.go#L137

Added line #L137 was not covered by tests
}
}
1 change: 1 addition & 0 deletions pkg/cmdutil/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
CONF_TOKEN = "token"
CONF_ALLOW_INCOMPLETE = "allow-incomplete"
CONF_SHOW_TASKS = "show-task"
CONF_SHOW_CLIENT = "show-client"
CONF_DESCR_AUTOCOMP = "description-autocomplete"
CONF_DESCR_AUTOCOMP_DAYS = "description-autocomplete-days"
CONF_SHOW_TOTAL_DURATION = "show-total-duration"
Expand Down
102 changes: 57 additions & 45 deletions pkg/output/time-entry/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,67 +36,66 @@ const (
// entries
type TimeEntryOutputOptions struct {
ShowTasks bool
ShowClients bool
ShowTotalDuration bool
TimeFormat string
}

// WithTimeFormat sets the date-time output format
func WithTimeFormat(format string) TimeEntryOutputOpt {
return func(teo *TimeEntryOutputOptions) error {
teo.TimeFormat = format
return nil
// NewTimeEntryOutputOptions creates a default TimeEntryOutputOptions
func NewTimeEntryOutputOptions() TimeEntryOutputOptions {
return TimeEntryOutputOptions{
TimeFormat: TimeFormatSimple,
ShowTasks: false,
ShowClients: false,
ShowTotalDuration: false,
}
}

// WithTimeFormat sets the date-time output format
func (teo TimeEntryOutputOptions) WithTimeFormat(
format string) TimeEntryOutputOptions {
teo.TimeFormat = format
return teo

}

// WithShowTasks shows a new column with the task of the time entry
func WithShowTasks() TimeEntryOutputOpt {
return func(teoo *TimeEntryOutputOptions) error {
teoo.ShowTasks = true
return nil
}
func (teo TimeEntryOutputOptions) WithShowTasks() TimeEntryOutputOptions {
teo.ShowTasks = true
return teo
}

// WithShowCliens shows a new column with the client of the time entry
func (teo TimeEntryOutputOptions) WithShowClients() TimeEntryOutputOptions {
teo.ShowClients = true
return teo
}

// WithTotalDuration shows a footer with the sum of the durations of the time
// entries
func WithTotalDuration() TimeEntryOutputOpt {
return func(teoo *TimeEntryOutputOptions) error {
teoo.ShowTotalDuration = true
return nil
}
func (teo TimeEntryOutputOptions) WithTotalDuration() TimeEntryOutputOptions {
teo.ShowTotalDuration = true
return teo
}

// TimeEntryOutputOpt allows the setting of TimeEntryOutputOptions values
type TimeEntryOutputOpt func(*TimeEntryOutputOptions) error

// TimeEntriesPrint will print more details
func TimeEntriesPrint(opts ...TimeEntryOutputOpt) func([]dto.TimeEntry, io.Writer) error {
options := &TimeEntryOutputOptions{
TimeFormat: TimeFormatSimple,
ShowTasks: false,
ShowTotalDuration: false,
}

for _, o := range opts {
err := o(options)
if err != nil {
return func(te []dto.TimeEntry, w io.Writer) error { return err }
}
}

func TimeEntriesPrint(
options TimeEntryOutputOptions) func([]dto.TimeEntry, io.Writer) error {
return func(timeEntries []dto.TimeEntry, w io.Writer) error {
tw := tablewriter.NewWriter(w)
taskColumn := 6
projectColumn := 4
header := []string{"ID", "Start", "End", "Dur",
"Project", "Description", "Tags"}
header := []string{"ID", "Start", "End", "Dur", "Project"}

if options.ShowTasks {
header = append(
header[:taskColumn],
header[taskColumn-1:]...,
)
header[taskColumn] = "Task"
header = append(header, "Client")
}

if options.ShowTasks {
header = append(header, "Task")
}

header = append(header, "Description", "Tags")

tw.SetHeader(header)
tw.SetRowLine(true)
if width, _, err := term.GetSize(int(os.Stdout.Fd())); err == nil {
Expand Down Expand Up @@ -124,18 +123,31 @@ func TimeEntriesPrint(opts ...TimeEntryOutputOpt) func([]dto.TimeEntry, io.Write
end.In(time.Local).Format(options.TimeFormat),
durationToString(end.Sub(t.TimeInterval.Start)),
projectName,
t.Description,
strings.Join(tagsToStringSlice(t.Tags), "\n"),
}

if options.ShowClients {
client := ""
if t.Project.ClientName != "" {
colors[len(line)] = colors[projectColumn]
client = t.Project.ClientName
}
line = append(line, client)
}

if options.ShowTasks {
line = append(line[:taskColumn], line[taskColumn-1:]...)
line[taskColumn] = ""
task := ""
if t.Task != nil {
line[taskColumn] = fmt.Sprintf("%s (%s)", t.Task.Name, t.Task.ID)
task = fmt.Sprintf("%s (%s)", t.Task.Name, t.Task.ID)
}
line = append(line, task)
}

line = append(
line,
t.Description,
strings.Join(tagsToStringSlice(t.Tags), "\n"),
)

tw.Rich(line, colors)
}

Expand Down

0 comments on commit 5bd7f37

Please sign in to comment.