add
This commit is contained in:
parent
1f158877de
commit
66f93d2bd5
117
cal/main.go
117
cal/main.go
|
@ -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
|
|
||||||
}
|
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
|
@ -68,17 +69,22 @@ duration=?`,
|
||||||
|
|
||||||
func (s *Sqlite) Find(id string) (item.Event, error) {
|
func (s *Sqlite) Find(id string) (item.Event, error) {
|
||||||
var event item.Event
|
var event item.Event
|
||||||
|
var durStr string
|
||||||
err := s.db.QueryRow(`
|
err := s.db.QueryRow(`
|
||||||
SELECT id, title, start, duration
|
SELECT id, title, start, duration
|
||||||
FROM events
|
FROM events
|
||||||
WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &event.Duration)
|
WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &durStr)
|
||||||
|
switch {
|
||||||
if err == sql.ErrNoRows {
|
case err == sql.ErrNoRows:
|
||||||
return event, fmt.Errorf("event not found: %w", err)
|
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 {
|
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
|
return event, nil
|
||||||
}
|
}
|
||||||
|
@ -95,9 +101,15 @@ FROM events`)
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var event item.Event
|
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)
|
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)
|
result = append(result, event)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue