diff --git a/plan/command/add.go b/plan/command/add.go index a91460e..0e8724a 100644 --- a/plan/command/add.go +++ b/plan/command/add.go @@ -87,7 +87,7 @@ func Add(localIDRepo storage.LocalID, eventRepo storage.Event, nameStr, onStr, a if frStr != "" { fr, err := time.ParseDuration(frStr) if err != nil { - return fmt.Errorf("%w: could not parse time: %s", ErrInvalidArg, err) + return fmt.Errorf("%w: could not parse duration: %s", ErrInvalidArg, err) } e.Duration = fr } diff --git a/plan/command/update.go b/plan/command/update.go new file mode 100644 index 0000000..b72463b --- /dev/null +++ b/plan/command/update.go @@ -0,0 +1,102 @@ +package command + +import ( + "fmt" + "time" + + "github.com/urfave/cli/v2" + "go-mod.ewintr.nl/planner/plan/storage" +) + +var UpdateCmd = &cli.Command{ + Name: "update", + Usage: "Update an event", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "localID", + Aliases: []string{"l"}, + Usage: "The local id of the event", + Required: true, + }, + &cli.StringFlag{ + Name: "name", + Aliases: []string{"n"}, + Usage: "The event that will happen", + }, + &cli.StringFlag{ + Name: "on", + Aliases: []string{"o"}, + Usage: "The date, in YYYY-MM-DD format", + }, + &cli.StringFlag{ + Name: "at", + Aliases: []string{"a"}, + 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)", + }, + }, +} + +func NewUpdateCmd(localRepo storage.LocalID, eventRepo storage.Event) *cli.Command { + UpdateCmd.Action = func(cCtx *cli.Context) error { + return Update(localRepo, eventRepo, cCtx.Int("localID"), cCtx.String("name"), cCtx.String("on"), cCtx.String("at"), cCtx.String("for")) + } + return UpdateCmd +} + +func Update(localRepo storage.LocalID, eventRepo storage.Event, localID int, nameStr, onStr, atStr, frStr string) error { + var id string + idMap, err := localRepo.FindAll() + if err != nil { + return fmt.Errorf("could not get local ids: %v", err) + } + for eid, lid := range idMap { + if localID == lid { + id = eid + } + } + if id == "" { + return fmt.Errorf("could not find local id") + } + + e, err := eventRepo.Find(id) + if err != nil { + return fmt.Errorf("could not find event") + } + + if nameStr != "" { + e.Title = nameStr + } + if onStr != "" || atStr != "" { + oldStart := e.Start + dateStr := oldStart.Format("2006-01-02") + if atStr != "" { + dateStr = atStr + } + timeStr := oldStart.Format("15:04") + if onStr != "" { + timeStr = onStr + } + newStart, err := time.Parse("2006-01-02 15:04", fmt.Sprintf("%s %s", dateStr, timeStr)) + if err != nil { + fmt.Errorf("could not parse new start: %s", err) + } + e.Start = newStart + } + if frStr != "" { + fr, err := time.ParseDuration(frStr) + if err != nil { + return fmt.Errorf("%w: could not parse duration: %s", ErrInvalidArg, err) + } + e.Duration = fr + } + if err := eventRepo.Store(e); err != nil { + return fmt.Errorf("could not store event: %v", err) + } + + return nil +} diff --git a/plan/command/update_test.go b/plan/command/update_test.go new file mode 100644 index 0000000..811f1e5 --- /dev/null +++ b/plan/command/update_test.go @@ -0,0 +1,155 @@ +package command_test + +import ( + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "go-mod.ewintr.nl/planner/item" + "go-mod.ewintr.nl/planner/plan/command" + "go-mod.ewintr.nl/planner/plan/storage/memory" +) + +func TestUpdate(t *testing.T) { + t.Parallel() + + eid := "c" + lid := 3 + oneHour, err := time.ParseDuration("1h") + if err != nil { + t.Errorf("exp nil, got %v", err) + } + title := "title" + start := time.Date(2024, 10, 6, 10, 0, 0, 0, time.UTC) + // twoHour, err := time.ParseDuration("2h") + // if err != nil { + // t.Errorf("exp nil, got %v", err) + // } + + for _, tc := range []struct { + name string + localID int + args map[string]string + expEvent item.Event + expErr bool + }{ + { + name: "no args", + localID: lid, + expEvent: item.Event{ + ID: eid, + EventBody: item.EventBody{ + Title: title, + Start: start, + Duration: oneHour, + }, + }, + }, + { + name: "not found", + localID: 1, + expErr: true, + }, + { + name: "name", + localID: lid, + args: map[string]string{ + "name": "updated", + }, + expEvent: item.Event{ + ID: eid, + EventBody: item.EventBody{ + Title: "updated", + Start: start, + Duration: oneHour, + }, + }, + }, + { + name: "invalid at", + localID: lid, + args: map[string]string{}, + }, + { + name: "at", + localID: lid, + args: map[string]string{ + "at": "2024-10-02", + }, + expEvent: item.Event{ + ID: eid, + EventBody: item.EventBody{ + Title: title, + Start: time.Date(2024, 10, 2, 10, 0, 0, 0, time.UTC), + Duration: oneHour, + }, + }, + }, + { + name: "on", + localID: lid, + args: map[string]string{ + "on": "11:00", + }, + expEvent: item.Event{ + ID: eid, + EventBody: item.EventBody{ + Title: title, + Start: time.Date(2024, 10, 6, 11, 0, 0, 0, time.UTC), + Duration: oneHour, + }, + }, + }, + { + name: "at and on", + localID: lid, + args: map[string]string{ + "at": "2024-10-02", + "on": "11:00", + }, + expEvent: item.Event{ + ID: eid, + EventBody: item.EventBody{ + Title: title, + Start: time.Date(2024, 10, 2, 11, 0, 0, 0, time.UTC), + Duration: oneHour, + }, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + eventRepo := memory.NewEvent() + localIDRepo := memory.NewLocalID() + if err := eventRepo.Store(item.Event{ + ID: eid, + EventBody: item.EventBody{ + Title: title, + Start: start, + Duration: oneHour, + }, + }); err != nil { + t.Errorf("exp nil, got %v", err) + } + if err := localIDRepo.Store(eid, lid); err != nil { + t.Errorf("exp nil, ,got %v", err) + } + + actErr := command.Update(localIDRepo, eventRepo, tc.localID, tc.args["name"], tc.args["on"], tc.args["at"], tc.args["for"]) != nil + if tc.expErr != actErr { + t.Errorf("exp %v, got %v", tc.expErr, actErr) + } + if tc.expErr { + return + } + + actEvent, err := eventRepo.Find(eid) + if err != nil { + t.Errorf("exp nil, got %v", err) + } + if diff := cmp.Diff(tc.expEvent, actEvent); diff != "" { + t.Errorf("(exp +, got -)\n%s", diff) + } + + }) + } +} diff --git a/plan/main.go b/plan/main.go index 4df6f3b..0ffe6a5 100644 --- a/plan/main.go +++ b/plan/main.go @@ -35,6 +35,7 @@ func main() { Commands: []*cli.Command{ command.NewAddCmd(localIDRepo, eventRepo), command.NewListCmd(localIDRepo, eventRepo), + command.NewUpdateCmd(localIDRepo, eventRepo), }, }