Skip to content

Commit

Permalink
Implement timetrace list records command (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
dominikbraun authored May 15, 2021
1 parent 16b10a9 commit 6cf6c1a
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 1 deletion.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,28 @@ timetrace list projects
+---+-------------+
```

### List all records from a date

**Syntax:**

```
timetrace list records <YYYY-MM-DD>
```

**Arguments:**

|Argument|Description|
|-|-|
|`YYYY-MM-DD`|The date of the records to list.|

**Example:**

Display all records created on May 1st 2021:

```
timetrace list records 2021-05-01
```

### Edit a project

**Syntax:**
Expand Down
59 changes: 59 additions & 0 deletions cli/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package cli

import (
"strconv"
"time"

"github.com/dominikbraun/timetrace/core"
"github.com/dominikbraun/timetrace/out"

"github.com/spf13/cobra"
)

const (
defaultTimeLayout = "15:04"
)

func listCommand(t *core.Timetrace) *cobra.Command {
list := &cobra.Command{
Use: "list",
Expand All @@ -19,6 +24,7 @@ func listCommand(t *core.Timetrace) *cobra.Command {
}

list.AddCommand(listProjectsCommand(t))
list.AddCommand(listRecordsCommand(t))

return list
}
Expand Down Expand Up @@ -48,3 +54,56 @@ func listProjectsCommand(t *core.Timetrace) *cobra.Command {

return listProjects
}

func listRecordsCommand(t *core.Timetrace) *cobra.Command {
listRecords := &cobra.Command{
Use: "records <YYYY-MM-DD>",
Short: "List all records from a date",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
date, err := time.Parse("2006-01-02", args[0])
if err != nil {
out.Err("failed to parse date: %s", err.Error())
return
}

records, err := t.ListRecords(date)
if err != nil {
out.Err("failed to list records: %s", err.Error())
return
}

dateLayout := defaultTimeLayout

if t.Config().Use12Hours {
dateLayout = "03:04PM"
}

rows := make([][]string, len(records))

for i, record := range records {
end := defaultString

if record.End != nil {
end = record.End.Format(dateLayout)
}

billable := defaultBool

if record.IsBillable {
billable = "yes"
}

rows[i] = make([]string, 4)
rows[i][0] = strconv.Itoa(i + 1)
rows[i][1] = record.Start.Format(dateLayout)
rows[i][2] = end
rows[i][3] = billable
}

out.Table([]string{"#", "Start", "End", "Billable"}, rows)
},
}

return listRecords
}
26 changes: 25 additions & 1 deletion core/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,30 @@ func (t *Timetrace) LoadRecord(start time.Time) (*Record, error) {
return t.loadRecord(path)
}

// ListRecords loads and returns all records from the given date. If no records
// are found, an empty slice and no error will be returned.
func (t *Timetrace) ListRecords(date time.Time) ([]*Record, error) {
dir := t.fs.RecordDirFromDate(date)
paths, err := t.fs.RecordFilepaths(dir, func(_, _ string) bool {
return true
})
if err != nil {
return nil, err
}

records := make([]*Record, 0)

for _, path := range paths {
record, err := t.loadRecord(path)
if err != nil {
return nil, err
}
records = append(records, record)
}

return records, nil
}

// SaveRecord persists the given record. Returns ErrRecordAlreadyExists if the
// record already exists and saving isn't forced.
func (t *Timetrace) SaveRecord(record Record, force bool) error {
Expand Down Expand Up @@ -74,7 +98,7 @@ func (t *Timetrace) DeleteRecord(record Record) error {
func (t *Timetrace) loadAllRecords(date time.Time) ([]*Record, error) {
dir := t.fs.RecordDirFromDate(date)

recordFilepaths, err := t.fs.RecordFilepaths(dir, func(a, b string) bool {
recordFilepaths, err := t.fs.RecordFilepaths(dir, func(_, _ string) bool {
return true
})
if err != nil {
Expand Down

0 comments on commit 6cf6c1a

Please sign in to comment.