Skip to content

Commit

Permalink
synchronisers: start implementing
Browse files Browse the repository at this point in the history
Signed-off-by: Sumner Evans <me@sumnerevans.com>
  • Loading branch information
sumnerevans committed Nov 23, 2022
1 parent 7bf3a4e commit ee889ab
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 25 deletions.
26 changes: 13 additions & 13 deletions commands/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ func (s *Sort) UnmarshalText(b []byte) error {

type Report struct {
// Specify the range positionally
Start string `arg:"positional" help:"specify the start of the reporting range (defaults to the beginning of last month)"`
End string `arg:"positional" help:"specify the end of the reporting range (defaults to the end of last month)"`
Start *lib.Date `arg:"positional" help:"specify the start of the reporting range (defaults to the beginning of last month)"`
End *lib.Date `arg:"positional" help:"specify the end of the reporting range (defaults to the end of last month)"`

// Specify the range using shorthand
Month string `arg:"-m,--month" help:"shorthand for reporting over an entire month (can be combined with --year, accepted formats: 01, 1, Jan, January, 2019-01)"`
Year int `arg:"-y,--year" help:"shorthand for reporting over an entire year (can be combined with --month)"`
Today bool `arg:"--today" help:"shorthand for reporting on today"`
Yesterday bool `arg:"--yesterday" help:"shorthand for reporting on yesterday"`
ThisWeek bool `arg:"--thisweek" help:"shorthand for reporting on the current week (Sunday-today)"`
LastWeek bool `arg:"--lastweek" help:"shorthand for reporting on last week (Sunday-Saturday)"`
ThisMonth bool `arg:"--thismonth" help:"shorthand for reporting on the current month"`
LastMonth bool `arg:"--lastmonth" help:"shorthand for reporting on last month"`
ThisYear bool `arg:"--thisyear" help:"shorthand for reporting on the current year"`
LastYear bool `arg:"--lastyear" help:"shorthand for reporting on last year"`
Month lib.Month `arg:"-m,--month" help:"shorthand for reporting over an entire month (can be combined with --year, accepted formats: 01, 1, Jan, January, 2019-01)"`
Year int `arg:"-y,--year" help:"shorthand for reporting over an entire year (can be combined with --month)"`
Today bool `arg:"--today" help:"shorthand for reporting on today"`
Yesterday bool `arg:"--yesterday" help:"shorthand for reporting on yesterday"`
ThisWeek bool `arg:"--thisweek" help:"shorthand for reporting on the current week (Sunday-today)"`
LastWeek bool `arg:"--lastweek" help:"shorthand for reporting on last week (Sunday-Saturday)"`
ThisMonth bool `arg:"--thismonth" help:"shorthand for reporting on the current month"`
LastMonth bool `arg:"--lastmonth" help:"shorthand for reporting on last month"`
ThisYear bool `arg:"--thisyear" help:"shorthand for reporting on the current year"`
LastYear bool `arg:"--lastyear" help:"shorthand for reporting on last year"`

// Specify the grains to show
TaskGrain bool `arg:"--taskgrain" help:"report on the task grain"`
Expand All @@ -58,7 +58,7 @@ type Report struct {
Asc bool `arg:"--asc" help:"sort ascending"`

// Output file
OutputFile string `arg:"-o,--outfile" help:"specify the filename to export the report to (supports PDF, HTML, and RST files, if set to '-' then the report is printed to stdout)" default:"-"`
OutputFile lib.Filename `arg:"-o,--outfile" help:"specify the filename to export the report to (supports PDF, HTML, and RST files, if set to '-' then the report is printed to stdout)" default:"-"`
}

func (s *Report) Run(config *lib.Config) error {
Expand Down
19 changes: 19 additions & 0 deletions commands/sync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package commands

import (
"context"

"github.com/sumnerevans/tracktime/lib"
"github.com/sumnerevans/tracktime/synchroniser"
)

type Sync struct {
Month *lib.Month `arg:"positional" help:"the month to synchronize time entries for (accepted formats: 01, 1, Jan, January, 2019-01)" default:"this month"`
}

func (s *Sync) Run(config *lib.Config) error {
for _, synchroniser := range synchroniser.Synchronisers {
go synchroniser.Sync(context.Background(), nil, nil, *s.Month)
}
return nil
}
47 changes: 44 additions & 3 deletions lib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,57 @@ import (
"gopkg.in/yaml.v3"
)

type GitHubSyncConfig struct {
Username string `yaml:"username"`
RootURI string `yaml:"root_uri"`
AccessToken string `yaml:"access_token"`
}

type GitLabSyncConfig struct {
APIRoot string `yaml:"api_root"`
APIKey string `yaml:"api_key"`
}

type SourceHutSyncConfig struct {
APIRoot string `yaml:"api_root"`
AccessToken string `yaml:"access_token"`
Username string `yaml:"username"`
}

type SyncConfig struct {
Enable bool `yaml:"enable"`
GitHub GitHubSyncConfig `yaml:"github"`
GitLab GitLabSyncConfig `yaml:"gitlab"`
SourceHut SourceHutSyncConfig `yaml:"sourcehut"`
}

type ReportingConfig struct {
FullName string `yaml:"fullname"`
ProjectRates map[string]int `yaml:"project_rates"`
CustomerRates map[string]int `yaml:"customer_rates"`
CustomerAliases map[string]string `yaml:"customer_aliases"`
CustomerAddresses map[string]string `yaml:"customer_addresses"`
DayWorkedMinThreshold int `yaml:"day_worked_min_threshold"`
ReportStatistics bool `yaml:"report_statistics"`
// TODO
// TableFormat string `yaml:"table_format"`
}

type Config struct {
FullName string `yaml:"fullname"`
Directory Filename `yaml:"directory"`
Version string `yaml:"version"`
Directory Filename `yaml:"directory"`

Reporting ReportingConfig `yaml:"reporting"`
Sync SyncConfig `yaml:"sync"`

// Editor
Editor string `yaml:"editor"`
EditorArgs []string `yaml:"editor_args"`
}

func ReadConfig(f Filename) (*Config, error) {
config := Config{
FullName: "<Not Specified>",
Reporting: ReportingConfig{FullName: "<Not Specified>"},
Directory: Filename("$HOME/.tracktime"),
}
configData, err := os.ReadFile(f.Expand())
Expand Down
29 changes: 29 additions & 0 deletions lib/month.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package lib

import (
"fmt"
"time"
)

type Month struct {
year int
month time.Month
}

func ThisMonth() Month {
now := time.Now().Local()
return Month{year: now.Year(), month: now.Month()}
}

func (d *Month) UnmarshalText(text []byte) error {
now := time.Now().Local()
switch string(text) {
case "this month", "thismonth":
d.year = now.Year()
d.month = now.Month()
default:
// TODO
return fmt.Errorf("Invalid date '%s'.", string(text))
}
return nil
}
62 changes: 62 additions & 0 deletions synchroniser/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package synchroniser

import (
"context"
"fmt"
"strings"

"github.com/sumnerevans/tracktime/lib"
)

type GitHubSynchroniser struct {
Config lib.GitHubSyncConfig
}

func (gh *GitHubSynchroniser) Name() string { return "GitHub" }

func (gh *GitHubSynchroniser) Init(config lib.SyncConfig) {
gh.Config = config.GitHub
}

func (gh *GitHubSynchroniser) Sync(ctx context.Context, aggregatedTime, syncedTime AggregatedTime, month lib.Month) (AggregatedTime, error) {
return aggregatedTime, nil
}

func (gh *GitHubSynchroniser) cleanTaskID(taskID string) string {
return strings.TrimPrefix(taskID, "#")
}

func (gh *GitHubSynchroniser) GetFormattedTaskID(entry *lib.TimeEntry) string {
if (entry.Type != "github" && entry.Type != "gh") || entry.TaskID == "" {
return ""
}

return fmt.Sprintf("#%s", gh.cleanTaskID(entry.TaskID))
}

func (gh *GitHubSynchroniser) GetTaskLink(entry *lib.TimeEntry) string {
var owner, project string
projectParts := strings.Split(entry.Project, "/")
if len(projectParts) == 1 {
if gh.Config.Username == "" {
return ""
}
owner = gh.Config.Username
project = projectParts[0]
} else if len(projectParts) == 2 {
owner = projectParts[0]
project = projectParts[1]
} else {
return ""
}
// Always link to /issues/ because it will redirect to /pull/ if necessary.
return fmt.Sprintf("%s/%s/%s/issues/%s", gh.Config.RootURI, owner, project, gh.cleanTaskID(entry.TaskID))
}

func (gh *GitHubSynchroniser) GetTaskDescription(ctx context.Context, entry *lib.TimeEntry) string {
return ""
}

func init() {
Synchronisers = append(Synchronisers, &GitHubSynchroniser{})
}
27 changes: 27 additions & 0 deletions synchroniser/syncroniser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package synchroniser

import (
"context"
"time"

"github.com/sumnerevans/tracktime/lib"
)

type AggregatedTimeKey struct {
Type lib.TimeEntryType
Project string
TaskID string
}

type AggregatedTime map[AggregatedTimeKey]time.Duration

type Synchroniser interface {
Init(config lib.SyncConfig)
Name() string
Sync(ctx context.Context, aggregatedTime, syncedTime AggregatedTime, month lib.Month) (AggregatedTime, error)
GetFormattedTaskID(entry *lib.TimeEntry) string
GetTaskLink(entry *lib.TimeEntry) string
GetTaskDescription(ctx context.Context, entry *lib.TimeEntry) string
}

var Synchronisers []Synchroniser
10 changes: 1 addition & 9 deletions tracktime.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,13 @@ import (
"github.com/sumnerevans/tracktime/lib"
)

type sync struct {
Month string `arg:"positional" help:"the month to synchronize time entries for (accepted formats: 01, 1, Jan, January, 2019-01)" default:"this month"`
}

func (s *sync) Run(config *lib.Config) error {
return nil
}

type args struct {
Start *commands.Start `arg:"subcommand" help:"start a new time entry for today"`
Stop *commands.Stop `arg:"subcommand" help:"stop the current time entry"`
Resume *commands.Resume `arg:"subcommand" help:"resume a time entry from today"`
List *commands.List `arg:"subcommand" help:"list the time entries for a date"`
Edit *commands.Edit `arg:"subcommand" help:"edit time entries for a date"`
Sync *sync `arg:"subcommand" help:"synchronize time spent on tasks for a month to external services"`
Sync *commands.Sync `arg:"subcommand" help:"synchronize time spent on tasks for a month to external services"`
Report *commands.Report `arg:"subcommand" help:"output a report about time spent in a time range"`
ConfigFile lib.Filename `arg:"--config" help:"the configuration file to use" default:"$HOME/.config/tracktime/tracktimerc"`
}
Expand Down

0 comments on commit ee889ab

Please sign in to comment.