2020-10-11 14:12:34 +00:00
package z
import (
2020-10-11 20:14:22 +00:00
"errors"
2020-10-15 21:44:04 +00:00
"strings"
2020-10-11 14:12:34 +00:00
"time"
2020-10-15 20:38:03 +00:00
"fmt"
"github.com/gookit/color"
2020-10-20 23:04:51 +00:00
"github.com/shopspring/decimal"
2020-10-11 14:12:34 +00:00
)
type Entry struct {
ID string ` json:"-" `
Begin time . Time ` json:"begin,omitempty" `
Finish time . Time ` json:"finish,omitempty" `
Project string ` json:"project,omitempty" `
Task string ` json:"task,omitempty" `
2020-10-17 12:17:01 +00:00
Notes string ` json:"notes,omitempty" `
2020-10-11 14:12:34 +00:00
User string ` json:"user,omitempty" `
2020-10-15 22:52:27 +00:00
SHA1 string ` json:"-" `
2020-10-11 14:12:34 +00:00
}
func NewEntry (
id string ,
begin string ,
finish string ,
project string ,
task string ,
user string ) ( Entry , error ) {
2020-10-15 09:54:11 +00:00
var err error
newEntry := Entry { }
newEntry . ID = id
newEntry . Project = project
newEntry . Task = task
newEntry . User = user
_ , err = newEntry . SetBeginFromString ( begin )
if err != nil {
return Entry { } , err
}
_ , err = newEntry . SetFinishFromString ( finish )
if err != nil {
return Entry { } , err
}
2021-02-07 18:02:32 +00:00
if id == "" && newEntry . IsFinishedAfterBegan ( ) == false {
2020-10-15 09:54:11 +00:00
return Entry { } , errors . New ( "beginning time of tracking cannot be after finish time" )
}
return newEntry , nil
}
2020-10-15 21:44:04 +00:00
func ( entry * Entry ) SetIDFromDatabaseKey ( key string ) ( error ) {
splitKey := strings . Split ( key , ":" )
if len ( splitKey ) < 3 || len ( splitKey ) > 3 {
return errors . New ( "not a valid database key" )
}
entry . ID = splitKey [ 2 ]
return nil
}
2020-10-15 09:54:11 +00:00
func ( entry * Entry ) SetBeginFromString ( begin string ) ( time . Time , error ) {
2020-10-11 14:12:34 +00:00
var beginTime time . Time
var err error
if begin == "" {
beginTime = time . Now ( )
} else {
beginTime , err = ParseTime ( begin )
if err != nil {
2020-10-15 09:54:11 +00:00
return beginTime , err
2020-10-11 14:12:34 +00:00
}
}
2020-10-15 09:54:11 +00:00
entry . Begin = beginTime
return beginTime , nil
}
func ( entry * Entry ) SetFinishFromString ( finish string ) ( time . Time , error ) {
var finishTime time . Time
var err error
2020-10-11 14:12:34 +00:00
if finish != "" {
finishTime , err = ParseTime ( finish )
if err != nil {
2020-10-15 09:54:11 +00:00
return finishTime , err
2020-10-11 14:12:34 +00:00
}
}
2020-10-15 09:54:11 +00:00
entry . Finish = finishTime
return finishTime , nil
}
2020-10-11 20:14:36 +00:00
2020-10-15 09:54:11 +00:00
func ( entry * Entry ) IsFinishedAfterBegan ( ) ( bool ) {
2020-10-15 20:38:03 +00:00
return ( entry . Finish . IsZero ( ) || entry . Begin . Before ( entry . Finish ) )
}
2020-10-15 20:56:04 +00:00
func ( entry * Entry ) GetOutputForTrack ( isRunning bool , wasRunning bool ) ( string ) {
var outputPrefix string = ""
var outputSuffix string = ""
now := time . Now ( )
trackDiffNow := now . Sub ( entry . Begin )
2021-12-19 04:41:20 +00:00
durationString := fmtDuration ( trackDiffNow )
2020-10-15 20:56:04 +00:00
if isRunning == true && wasRunning == false {
outputPrefix = "began tracking"
} else if isRunning == true && wasRunning == true {
outputPrefix = "tracking"
2021-12-19 04:41:20 +00:00
outputSuffix = fmt . Sprintf ( " for %sh" , color . FgLightWhite . Render ( durationString ) )
2020-10-15 20:56:04 +00:00
} else if isRunning == false && wasRunning == false {
2020-10-15 20:38:03 +00:00
outputPrefix = "tracked"
}
if entry . Task != "" && entry . Project != "" {
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s %s %s on %s%s\n" , CharTrack , outputPrefix , color . FgLightWhite . Render ( entry . Task ) , color . FgLightWhite . Render ( entry . Project ) , outputSuffix )
2020-10-15 20:38:03 +00:00
} else if entry . Task != "" && entry . Project == "" {
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s %s %s%s\n" , CharTrack , outputPrefix , color . FgLightWhite . Render ( entry . Task ) , outputSuffix )
2020-10-15 20:38:03 +00:00
} else if entry . Task == "" && entry . Project != "" {
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s %s task on %s%s\n" , CharTrack , outputPrefix , color . FgLightWhite . Render ( entry . Project ) , outputSuffix )
2020-10-15 20:38:03 +00:00
}
2020-10-15 20:56:04 +00:00
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s %s task%s\n" , CharTrack , outputPrefix , outputSuffix )
2020-10-15 20:38:03 +00:00
}
2020-10-20 23:04:51 +00:00
func ( entry * Entry ) GetDuration ( ) ( decimal . Decimal ) {
duration := entry . Finish . Sub ( entry . Begin )
2021-06-14 04:21:50 +00:00
if ( duration < 0 ) {
duration = time . Now ( ) . Sub ( entry . Begin )
}
2020-10-20 23:04:51 +00:00
return decimal . NewFromFloat ( duration . Hours ( ) )
}
2020-10-15 20:38:03 +00:00
func ( entry * Entry ) GetOutputForFinish ( ) ( string ) {
2020-10-15 20:56:04 +00:00
var outputSuffix string = ""
2020-10-15 20:38:03 +00:00
trackDiff := entry . Finish . Sub ( entry . Begin )
2021-12-19 04:33:12 +00:00
taskDuration := fmtDuration ( trackDiff )
2020-10-15 20:38:03 +00:00
2021-12-19 04:41:20 +00:00
outputSuffix = fmt . Sprintf ( " for %sh" , color . FgLightWhite . Render ( taskDuration ) )
2020-10-15 20:56:04 +00:00
2020-10-15 20:38:03 +00:00
if entry . Task != "" && entry . Project != "" {
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s finished tracking %s on %s%s\n" , CharFinish , color . FgLightWhite . Render ( entry . Task ) , color . FgLightWhite . Render ( entry . Project ) , outputSuffix )
2020-10-15 20:38:03 +00:00
} else if entry . Task != "" && entry . Project == "" {
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s finished tracking %s%s\n" , CharFinish , color . FgLightWhite . Render ( entry . Task ) , outputSuffix )
2020-10-15 20:38:03 +00:00
} else if entry . Task == "" && entry . Project != "" {
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s finished tracking task on %s%s\n" , CharFinish , color . FgLightWhite . Render ( entry . Project ) , outputSuffix )
2020-10-15 20:38:03 +00:00
}
2020-10-15 21:07:36 +00:00
return fmt . Sprintf ( "%s finished tracking task%s\n" , CharFinish , outputSuffix )
2020-10-11 14:12:34 +00:00
}
2020-10-15 21:44:12 +00:00
2020-10-17 20:14:00 +00:00
func ( entry * Entry ) GetOutput ( full bool ) ( string ) {
var output string = ""
2021-02-07 18:22:16 +00:00
var entryFinish time . Time
var isRunning string = ""
if entry . Finish . IsZero ( ) {
entryFinish = time . Now ( )
isRunning = "[running]"
} else {
entryFinish = entry . Finish
}
trackDiff := entryFinish . Sub ( entry . Begin )
2021-12-19 04:33:12 +00:00
taskDuration := fmtDuration ( trackDiff )
2020-10-17 20:14:00 +00:00
if full == false {
2021-12-19 04:33:12 +00:00
2021-12-19 04:41:20 +00:00
output = fmt . Sprintf ( "%s %s on %s from %s to %s (%sh) %s" ,
2021-02-07 18:22:16 +00:00
color . FgGray . Render ( entry . ID ) ,
color . FgLightWhite . Render ( entry . Task ) ,
color . FgLightWhite . Render ( entry . Project ) ,
color . FgLightWhite . Render ( entry . Begin . Format ( "2006-01-02 15:04 -0700" ) ) ,
color . FgLightWhite . Render ( entryFinish . Format ( "2006-01-02 15:04 -0700" ) ) ,
2021-12-19 04:33:12 +00:00
color . FgLightWhite . Render ( taskDuration ) ,
2021-02-07 18:22:16 +00:00
color . FgLightYellow . Render ( isRunning ) ,
)
2020-10-17 20:14:00 +00:00
} else {
2021-12-19 04:41:20 +00:00
output = fmt . Sprintf ( "%s\n %s on %s\n %sh from %s to %s %s\n\n Notes:\n %s\n" ,
2021-02-07 18:22:16 +00:00
color . FgGray . Render ( entry . ID ) ,
color . FgLightWhite . Render ( entry . Task ) ,
color . FgLightWhite . Render ( entry . Project ) ,
2021-12-19 04:33:12 +00:00
color . FgLightWhite . Render ( taskDuration ) ,
2021-02-07 18:22:16 +00:00
color . FgLightWhite . Render ( entry . Begin . Format ( "2006-01-02 15:04 -0700" ) ) ,
color . FgLightWhite . Render ( entryFinish . Format ( "2006-01-02 15:04 -0700" ) ) ,
color . FgLightYellow . Render ( isRunning ) ,
color . FgLightWhite . Render ( strings . Replace ( entry . Notes , "\n" , "\n " , - 1 ) ) ,
)
2020-10-17 20:14:00 +00:00
}
return output
2020-10-15 21:44:12 +00:00
}
2020-10-17 14:32:41 +00:00
2020-10-17 14:50:21 +00:00
func GetFilteredEntries ( entries [ ] Entry , project string , task string , since time . Time , until time . Time ) ( [ ] Entry , error ) {
var filteredEntries [ ] Entry
2020-10-17 14:32:41 +00:00
2020-10-17 14:50:21 +00:00
for _ , entry := range entries {
2020-10-17 14:32:41 +00:00
if project != "" && GetIdFromName ( entry . Project ) != GetIdFromName ( project ) {
continue
}
if task != "" && GetIdFromName ( entry . Task ) != GetIdFromName ( task ) {
continue
}
if since . IsZero ( ) == false && since . Before ( entry . Begin ) == false && since . Equal ( entry . Begin ) == false {
continue
}
if until . IsZero ( ) == false && until . After ( entry . Finish ) == false && until . Equal ( entry . Finish ) == false {
continue
}
2020-10-17 14:50:21 +00:00
filteredEntries = append ( filteredEntries , entry )
2020-10-17 14:32:41 +00:00
}
return filteredEntries , nil
}