Skip to content

Commit

Permalink
feat: time entry commands allow client filter for project
Browse files Browse the repository at this point in the history
  • Loading branch information
lucassabreu committed Feb 9, 2024
1 parent 737626c commit 0a09481
Show file tree
Hide file tree
Showing 16 changed files with 279 additions and 125 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- new flag `--client` to filter projects by client when managing time entries

## [v0.46.0] - 2023-12-06

### Added
Expand Down
5 changes: 0 additions & 5 deletions pkg/cmd/project/edit/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,6 @@ func NewCmdEdit(
return err
}

if ids, err = search.GetProjectsByName(
c, w, ids); err != nil {
return err
}

if client != nil && *client != "" {
if *client, err = search.GetClientByName(
c, w, *client); err != nil {
Expand Down
98 changes: 0 additions & 98 deletions pkg/cmd/project/get/get.go

This file was deleted.

2 changes: 1 addition & 1 deletion pkg/cmd/task/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func NewCmdDelete(

if f.Config().IsAllowNameForID() {
if project, err = search.GetProjectByName(
c, w, project); err != nil {
c, w, project, ""); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/task/done/done.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func NewCmdDone(

if f.Config().IsAllowNameForID() {
if project, err = search.GetProjectByName(
c, workspace, project); err != nil {
c, workspace, project, ""); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/task/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func NewCmdList(
if f.Config().IsAllowNameForID() &&
p.ProjectID != "" {
if p.ProjectID, err = search.GetProjectByName(
c, workspace, p.ProjectID); err != nil {
c, workspace, p.ProjectID, ""); err != nil {
return err
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/task/quick-add/quick-add.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func NewCmdQuickAdd(

p, _ := cmd.Flags().GetString("project")
if f.Config().IsAllowNameForID() {
if p, err = search.GetProjectByName(c, w, p); err != nil {
if p, err = search.GetProjectByName(c, w, p, ""); err != nil {
return err
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/task/util/read-flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func TaskReadFlags(cmd *cobra.Command, f cmdutil.Factory) (p FlagsDTO, err error
}

if p.ProjectID, err = search.GetProjectByName(
c, p.Workspace, p.ProjectID); err != nil {
c, p.Workspace, p.ProjectID, ""); err != nil {
return p, err
}

Expand Down
152 changes: 152 additions & 0 deletions pkg/cmd/time-entry/in/in_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package in_test

import (
"bytes"
"errors"
"io"
"testing"
"time"
Expand Down Expand Up @@ -150,6 +151,157 @@ func TestNewCmdIn_ShouldNotSetBillable_WhenNotAsked(t *testing.T) {
return
}

t.Fatalf("err: %s", err)
})
}
}

func TestNewCmdIn_ShouldLookupProject_WithAndWithoutClient(t *testing.T) {
defaultStart := timehlp.Today().Add(8 * time.Hour)

projects := []dto.Project{
{ID: "p1", Name: "first", ClientID: "c1", ClientName: "other"},
{ID: "p2", Name: "second", ClientID: "c2", ClientName: "me"},
{ID: "p3", Name: "second", ClientID: "c3", ClientName: "clockify"},
{ID: "p4", Name: "third"},
{ID: "p5", Name: "notonclient", ClientID: "c3", ClientName: "clockify"},
}

tts := []struct {
name string
args []string
param api.CreateTimeEntryParam
err error
}{
{
name: "only project",
args: []string{"-s=08:00", "-p=first"},
param: api.CreateTimeEntryParam{
Workspace: w.ID,
Start: defaultStart,
ProjectID: projects[0].ID,
},
},
{
name: "project and client",
args: []string{"-s=08:00", "-p=second", "-c=me"},
param: api.CreateTimeEntryParam{
Workspace: w.ID,
Start: defaultStart,
ProjectID: projects[1].ID,
},
},
{
name: "project and other client",
args: []string{"-s=08:00", "-p=second", "-c=clockify"},
param: api.CreateTimeEntryParam{
Workspace: w.ID,
Start: defaultStart,
ProjectID: projects[2].ID,
},
},
{
name: "project without client",
args: []string{"-s=08:00", "-p=third"},
param: api.CreateTimeEntryParam{
Workspace: w.ID,
Start: defaultStart,
ProjectID: projects[3].ID,
},
},
{
name: "project does not exist",
args: []string{"-s=08:00", "-p=notfound"},
err: errors.New(
"No project with id or name containing 'notfound' " +
"was found"),
},
{
name: "project does not exist in this client",
args: []string{"-s=08:00", "-p=notonclient", "-c=me"},
err: errors.New(
"No project with id or name containing 'notonclient' " +
"was found for client 'me'"),
},
}

for i := range tts {
tt := &tts[i]

t.Run(tt.name, func(t *testing.T) {
f := mocks.NewMockFactory(t)

f.EXPECT().GetUserID().Return("u", nil)
f.EXPECT().GetWorkspaceID().Return(w.ID, nil)

f.EXPECT().Config().Return(&mocks.SimpleConfig{
AllowNameForID: true,
})

c := mocks.NewMockClient(t)
f.EXPECT().Client().Return(c, nil)

c.EXPECT().GetProjects(api.GetProjectsParam{
Workspace: w.ID,
PaginationParam: api.AllPages(),
}).
Return(projects, nil)

c.EXPECT().GetTimeEntryInProgress(api.GetTimeEntryInProgressParam{
Workspace: w.ID,
UserID: "u",
}).
Return(nil, nil)

if tt.err == nil {
c.EXPECT().GetProject(api.GetProjectParam{
Workspace: w.ID,
ProjectID: tt.param.ProjectID,
}).
Return(&dto.Project{ID: tt.param.ProjectID}, nil)

f.EXPECT().GetWorkspace().Return(w, nil)

c.EXPECT().Out(api.OutParam{
Workspace: w.ID,
UserID: "u",
End: tt.param.Start,
}).Return(api.ErrorNotFound)

c.EXPECT().CreateTimeEntry(tt.param).
Return(dto.TimeEntryImpl{ID: "te"}, nil)
}

called := false
cmd := in.NewCmdIn(f, func(
_ dto.TimeEntryImpl, _ io.Writer, _ util.OutputFlags) error {
called = true
return nil
})

cmd.SilenceUsage = true
cmd.SilenceErrors = true

out := bytes.NewBufferString("")
cmd.SetOut(out)
cmd.SetErr(out)

cmd.SetArgs(append(tt.args, "-q"))
_, err := cmd.ExecuteC()

if tt.err != nil {
assert.EqualError(t, err, tt.err.Error())
return
}

t.Cleanup(func() {
assert.True(t, called)
})

if assert.NoError(t, err) {
return
}

t.Fatalf("err: %s", err)
})
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/time-entry/report/util/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func ReportWithRange(

if rf.Project != "" && f.Config().IsAllowNameForID() {
if rf.Project, err = search.GetProjectByName(
c, workspace, rf.Project); err != nil {
c, workspace, rf.Project, ""); err != nil {
return err
}
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/cmd/time-entry/util/fill-with-flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ func FillTimeEntryWithFlags(flags flagSet) Step {
dto.TaskID = ""
}
dto.ProjectID = p

if flags.Changed("client") {
c, _ := flags.GetString("client")
if c != dto.Client {
dto.TaskID = ""
}
dto.Client = c
}
}

if flags.Changed("description") {
Expand Down
4 changes: 4 additions & 0 deletions pkg/cmd/time-entry/util/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func AddTimeEntryFlags(
cmd.Flags().BoolP("allow-incomplete", "A", false,
"allow creation of incomplete time entries to be edited later")

cmd.Flags().StringP("client", "c", "", "client of the project to use for time entry")
_ = cmdcompl.AddSuggestionsToFlag(cmd, "client",
cmdcomplutil.NewClientAutoComplete(f))

cmd.Flags().StringP("project", "p", "", "project to use for time entry")
_ = cmdcompl.AddSuggestionsToFlag(cmd, "project",
cmdcomplutil.NewProjectAutoComplete(f))
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/time-entry/util/name-for-id.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func lookupProject(c api.Client) Step {

var err error
te.ProjectID, err = search.GetProjectByName(
c, te.Workspace, te.ProjectID)
c, te.Workspace, te.ProjectID, te.Client)
return te, err
}

Expand Down
1 change: 1 addition & 0 deletions pkg/cmd/time-entry/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type TimeEntryDTO struct {
Workspace string
UserID string
ProjectID string
Client string
TaskID string
Description string
Start time.Time
Expand Down
Loading

0 comments on commit 0a09481

Please sign in to comment.