From 66f93d2bd57e946c7922195593011dab402bb78e Mon Sep 17 00:00:00 2001 From: Erik Winter Date: Fri, 27 Sep 2024 07:38:50 +0200 Subject: [PATCH] add --- cal/main.go | 117 ------------------------- cal/planner.go | 35 -------- plan/main.go | 165 +++++++++++++++++++++++++++++++++++ {cal => plan}/memory.go | 0 {cal => plan}/memory_test.go | 0 plan/planner.go | 38 ++++++++ {cal => plan}/sqlite.go | 24 +++-- 7 files changed, 221 insertions(+), 158 deletions(-) delete mode 100644 cal/main.go delete mode 100644 cal/planner.go create mode 100644 plan/main.go rename {cal => plan}/memory.go (100%) rename {cal => plan}/memory_test.go (100%) create mode 100644 plan/planner.go rename {cal => plan}/sqlite.go (87%) diff --git a/cal/main.go b/cal/main.go deleted file mode 100644 index 48ba4cc..0000000 --- a/cal/main.go +++ /dev/null @@ -1,117 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - "time" - - "github.com/urfave/cli/v2" - "gopkg.in/yaml.v3" -) - -func main() { - confPath, err := os.UserConfigDir() - if err != nil { - fmt.Printf("could not get config path: %s\n", err) - os.Exit(1) - } - conf, err := LoadConfig(filepath.Join(confPath, "planner", "cal", "config.yaml")) - if err != nil { - fmt.Printf("could not open config file: %s\n", err) - os.Exit(1) - } - - repo, err := NewSqlite(conf.DBPath) - if err != nil { - fmt.Printf("could not open db file: %s\n", err) - os.Exit(1) - } - - app := &cli.App{ - Name: "list", - Usage: "list all events", - Action: func(*cli.Context) error { - all, err := repo.FindAll() - if err != nil { - return err - } - for _, e := range all { - fmt.Printf("%s\t%s\t%s\t%s\n", e.ID, e.Title, e.Start.Format(time.DateTime), e.Duration.String()) - } - - return nil - }, - } - - if err := app.Run(os.Args); err != nil { - fmt.Println(err) - os.Exit(1) - } - - // one := item.Event{ - // ID: "a", - // EventBody: item.EventBody{ - // Title: "title", - // Start: time.Now(), - // End: time.Now().Add(-5 * time.Second), - // }, - // } - // if err := repo.Store(one); err != nil { - // fmt.Println(err) - // os.Exit(1) - // } - - // all, err := repo.FindAll() - // if err != nil { - // fmt.Println(err) - // os.Exit(1) - // } - - // fmt.Printf("all: %+v\n", all) - - // c := client.NewClient("http://localhost:8092", "testKey") - // items, err := c.Updated([]item.Kind{item.KindEvent}, time.Time{}) - // if err != nil { - // fmt.Println(err) - // os.Exit(1) - // } - - // fmt.Printf("%+v\n", items) - - // i := item.Item{ - // ID: "id-1", - // Kind: item.KindEvent, - // Updated: time.Now(), - // Body: "body", - // } - // if err := c.Update([]item.Item{i}); err != nil { - // fmt.Println(err) - // os.Exit(1) - // } - - // items, err = c.Updated([]item.Kind{item.KindEvent}, time.Time{}) - // if err != nil { - // fmt.Println(err) - // os.Exit(1) - // } - - // fmt.Printf("%+v\n", items) -} - -type Configuration struct { - DBPath string `yaml:"dbpath"` -} - -func LoadConfig(path string) (Configuration, error) { - confFile, err := os.ReadFile(path) - if err != nil { - return Configuration{}, fmt.Errorf("could not open file: %s", err) - } - var conf Configuration - if err := yaml.Unmarshal(confFile, &conf); err != nil { - return Configuration{}, fmt.Errorf("could not unmarshal config: %s", err) - } - - return conf, nil -} diff --git a/cal/planner.go b/cal/planner.go deleted file mode 100644 index 903562a..0000000 --- a/cal/planner.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "time" - - "github.com/google/uuid" -) - -type Kind string - -const ( - KindTask Kind = "task" - KindEvent Kind = "event" -) - -var ( - KnownKinds = []Kind{KindTask, KindEvent} -) - -type Item struct { - ID string `json:"id"` - Kind Kind `json:"kind"` - Updated time.Time `json:"updated"` - Deleted bool `json:"deleted"` - Body string `json:"body"` -} - -func NewItem(k Kind, body string) Item { - return Item{ - ID: uuid.New().String(), - Kind: k, - Updated: time.Now(), - Body: body, - } -} diff --git a/plan/main.go b/plan/main.go new file mode 100644 index 0000000..8a956fa --- /dev/null +++ b/plan/main.go @@ -0,0 +1,165 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "time" + + "github.com/urfave/cli/v2" + "go-mod.ewintr.nl/planner/item" + "gopkg.in/yaml.v3" +) + +func main() { + confPath, err := os.UserConfigDir() + if err != nil { + fmt.Printf("could not get config path: %s\n", err) + os.Exit(1) + } + conf, err := LoadConfig(filepath.Join(confPath, "planner", "plan", "config.yaml")) + if err != nil { + fmt.Printf("could not open config file: %s\n", err) + os.Exit(1) + } + + repo, err := NewSqlite(conf.DBPath) + if err != nil { + fmt.Printf("could not open db file: %s\n", err) + os.Exit(1) + } + + app := &cli.App{ + Name: "plan", + Usage: "Plan your day with events", + Commands: []*cli.Command{ + { + Name: "list", + Usage: "List everything", + Action: func(cCtx *cli.Context) error { + return List(repo) + }, + }, + { + Name: "add", + Usage: "Add a new event", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "name", + Aliases: []string{"n"}, + Usage: "The event that will happen", + }, + &cli.StringFlag{ + Name: "date", + Aliases: []string{"d"}, + Usage: "The date, in YYYY-MM-DD format", + }, + &cli.StringFlag{ + Name: "time", + Aliases: []string{"t"}, + Usage: "The time, in HH:MM format. If omitted, the event will last the whole day", + }, + &cli.StringFlag{ + Name: "for", + Aliases: []string{"f"}, + Usage: "The duration, in show format (e.g. 1h30m)", + }, + }, + Action: func(cCtx *cli.Context) error { + return Add(cCtx, repo) + }, + }, + }, + } + + if err := app.Run(os.Args); err != nil { + fmt.Println(err) + os.Exit(1) + } + + // all, err := repo.FindAll() + // if err != nil { + // fmt.Println(err) + // os.Exit(1) + // } + + // fmt.Printf("all: %+v\n", all) + + // c := client.NewClient("http://localhost:8092", "testKey") + // items, err := c.Updated([]item.Kind{item.KindEvent}, time.Time{}) + // if err != nil { + // fmt.Println(err) + // os.Exit(1) + // } + + // fmt.Printf("%+v\n", items) + + // i := item.Item{ + // ID: "id-1", + // Kind: item.KindEvent, + // Updated: time.Now(), + // Body: "body", + // } + // if err := c.Update([]item.Item{i}); err != nil { + // fmt.Println(err) + // os.Exit(1) + // } + + // items, err = c.Updated([]item.Kind{item.KindEvent}, time.Time{}) + // if err != nil { + // fmt.Println(err) + // os.Exit(1) + // } + + // fmt.Printf("%+v\n", items) +} + +func List(repo EventRepo) error { + all, err := repo.FindAll() + if err != nil { + return err + } + for _, e := range all { + fmt.Printf("%s\t%s\t%s\t%s\n", e.ID, e.Title, e.Start.Format(time.DateTime), e.Duration.String()) + } + + return nil +} + +func Add(cCtx *cli.Context, repo EventRepo) error { + desc := cCtx.String("name") + date, err := time.Parse("2006-01-02", cCtx.String("date")) + if err != nil { + return fmt.Errorf("could not parse date: %v", err) + } + + one := item.Event{ + ID: "a", + EventBody: item.EventBody{ + Title: desc, + Start: date, + }, + } + if err := repo.Store(one); err != nil { + return fmt.Errorf("could not store event: %v", err) + } + + return nil +} + +type Configuration struct { + DBPath string `yaml:"dbpath"` +} + +func LoadConfig(path string) (Configuration, error) { + confFile, err := os.ReadFile(path) + if err != nil { + return Configuration{}, fmt.Errorf("could not open file: %s", err) + } + var conf Configuration + if err := yaml.Unmarshal(confFile, &conf); err != nil { + return Configuration{}, fmt.Errorf("could not unmarshal config: %s", err) + } + + return conf, nil +} diff --git a/cal/memory.go b/plan/memory.go similarity index 100% rename from cal/memory.go rename to plan/memory.go diff --git a/cal/memory_test.go b/plan/memory_test.go similarity index 100% rename from cal/memory_test.go rename to plan/memory_test.go diff --git a/plan/planner.go b/plan/planner.go new file mode 100644 index 0000000..d9fcef7 --- /dev/null +++ b/plan/planner.go @@ -0,0 +1,38 @@ +package main + +import "go-mod.ewintr.nl/planner/item" + +// type Kind string + +// const ( +// KindTask Kind = "task" +// KindEvent Kind = "event" +// ) + +// var ( +// KnownKinds = []Kind{KindTask, KindEvent} +// ) + +// type Item struct { +// ID string `json:"id"` +// Kind Kind `json:"kind"` +// Updated time.Time `json:"updated"` +// Deleted bool `json:"deleted"` +// Body string `json:"body"` +// } + +// func NewItem(k Kind, body string) Item { +// return Item{ +// ID: uuid.New().String(), +// Kind: k, +// Updated: time.Now(), +// Body: body, +// } +// } + +type EventRepo interface { + Store(event item.Event) error + Find(id string) (item.Event, error) + FindAll() ([]item.Event, error) + Delete(id string) error +} diff --git a/cal/sqlite.go b/plan/sqlite.go similarity index 87% rename from cal/sqlite.go rename to plan/sqlite.go index 7855010..45b4e18 100644 --- a/cal/sqlite.go +++ b/plan/sqlite.go @@ -4,6 +4,7 @@ import ( "database/sql" "errors" "fmt" + "time" "go-mod.ewintr.nl/planner/item" _ "modernc.org/sqlite" @@ -68,17 +69,22 @@ duration=?`, func (s *Sqlite) Find(id string) (item.Event, error) { var event item.Event + var durStr string err := s.db.QueryRow(` SELECT id, title, start, duration FROM events -WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &event.Duration) - - if err == sql.ErrNoRows { - return event, fmt.Errorf("event not found: %w", err) +WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &durStr) + switch { + case err == sql.ErrNoRows: + return item.Event{}, fmt.Errorf("event not found: %w", err) + case err != nil: + return item.Event{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err) } + dur, err := time.ParseDuration(durStr) if err != nil { - return event, fmt.Errorf("%w: %v", ErrSqliteFailure, err) + return item.Event{}, fmt.Errorf("%w: %v", err) } + event.Duration = dur return event, nil } @@ -95,9 +101,15 @@ FROM events`) defer rows.Close() for rows.Next() { var event item.Event - if err := rows.Scan(&event.ID, &event.Title, &event.Start, &event.Duration); err != nil { + var durStr string + if err := rows.Scan(&event.ID, &event.Title, &event.Start, &durStr); err != nil { return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err) } + dur, err := time.ParseDuration(durStr) + if err != nil { + return nil, fmt.Errorf("%w: %v", err) + } + event.Duration = dur result = append(result, event) }