Skip to content

Commit

Permalink
merge: branch 'release/0.6.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
sascha-andres committed Nov 1, 2019
2 parents 0e68c33 + ecd06a1 commit 1277c6b
Show file tree
Hide file tree
Showing 24 changed files with 160 additions and 165 deletions.
23 changes: 23 additions & 0 deletions .commit-hook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---

version: 2

subject-line-length: 50
body-required: false
separate-body: true
body-line-length: 72
enforce-body-line-length: true

external-tools:
- name: detect local replacements
command:
- go-dlr
severity: error

ignore:
- ^#.*

subject:
- severity: error
expression: ^[a-z]+(\([a-z]+\))?:.*[^\.]$
name: subject line test
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ This is in an early phase but used regularly with the toggl backend and from tim

|Version|Description|
|---|---|
|0.7.0|Better formating of time values|
||Make append separator configurable|
||Display client for time entry|
||Display project for time entry|
|0.6.0|add support for projects (add,delete and list|
||remove MySQL support|
||Workspace flag|
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/pelletier/go-toml v1.4.0 // indirect
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
github.com/pkg/errors v0.8.1
github.com/sascha-andres/go-toggl v1.1.0
github.com/sascha-andres/go-toggl v1.2.0
github.com/sirupsen/logrus v1.4.2
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cobra v0.0.5
Expand All @@ -28,5 +28,3 @@ require (
)

go 1.13

replace github.com/sascha-andres/go-toggl => ../go-toggl
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sascha-andres/go-toggl v1.1.0 h1:paMnWMP7eSoz5MJZDLSpH0qWh3BXv2It1gMZXZBxKVo=
github.com/sascha-andres/go-toggl v1.1.0/go.mod h1:bD/oZPHz5abWkB92xKC6TR10Bgs9WuOFvEQCCRlaah8=
github.com/sascha-andres/go-toggl v1.2.0 h1:00gEShaMkz2lQagmU0aJw/cDAFt1nIj/YHhPe49/nxI=
github.com/sascha-andres/go-toggl v1.2.0/go.mod h1:bD/oZPHz5abWkB92xKC6TR10Bgs9WuOFvEQCCRlaah8=
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
Expand Down
98 changes: 81 additions & 17 deletions persistence/toggl.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ type (
}
)

func NewToggl(dsn string, workspace int) (*TogglPersistor, error) {
// NewToggl establishes a session to toggl api
// token constains the api token to access the toggl pai
// workspace defines the workspace to work within
func NewToggl(token string, workspace int) (*TogglPersistor, error) {
res := TogglPersistor{
dsn: dsn,
dsn: token,
workspace: workspace,
session: toggl.OpenSession(dsn),
session: toggl.OpenSession(token),
}
toggl.DisableLog()
return &res, res.guessWork()
return &res, res.guessWorkspace()
}

func (t *TogglPersistor) guessWork() error {
func (t *TogglPersistor) guessWorkspace() error {
if t.workspace == 0 {
account, err := t.session.GetAccount()
if err != nil {
Expand All @@ -40,6 +43,7 @@ func (t *TogglPersistor) guessWork() error {
return nil
}

// New starts a new time entry with no description
func (t *TogglPersistor) New() error {
_, err := t.session.StartTimeEntry("")
if err != nil {
Expand All @@ -48,7 +52,8 @@ func (t *TogglPersistor) New() error {
return nil
}

func (t *TogglPersistor) Append(line string) error {
// Append adds text to the description separated by ;
func (t *TogglPersistor) Append(line, separator string) error {
account, err := t.session.GetAccount()
if err != nil {
return errors.Wrap(err, "Unable to get account")
Expand All @@ -60,7 +65,7 @@ func (t *TogglPersistor) Append(line string) error {
if te.Description == "" {
te.Description = line
} else {
te.Description = fmt.Sprintf("%s;%s", te.Description, line)
te.Description = fmt.Sprintf("%s%s%s", te.Description, separator, line)
}
_, err = t.session.UpdateTimeEntry(*te)
if err != nil {
Expand All @@ -69,6 +74,8 @@ func (t *TogglPersistor) Append(line string) error {
return nil
}

// Tag toggle the tags associated with the running time entry
// name is the name of the tag
func (t *TogglPersistor) Tag(name string) error {
account, err := t.session.GetAccount()
if err != nil {
Expand All @@ -90,6 +97,7 @@ func (t *TogglPersistor) Tag(name string) error {
return nil
}

// Done ends the currently running time entry
func (t *TogglPersistor) Done() error {
account, err := t.session.GetAccount()
if err != nil {
Expand All @@ -106,10 +114,7 @@ func (t *TogglPersistor) Done() error {
return nil
}

func (t *TogglPersistor) Close() error {
return nil
}

// Current returns the currently running time entry
func (t *TogglPersistor) Current() (*timenote.TimeEntry, error) {
account, err := t.session.GetAccount()
if err != nil {
Expand All @@ -125,9 +130,48 @@ func (t *TogglPersistor) Current() (*timenote.TimeEntry, error) {
res.Tag = fmt.Sprintf("%v", te.Tags)
res.Start = *te.Start
res.Duration = te.Duration
if te.Pid > 0 {
p, err := t.GetProject(te.Pid)
if err != nil {
res.Project = "- unknown project -"
} else {
res.Project = p.Name
if p.Cid > 0 {
c, err := t.GetClientByID(p.Cid)
if err != nil {
res.Client = "- unknown client -"
} else {
res.Client = c.Name
}
}
}
}
return &res, nil
}

// GetClientByID gets all clients and returns the one with the given ID
func (t *TogglPersistor) GetClientByID(clientID int) (*timenote.Client, error) {
cs, err := t.Clients()
if err != nil {
return nil, err
}
for _, c := range cs {
if c.ID == clientID {
return &c, nil
}
}
return nil, nil
}

// GetProject returns the given project
func (t *TogglPersistor) GetProject(projectID int) (*toggl.Project, error) {
p, err := t.session.GetProject(projectID)
if err != nil {
return nil, err
}
return p, nil
}

func getCurrentTimeEntry(account toggl.Account) (*toggl.TimeEntry, error) {
for _, te := range account.Data.TimeEntries {
if nil == te.Stop {
Expand All @@ -137,6 +181,7 @@ func getCurrentTimeEntry(account toggl.Account) (*toggl.TimeEntry, error) {
return nil, fmt.Errorf("no current time entry")
}

// SetProjectForCurrentTimestamp apply project to running time entry
func (t *TogglPersistor) SetProjectForCurrentTimestamp(name string) error {
var (
account toggl.Account
Expand Down Expand Up @@ -177,6 +222,7 @@ func (t *TogglPersistor) createProject(account toggl.Account, name string) (int,
return res.ID, nil
}

// CreateProject creates a new project within the workspace
func (t *TogglPersistor) CreateProject(name string) error {
id, err := t.getProjectID(name)
if err != nil {
Expand All @@ -195,6 +241,7 @@ func (t *TogglPersistor) CreateProject(name string) error {
return nil
}

// DeleteProject removes a project from the workspace
func (t *TogglPersistor) DeleteProject(name string) error {
var (
project *toggl.Project
Expand Down Expand Up @@ -239,10 +286,7 @@ func (t *TogglPersistor) getProjectID(name string) (int, error) {
return 0, nil
}

func (t *TogglPersistor) GetWebsite() (bool, string, error) {
return true, "https://toggl.com/app/timer", nil
}

// Clients ereturn all clients
func (t *TogglPersistor) Clients() ([]timenote.Client, error) {
clients, err := t.session.GetClients()
if err != nil {
Expand All @@ -259,11 +303,13 @@ func (t *TogglPersistor) Clients() ([]timenote.Client, error) {
return result, nil
}

// NewClient creates a new client
func (t *TogglPersistor) NewClient(name string) error {
_, err := t.session.CreateClient(name, t.workspace)
return err
}

// ListForDay returns all time entries for a day
func (t *TogglPersistor) ListForDay() ([]timenote.TimeEntry, error) {
year, month, day := time.Now().Date()
loc, _ := time.LoadLocation("")
Expand All @@ -275,18 +321,36 @@ func (t *TogglPersistor) ListForDay() ([]timenote.TimeEntry, error) {
}
result := make([]timenote.TimeEntry, 0)
for _, entry := range entries {
result = append(result, timenote.TimeEntry{
te := timenote.TimeEntry{
ID: entry.ID,
Tag: fmt.Sprintf("%v", entry.Tags),
Note: entry.Description,
Start: *entry.Start,
Stop: entry.Stop,
Duration: entry.Duration,
})
}
if entry.Pid > 0 {
p, err := t.GetProject(entry.Pid)
if err != nil {
te.Project = "- unknown project -"
} else {
te.Project = p.Name
if p.Cid > 0 {
c, err := t.GetClientByID(p.Cid)
if err != nil {
te.Client = "- unknown client -"
} else {
te.Client = c.Name
}
}
}
}
result = append(result, te)
}
return result, nil
}

// Projects returns a list of all projects
func (t *TogglPersistor) Projects() ([]timenote.Project, error) {
projects, err := t.session.GetProjects(t.workspace)
if err != nil {
Expand Down
34 changes: 19 additions & 15 deletions timeentry.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@ package timenote
import (
"fmt"
"time"

"github.com/pkg/errors"
)

// ErrNoCurrentTimeEntry should be returned in case no running timeentry is found
var ErrNoCurrentTimeEntry = errors.New("timenote: no current timeentry")

type (
// TimeEntry represents a simple note
TimeEntry struct {
Expand All @@ -25,10 +20,28 @@ type (
Stop *time.Time
// time entry duration in seconds. If the time entry is currently running, the duration attribute contains a negative value, denoting the start of the time entry in seconds since epoch (Jan 1 1970). The correct duration can be calculated as current_time + duration, where current_time is the current time in seconds since epoch.
Duration int64
// TimeEntry belongs to project
Project string
// // TimeEntry belongs to client
Client string
}
)

func (te *TimeEntry) String() string {
humanTime := te.getHumanTime()
if "[]" == te.Tag {
if "" == te.Note {
return fmt.Sprintf("client, project: %s, %s\nduration: %s\n", te.Client, te.Project, humanTime)
}
return fmt.Sprintf("client, project: %s, %s\nduration: %s\nnote: %s\n", te.Client, te.Project, humanTime, te.Note)
}
if "" == te.Note {
return fmt.Sprintf("client, project: %s, %s\nduration: %s - tags:%s\n", te.Client, te.Project, humanTime, te.Tag)
}
return fmt.Sprintf("client, project: %s, %s\nduration: %s - tags:%s\nnote: %s\n", te.Client, te.Project, humanTime, te.Tag, te.Note)
}

func (te *TimeEntry) getHumanTime() string {
humanTime := ""
if te.Duration < 0 {
t := time.Now().UTC().Add(time.Duration(te.Duration) * time.Second)
Expand All @@ -40,14 +53,5 @@ func (te *TimeEntry) String() string {
}
humanTime = td.String()
}
if "[]" == te.Tag {
if "" == te.Note {
return fmt.Sprintf("duration: %s\n", humanTime)
}
return fmt.Sprintf("duration: %s\nnote: %s\n", humanTime, te.Note)
}
if "" == te.Note {
return fmt.Sprintf("duration: %s - tags:%s\n", humanTime, te.Tag)
}
return fmt.Sprintf("duration: %s - tags:%s\n%s\n", humanTime, te.Tag, te.Note)
return humanTime
}
27 changes: 2 additions & 25 deletions timenote/cmd/browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@
package cmd

import (
"fmt"
"github.com/pkg/browser"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"livingit.de/code/timenote/persistence"
)

// browserCmd represents the browser command
Expand All @@ -30,29 +27,9 @@ var browserCmd = &cobra.Command{
Long: `Depending on your backend this may open a browser
with your dashboard.`,
Run: func(cmd *cobra.Command, args []string) {
p, err := persistence.NewToggl(viper.GetString("dsn"), viper.GetInt("workspace"))
err := browser.OpenURL("https://toggl.com/app/timer")
if err != nil {
log.Fatal(err)
}
defer func() {
err := p.Close()
if err != nil {
log.Fatal(err)
}
}()

has, url, err := p.GetWebsite()
if err != nil {
log.Error(err)
return
}
if has {
err = browser.OpenURL(url)
if err != nil {
log.Warnf("error executing browser: %s", err)
}
} else {
fmt.Println("no url for backend")
log.Warnf("error executing browser: %s", err)
}
},
}
Expand Down
Loading

0 comments on commit 1277c6b

Please sign in to comment.