rename event to task
This commit is contained in:
parent
5985356c99
commit
dcdc75887f
Binary file not shown.
|
@ -10,12 +10,12 @@ import (
|
|||
type Kind string
|
||||
|
||||
const (
|
||||
KindTask Kind = "task"
|
||||
KindEvent Kind = "event"
|
||||
KindSchedule Kind = "schedule"
|
||||
KindTask Kind = "task"
|
||||
)
|
||||
|
||||
var (
|
||||
KnownKinds = []Kind{KindTask, KindEvent}
|
||||
KnownKinds = []Kind{KindSchedule, KindTask}
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
|
|
|
@ -8,14 +8,14 @@ import (
|
|||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
type EventBody struct {
|
||||
type TaskBody struct {
|
||||
Title string `json:"title"`
|
||||
Time Time `json:"time"`
|
||||
Duration time.Duration `json:"duration"`
|
||||
}
|
||||
|
||||
func (e EventBody) MarshalJSON() ([]byte, error) {
|
||||
type Alias EventBody
|
||||
func (e TaskBody) MarshalJSON() ([]byte, error) {
|
||||
type Alias TaskBody
|
||||
return json.Marshal(&struct {
|
||||
Duration string `json:"duration"`
|
||||
*Alias
|
||||
|
@ -25,8 +25,8 @@ func (e EventBody) MarshalJSON() ([]byte, error) {
|
|||
})
|
||||
}
|
||||
|
||||
func (e *EventBody) UnmarshalJSON(data []byte) error {
|
||||
type Alias EventBody
|
||||
func (e *TaskBody) UnmarshalJSON(data []byte) error {
|
||||
type Alias TaskBody
|
||||
aux := &struct {
|
||||
Duration string `json:"duration"`
|
||||
*Alias
|
||||
|
@ -45,70 +45,70 @@ func (e *EventBody) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
type Task struct {
|
||||
ID string `json:"id"`
|
||||
Date Date `json:"date"`
|
||||
Recurrer Recurrer `json:"recurrer"`
|
||||
RecurNext Date `json:"recurNext"`
|
||||
EventBody
|
||||
TaskBody
|
||||
}
|
||||
|
||||
func NewEvent(i Item) (Event, error) {
|
||||
if i.Kind != KindEvent {
|
||||
return Event{}, fmt.Errorf("item is not an event")
|
||||
func NewTask(i Item) (Task, error) {
|
||||
if i.Kind != KindTask {
|
||||
return Task{}, fmt.Errorf("item is not an task")
|
||||
}
|
||||
|
||||
var e Event
|
||||
if err := json.Unmarshal([]byte(i.Body), &e); err != nil {
|
||||
return Event{}, fmt.Errorf("could not unmarshal item body: %v", err)
|
||||
var t Task
|
||||
if err := json.Unmarshal([]byte(i.Body), &t); err != nil {
|
||||
return Task{}, fmt.Errorf("could not unmarshal item body: %v", err)
|
||||
}
|
||||
|
||||
e.ID = i.ID
|
||||
e.Date = i.Date
|
||||
e.Recurrer = i.Recurrer
|
||||
e.RecurNext = i.RecurNext
|
||||
t.ID = i.ID
|
||||
t.Date = i.Date
|
||||
t.Recurrer = i.Recurrer
|
||||
t.RecurNext = i.RecurNext
|
||||
|
||||
return e, nil
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (e Event) Item() (Item, error) {
|
||||
body, err := json.Marshal(e.EventBody)
|
||||
func (t Task) Item() (Item, error) {
|
||||
body, err := json.Marshal(t.TaskBody)
|
||||
if err != nil {
|
||||
return Item{}, fmt.Errorf("could not marshal event body to json")
|
||||
return Item{}, fmt.Errorf("could not marshal task body to json")
|
||||
}
|
||||
|
||||
return Item{
|
||||
ID: e.ID,
|
||||
Kind: KindEvent,
|
||||
Date: e.Date,
|
||||
Recurrer: e.Recurrer,
|
||||
RecurNext: e.RecurNext,
|
||||
ID: t.ID,
|
||||
Kind: KindTask,
|
||||
Date: t.Date,
|
||||
Recurrer: t.Recurrer,
|
||||
RecurNext: t.RecurNext,
|
||||
Body: string(body),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e Event) Valid() bool {
|
||||
if e.Title == "" {
|
||||
func (t Task) Valid() bool {
|
||||
if t.Title == "" {
|
||||
return false
|
||||
}
|
||||
if e.Date.IsZero() {
|
||||
if t.Date.IsZero() {
|
||||
return false
|
||||
}
|
||||
if e.Duration.Seconds() < 1 {
|
||||
if t.Duration.Seconds() < 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func EventDiff(a, b Event) string {
|
||||
func TaskDiff(a, b Task) string {
|
||||
aJSON, _ := json.Marshal(a)
|
||||
bJSON, _ := json.Marshal(b)
|
||||
|
||||
return cmp.Diff(string(aJSON), string(bJSON))
|
||||
}
|
||||
|
||||
func EventDiffs(a, b []Event) string {
|
||||
func TaskDiffs(a, b []Task) string {
|
||||
aJSON, _ := json.Marshal(a)
|
||||
bJSON, _ := json.Marshal(b)
|
||||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"go-mod.ewintr.nl/planner/item"
|
||||
)
|
||||
|
||||
func TestNewEvent(t *testing.T) {
|
||||
func TestNewTask(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
oneHour, err := time.ParseDuration("1h")
|
||||
|
@ -16,17 +16,17 @@ func TestNewEvent(t *testing.T) {
|
|||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
it item.Item
|
||||
expEvent item.Event
|
||||
expErr bool
|
||||
name string
|
||||
it item.Item
|
||||
expTask item.Task
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
name: "wrong kind",
|
||||
it: item.Item{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 9, 20),
|
||||
Kind: item.KindTask,
|
||||
Kind: item.KindSchedule,
|
||||
Body: `{
|
||||
"title":"title",
|
||||
"time":"08:00",
|
||||
|
@ -39,7 +39,7 @@ func TestNewEvent(t *testing.T) {
|
|||
name: "invalid json",
|
||||
it: item.Item{
|
||||
ID: "a",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Body: `{"id":"a"`,
|
||||
},
|
||||
expErr: true,
|
||||
|
@ -48,7 +48,7 @@ func TestNewEvent(t *testing.T) {
|
|||
name: "valid",
|
||||
it: item.Item{
|
||||
ID: "a",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Date: item.NewDate(2024, 9, 20),
|
||||
Recurrer: item.NewRecurrer("2024-12-08, daily"),
|
||||
Body: `{
|
||||
|
@ -57,11 +57,11 @@ func TestNewEvent(t *testing.T) {
|
|||
"duration":"1h"
|
||||
}`,
|
||||
},
|
||||
expEvent: item.Event{
|
||||
expTask: item.Task{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 9, 20),
|
||||
Recurrer: item.NewRecurrer("2024-12-08, daily"),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Time: item.NewTime(8, 0),
|
||||
Duration: oneHour,
|
||||
|
@ -70,21 +70,21 @@ func TestNewEvent(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actEvent, actErr := item.NewEvent(tc.it)
|
||||
actTask, actErr := item.NewTask(tc.it)
|
||||
if tc.expErr != (actErr != nil) {
|
||||
t.Errorf("exp nil, got %v", actErr)
|
||||
}
|
||||
if tc.expErr {
|
||||
return
|
||||
}
|
||||
if diff := item.EventDiff(tc.expEvent, actEvent); diff != "" {
|
||||
if diff := item.TaskDiff(tc.expTask, actTask); diff != "" {
|
||||
t.Errorf("(+exp, -got)\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEventItem(t *testing.T) {
|
||||
func TestTaskItem(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
oneHour, err := time.ParseDuration("1h")
|
||||
|
@ -93,24 +93,24 @@ func TestEventItem(t *testing.T) {
|
|||
}
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
event item.Event
|
||||
tsk item.Task
|
||||
expItem item.Item
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
expItem: item.Item{
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Updated: time.Time{},
|
||||
Body: `{"duration":"0s","title":"","time":"00:00"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "normal",
|
||||
event: item.Event{
|
||||
tsk: item.Task{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 9, 23),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Time: item.NewTime(8, 0),
|
||||
Duration: oneHour,
|
||||
|
@ -118,7 +118,7 @@ func TestEventItem(t *testing.T) {
|
|||
},
|
||||
expItem: item.Item{
|
||||
ID: "a",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Updated: time.Time{},
|
||||
Date: item.NewDate(2024, 9, 23),
|
||||
Body: `{"duration":"1h0m0s","title":"title","time":"08:00"}`,
|
||||
|
@ -126,7 +126,7 @@ func TestEventItem(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actItem, actErr := tc.event.Item()
|
||||
actItem, actErr := tc.tsk.Item()
|
||||
if tc.expErr != (actErr != nil) {
|
||||
t.Errorf("exp nil, got %v", actErr)
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func TestEventItem(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestEventValidate(t *testing.T) {
|
||||
func TestTaskValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
oneHour, err := time.ParseDuration("1h")
|
||||
|
@ -149,19 +149,19 @@ func TestEventValidate(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
event item.Event
|
||||
exp bool
|
||||
name string
|
||||
tsk item.Task
|
||||
exp bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
},
|
||||
{
|
||||
name: "missing title",
|
||||
event: item.Event{
|
||||
tsk: item.Task{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 9, 20),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Time: item.NewTime(8, 0),
|
||||
Duration: oneHour,
|
||||
},
|
||||
|
@ -169,9 +169,9 @@ func TestEventValidate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "no date",
|
||||
event: item.Event{
|
||||
tsk: item.Task{
|
||||
ID: "a",
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Time: item.NewTime(8, 0),
|
||||
Duration: oneHour,
|
||||
|
@ -180,10 +180,10 @@ func TestEventValidate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "no duration",
|
||||
event: item.Event{
|
||||
tsk: item.Task{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 9, 20),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Time: item.NewTime(8, 0),
|
||||
},
|
||||
|
@ -191,10 +191,10 @@ func TestEventValidate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "valid",
|
||||
event: item.Event{
|
||||
tsk: item.Task{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 9, 20),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Time: item.NewTime(8, 0),
|
||||
Duration: oneHour,
|
||||
|
@ -204,7 +204,7 @@ func TestEventValidate(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if act := tc.event.Valid(); tc.exp != act {
|
||||
if act := tc.tsk.Valid(); tc.exp != act {
|
||||
t.Errorf("exp %v, got %v", tc.exp, act)
|
||||
}
|
||||
|
|
@ -11,15 +11,15 @@ import (
|
|||
|
||||
type Add struct {
|
||||
localIDRepo storage.LocalID
|
||||
eventRepo storage.Event
|
||||
taskRepo storage.Task
|
||||
syncRepo storage.Sync
|
||||
argSet *ArgSet
|
||||
}
|
||||
|
||||
func NewAdd(localRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync) Command {
|
||||
func NewAdd(localRepo storage.LocalID, taskRepo storage.Task, syncRepo storage.Sync) Command {
|
||||
return &Add{
|
||||
localIDRepo: localRepo,
|
||||
eventRepo: eventRepo,
|
||||
taskRepo: taskRepo,
|
||||
syncRepo: syncRepo,
|
||||
argSet: &ArgSet{
|
||||
Flags: map[string]Flag{
|
||||
|
@ -75,21 +75,21 @@ func (add *Add) Execute(main []string, flags map[string]string) error {
|
|||
func (add *Add) do() error {
|
||||
as := add.argSet
|
||||
rec := as.GetRecurrer(FlagRec)
|
||||
e := item.Event{
|
||||
tsk := item.Task{
|
||||
ID: uuid.New().String(),
|
||||
Date: as.GetDate(FlagOn),
|
||||
Recurrer: rec,
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: as.Main,
|
||||
Time: as.GetTime(FlagAt),
|
||||
Duration: as.GetDuration(FlagFor),
|
||||
},
|
||||
}
|
||||
if rec != nil {
|
||||
e.RecurNext = rec.First()
|
||||
tsk.RecurNext = rec.First()
|
||||
}
|
||||
|
||||
if err := add.eventRepo.Store(e); err != nil {
|
||||
if err := add.taskRepo.Store(tsk); err != nil {
|
||||
return fmt.Errorf("could not store event: %v", err)
|
||||
}
|
||||
|
||||
|
@ -97,11 +97,11 @@ func (add *Add) do() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not create next local id: %v", err)
|
||||
}
|
||||
if err := add.localIDRepo.Store(e.ID, localID); err != nil {
|
||||
if err := add.localIDRepo.Store(tsk.ID, localID); err != nil {
|
||||
return fmt.Errorf("could not store local id: %v", err)
|
||||
}
|
||||
|
||||
it, err := e.Item()
|
||||
it, err := tsk.Item()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert event to sync item: %v", err)
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ func TestAdd(t *testing.T) {
|
|||
anHour := time.Hour
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
main []string
|
||||
flags map[string]string
|
||||
expErr bool
|
||||
expEvent item.Event
|
||||
name string
|
||||
main []string
|
||||
flags map[string]string
|
||||
expErr bool
|
||||
expTask item.Task
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
|
@ -48,10 +48,10 @@ func TestAdd(t *testing.T) {
|
|||
flags: map[string]string{
|
||||
command.FlagOn: aDate.String(),
|
||||
},
|
||||
expEvent: item.Event{
|
||||
expTask: item.Task{
|
||||
ID: "title",
|
||||
Date: aDate,
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Duration: aDay,
|
||||
},
|
||||
|
@ -65,10 +65,10 @@ func TestAdd(t *testing.T) {
|
|||
command.FlagAt: aTime.String(),
|
||||
command.FlagFor: anHourStr,
|
||||
},
|
||||
expEvent: item.Event{
|
||||
expTask: item.Task{
|
||||
ID: "title",
|
||||
Date: aDate,
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Time: aTime,
|
||||
Duration: anHour,
|
||||
|
@ -86,10 +86,10 @@ func TestAdd(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
eventRepo := memory.NewEvent()
|
||||
taskRepo := memory.NewTask()
|
||||
localRepo := memory.NewLocalID()
|
||||
syncRepo := memory.NewSync()
|
||||
cmd := command.NewAdd(localRepo, eventRepo, syncRepo)
|
||||
cmd := command.NewAdd(localRepo, taskRepo, syncRepo)
|
||||
actParseErr := cmd.Execute(tc.main, tc.flags) != nil
|
||||
if tc.expErr != actParseErr {
|
||||
t.Errorf("exp %v, got %v", tc.expErr, actParseErr)
|
||||
|
@ -98,12 +98,12 @@ func TestAdd(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
actEvents, err := eventRepo.FindAll()
|
||||
actTasks, err := taskRepo.FindAll()
|
||||
if err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
if len(actEvents) != 1 {
|
||||
t.Errorf("exp 1, got %d", len(actEvents))
|
||||
if len(actTasks) != 1 {
|
||||
t.Errorf("exp 1, got %d", len(actTasks))
|
||||
}
|
||||
|
||||
actLocalIDs, err := localRepo.FindAll()
|
||||
|
@ -113,15 +113,15 @@ func TestAdd(t *testing.T) {
|
|||
if len(actLocalIDs) != 1 {
|
||||
t.Errorf("exp 1, got %v", len(actLocalIDs))
|
||||
}
|
||||
if _, ok := actLocalIDs[actEvents[0].ID]; !ok {
|
||||
if _, ok := actLocalIDs[actTasks[0].ID]; !ok {
|
||||
t.Errorf("exp true, got %v", ok)
|
||||
}
|
||||
|
||||
if actEvents[0].ID == "" {
|
||||
if actTasks[0].ID == "" {
|
||||
t.Errorf("exp string not te be empty")
|
||||
}
|
||||
tc.expEvent.ID = actEvents[0].ID
|
||||
if diff := item.EventDiff(tc.expEvent, actEvents[0]); diff != "" {
|
||||
tc.expTask.ID = actTasks[0].ID
|
||||
if diff := item.TaskDiff(tc.expTask, actTasks[0]); diff != "" {
|
||||
t.Errorf("(exp -, got +)\n%s", diff)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,15 +9,15 @@ import (
|
|||
|
||||
type Delete struct {
|
||||
localIDRepo storage.LocalID
|
||||
eventRepo storage.Event
|
||||
taskRepo storage.Task
|
||||
syncRepo storage.Sync
|
||||
localID int
|
||||
}
|
||||
|
||||
func NewDelete(localIDRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync) Command {
|
||||
func NewDelete(localIDRepo storage.LocalID, taskRepo storage.Task, syncRepo storage.Sync) Command {
|
||||
return &Delete{
|
||||
localIDRepo: localIDRepo,
|
||||
eventRepo: eventRepo,
|
||||
taskRepo: taskRepo,
|
||||
syncRepo: syncRepo,
|
||||
}
|
||||
}
|
||||
|
@ -41,23 +41,23 @@ func (del *Delete) do() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not get local ids: %v", err)
|
||||
}
|
||||
for eid, lid := range idMap {
|
||||
for tskID, lid := range idMap {
|
||||
if del.localID == lid {
|
||||
id = eid
|
||||
id = tskID
|
||||
}
|
||||
}
|
||||
if id == "" {
|
||||
return fmt.Errorf("could not find local id")
|
||||
}
|
||||
|
||||
e, err := del.eventRepo.Find(id)
|
||||
tsk, err := del.taskRepo.Find(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get event: %v", err)
|
||||
return fmt.Errorf("could not get task: %v", err)
|
||||
}
|
||||
|
||||
it, err := e.Item()
|
||||
it, err := tsk.Item()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert event to sync item: %v", err)
|
||||
return fmt.Errorf("could not convert task to sync item: %v", err)
|
||||
}
|
||||
it.Deleted = true
|
||||
if err := del.syncRepo.Store(it); err != nil {
|
||||
|
@ -68,8 +68,8 @@ func (del *Delete) do() error {
|
|||
return fmt.Errorf("could not delete local id: %v", err)
|
||||
}
|
||||
|
||||
if err := del.eventRepo.Delete(id); err != nil {
|
||||
return fmt.Errorf("could not delete event: %v", err)
|
||||
if err := del.taskRepo.Delete(id); err != nil {
|
||||
return fmt.Errorf("could not delete task: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -13,10 +13,10 @@ import (
|
|||
func TestDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := item.Event{
|
||||
e := item.Task{
|
||||
ID: "id",
|
||||
Date: item.NewDate(2024, 10, 7),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "name",
|
||||
},
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestDelete(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
eventRepo := memory.NewEvent()
|
||||
eventRepo := memory.NewTask()
|
||||
syncRepo := memory.NewSync()
|
||||
if err := eventRepo.Store(e); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
|
|
|
@ -8,13 +8,13 @@ import (
|
|||
|
||||
type List struct {
|
||||
localIDRepo storage.LocalID
|
||||
eventRepo storage.Event
|
||||
taskRepo storage.Task
|
||||
}
|
||||
|
||||
func NewList(localIDRepo storage.LocalID, eventRepo storage.Event) Command {
|
||||
func NewList(localIDRepo storage.LocalID, taskRepo storage.Task) Command {
|
||||
return &List{
|
||||
localIDRepo: localIDRepo,
|
||||
eventRepo: eventRepo,
|
||||
taskRepo: taskRepo,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ func (list *List) do() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not get local ids: %v", err)
|
||||
}
|
||||
all, err := list.eventRepo.FindAll()
|
||||
all, err := list.taskRepo.FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@ import (
|
|||
func TestList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
eventRepo := memory.NewEvent()
|
||||
taskRepo := memory.NewTask()
|
||||
localRepo := memory.NewLocalID()
|
||||
e := item.Event{
|
||||
e := item.Task{
|
||||
ID: "id",
|
||||
Date: item.NewDate(2024, 10, 7),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "name",
|
||||
},
|
||||
}
|
||||
if err := eventRepo.Store(e); err != nil {
|
||||
if err := taskRepo.Store(e); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
if err := localRepo.Store(e.ID, 1); err != nil {
|
||||
|
@ -47,7 +47,7 @@ func TestList(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := command.NewList(localRepo, eventRepo)
|
||||
cmd := command.NewList(localRepo, taskRepo)
|
||||
actErr := cmd.Execute(tc.main, nil) != nil
|
||||
if tc.expErr != actErr {
|
||||
t.Errorf("exp %v, got %v", tc.expErr, actErr)
|
||||
|
|
|
@ -14,15 +14,15 @@ type Sync struct {
|
|||
client client.Client
|
||||
syncRepo storage.Sync
|
||||
localIDRepo storage.LocalID
|
||||
eventRepo storage.Event
|
||||
taskRepo storage.Task
|
||||
}
|
||||
|
||||
func NewSync(client client.Client, syncRepo storage.Sync, localIDRepo storage.LocalID, eventRepo storage.Event) Command {
|
||||
func NewSync(client client.Client, syncRepo storage.Sync, localIDRepo storage.LocalID, taskRepo storage.Task) Command {
|
||||
return &Sync{
|
||||
client: client,
|
||||
syncRepo: syncRepo,
|
||||
localIDRepo: localIDRepo,
|
||||
eventRepo: eventRepo,
|
||||
taskRepo: taskRepo,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ func (sync *Sync) do() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not find timestamp of last update: %v", err)
|
||||
}
|
||||
recItems, err := sync.client.Updated([]item.Kind{item.KindEvent}, ts)
|
||||
recItems, err := sync.client.Updated([]item.Kind{item.KindTask}, ts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not receive updates: %v", err)
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ func (sync *Sync) do() error {
|
|||
if err := sync.localIDRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) {
|
||||
return fmt.Errorf("could not delete local id: %v", err)
|
||||
}
|
||||
if err := sync.eventRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) {
|
||||
return fmt.Errorf("could not delete event: %v", err)
|
||||
if err := sync.taskRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) {
|
||||
return fmt.Errorf("could not delete task: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -76,16 +76,16 @@ func (sync *Sync) do() error {
|
|||
return fmt.Errorf("could not get local ids: %v", err)
|
||||
}
|
||||
for _, u := range updated {
|
||||
var eBody item.EventBody
|
||||
if err := json.Unmarshal([]byte(u.Body), &eBody); err != nil {
|
||||
return fmt.Errorf("could not unmarshal event body: %v", err)
|
||||
var tskBody item.TaskBody
|
||||
if err := json.Unmarshal([]byte(u.Body), &tskBody); err != nil {
|
||||
return fmt.Errorf("could not unmarshal task body: %v", err)
|
||||
}
|
||||
e := item.Event{
|
||||
ID: u.ID,
|
||||
EventBody: eBody,
|
||||
tsk := item.Task{
|
||||
ID: u.ID,
|
||||
TaskBody: tskBody,
|
||||
}
|
||||
if err := sync.eventRepo.Store(e); err != nil {
|
||||
return fmt.Errorf("could not store event: %v", err)
|
||||
if err := sync.taskRepo.Store(tsk); err != nil {
|
||||
return fmt.Errorf("could not store task: %v", err)
|
||||
}
|
||||
lid, ok := lidMap[u.ID]
|
||||
if !ok {
|
||||
|
|
|
@ -17,7 +17,7 @@ func TestSyncParse(t *testing.T) {
|
|||
syncClient := client.NewMemory()
|
||||
syncRepo := memory.NewSync()
|
||||
localIDRepo := memory.NewLocalID()
|
||||
eventRepo := memory.NewEvent()
|
||||
taskRepo := memory.NewTask()
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
|
@ -39,7 +39,7 @@ func TestSyncParse(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := command.NewSync(syncClient, syncRepo, localIDRepo, eventRepo)
|
||||
cmd := command.NewSync(syncClient, syncRepo, localIDRepo, taskRepo)
|
||||
actErr := cmd.Execute(tc.main, nil) != nil
|
||||
if tc.expErr != actErr {
|
||||
t.Errorf("exp %v, got %v", tc.expErr, actErr)
|
||||
|
@ -54,11 +54,11 @@ func TestSyncSend(t *testing.T) {
|
|||
syncClient := client.NewMemory()
|
||||
syncRepo := memory.NewSync()
|
||||
localIDRepo := memory.NewLocalID()
|
||||
eventRepo := memory.NewEvent()
|
||||
taskRepo := memory.NewTask()
|
||||
|
||||
it := item.Item{
|
||||
ID: "a",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Body: `{
|
||||
"title":"title",
|
||||
"start":"2024-10-18T08:00:00Z",
|
||||
|
@ -77,12 +77,12 @@ func TestSyncSend(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "single",
|
||||
ks: []item.Kind{item.KindEvent},
|
||||
ks: []item.Kind{item.KindTask},
|
||||
expItems: []item.Item{it},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := command.NewSync(syncClient, syncRepo, localIDRepo, eventRepo)
|
||||
cmd := command.NewSync(syncClient, syncRepo, localIDRepo, taskRepo)
|
||||
if err := cmd.Execute([]string{"sync"}, nil); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
|
@ -115,31 +115,31 @@ func TestSyncReceive(t *testing.T) {
|
|||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
present []item.Event
|
||||
present []item.Task
|
||||
updated []item.Item
|
||||
expEvent []item.Event
|
||||
expTask []item.Task
|
||||
expLocalID map[string]int
|
||||
}{
|
||||
{
|
||||
name: "no new",
|
||||
expEvent: []item.Event{},
|
||||
expTask: []item.Task{},
|
||||
expLocalID: map[string]int{},
|
||||
},
|
||||
{
|
||||
name: "new",
|
||||
updated: []item.Item{{
|
||||
ID: "a",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Body: `{
|
||||
"title":"title",
|
||||
"start":"2024-10-23T08:00:00Z",
|
||||
"duration":"1h"
|
||||
}`,
|
||||
}},
|
||||
expEvent: []item.Event{{
|
||||
expTask: []item.Task{{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 10, 23),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Duration: oneHour,
|
||||
},
|
||||
|
@ -150,27 +150,27 @@ func TestSyncReceive(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "update existing",
|
||||
present: []item.Event{{
|
||||
present: []item.Task{{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 10, 23),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "title",
|
||||
Duration: oneHour,
|
||||
},
|
||||
}},
|
||||
updated: []item.Item{{
|
||||
ID: "a",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Body: `{
|
||||
"title":"new title",
|
||||
"start":"2024-10-23T08:00:00Z",
|
||||
"duration":"1h"
|
||||
}`,
|
||||
}},
|
||||
expEvent: []item.Event{{
|
||||
expTask: []item.Task{{
|
||||
ID: "a",
|
||||
Date: item.NewDate(2024, 10, 23),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "new title",
|
||||
Duration: oneHour,
|
||||
},
|
||||
|
@ -185,10 +185,10 @@ func TestSyncReceive(t *testing.T) {
|
|||
syncClient := client.NewMemory()
|
||||
syncRepo := memory.NewSync()
|
||||
localIDRepo := memory.NewLocalID()
|
||||
eventRepo := memory.NewEvent()
|
||||
taskRepo := memory.NewTask()
|
||||
|
||||
for i, p := range tc.present {
|
||||
if err := eventRepo.Store(p); err != nil {
|
||||
if err := taskRepo.Store(p); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
if err := localIDRepo.Store(p.ID, i+1); err != nil {
|
||||
|
@ -200,17 +200,17 @@ func TestSyncReceive(t *testing.T) {
|
|||
}
|
||||
|
||||
// sync
|
||||
cmd := command.NewSync(syncClient, syncRepo, localIDRepo, eventRepo)
|
||||
cmd := command.NewSync(syncClient, syncRepo, localIDRepo, taskRepo)
|
||||
if err := cmd.Execute([]string{"sync"}, nil); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
|
||||
// check result
|
||||
actEvents, err := eventRepo.FindAll()
|
||||
actTasks, err := taskRepo.FindAll()
|
||||
if err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
if diff := item.EventDiffs(tc.expEvent, actEvents); diff != "" {
|
||||
if diff := item.TaskDiffs(tc.expTask, actTasks); diff != "" {
|
||||
t.Errorf("(exp +, got -)\n%s", diff)
|
||||
}
|
||||
actLocalIDs, err := localIDRepo.FindAll()
|
||||
|
|
|
@ -10,16 +10,16 @@ import (
|
|||
|
||||
type Update struct {
|
||||
localIDRepo storage.LocalID
|
||||
eventRepo storage.Event
|
||||
taskRepo storage.Task
|
||||
syncRepo storage.Sync
|
||||
argSet *ArgSet
|
||||
localID int
|
||||
}
|
||||
|
||||
func NewUpdate(localIDRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync) Command {
|
||||
func NewUpdate(localIDRepo storage.LocalID, taskRepo storage.Task, syncRepo storage.Sync) Command {
|
||||
return &Update{
|
||||
localIDRepo: localIDRepo,
|
||||
eventRepo: eventRepo,
|
||||
taskRepo: taskRepo,
|
||||
syncRepo: syncRepo,
|
||||
argSet: &ArgSet{
|
||||
Flags: map[string]Flag{
|
||||
|
@ -67,47 +67,47 @@ func (update *Update) do() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not get local ids: %v", err)
|
||||
}
|
||||
for eid, lid := range idMap {
|
||||
for tid, lid := range idMap {
|
||||
if update.localID == lid {
|
||||
id = eid
|
||||
id = tid
|
||||
}
|
||||
}
|
||||
if id == "" {
|
||||
return fmt.Errorf("could not find local id")
|
||||
}
|
||||
|
||||
e, err := update.eventRepo.Find(id)
|
||||
tsk, err := update.taskRepo.Find(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find event")
|
||||
return fmt.Errorf("could not find task")
|
||||
}
|
||||
|
||||
if as.Main != "" {
|
||||
e.Title = as.Main
|
||||
tsk.Title = as.Main
|
||||
}
|
||||
if as.IsSet(FlagOn) {
|
||||
e.Date = as.GetDate(FlagOn)
|
||||
tsk.Date = as.GetDate(FlagOn)
|
||||
}
|
||||
if as.IsSet(FlagAt) {
|
||||
e.Time = as.GetTime(FlagAt)
|
||||
tsk.Time = as.GetTime(FlagAt)
|
||||
}
|
||||
if as.IsSet(FlagFor) {
|
||||
e.Duration = as.GetDuration(FlagFor)
|
||||
tsk.Duration = as.GetDuration(FlagFor)
|
||||
}
|
||||
if as.IsSet(FlagRec) {
|
||||
e.Recurrer = as.GetRecurrer(FlagRec)
|
||||
tsk.Recurrer = as.GetRecurrer(FlagRec)
|
||||
}
|
||||
|
||||
if !e.Valid() {
|
||||
return fmt.Errorf("event is unvalid")
|
||||
if !tsk.Valid() {
|
||||
return fmt.Errorf("task is unvalid")
|
||||
}
|
||||
|
||||
if err := update.eventRepo.Store(e); err != nil {
|
||||
return fmt.Errorf("could not store event: %v", err)
|
||||
if err := update.taskRepo.Store(tsk); err != nil {
|
||||
return fmt.Errorf("could not store task: %v", err)
|
||||
}
|
||||
|
||||
it, err := e.Item()
|
||||
it, err := tsk.Item()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert event to sync item: %v", err)
|
||||
return fmt.Errorf("could not convert task to sync item: %v", err)
|
||||
}
|
||||
if err := update.syncRepo.Store(it); err != nil {
|
||||
return fmt.Errorf("could not store sync item: %v", err)
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
func TestUpdateExecute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
eid := "c"
|
||||
tskID := "c"
|
||||
lid := 3
|
||||
oneHour, err := time.ParseDuration("1h")
|
||||
if err != nil {
|
||||
|
@ -28,12 +28,12 @@ func TestUpdateExecute(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
localID int
|
||||
main []string
|
||||
flags map[string]string
|
||||
expEvent item.Event
|
||||
expErr bool
|
||||
name string
|
||||
localID int
|
||||
main []string
|
||||
flags map[string]string
|
||||
expTask item.Task
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
name: "no args",
|
||||
|
@ -48,10 +48,10 @@ func TestUpdateExecute(t *testing.T) {
|
|||
name: "name",
|
||||
localID: lid,
|
||||
main: []string{"update", fmt.Sprintf("%d", lid), "updated"},
|
||||
expEvent: item.Event{
|
||||
ID: eid,
|
||||
expTask: item.Task{
|
||||
ID: tskID,
|
||||
Date: item.NewDate(2024, 10, 6),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: "updated",
|
||||
Time: aTime,
|
||||
Duration: oneHour,
|
||||
|
@ -74,10 +74,10 @@ func TestUpdateExecute(t *testing.T) {
|
|||
flags: map[string]string{
|
||||
"on": "2024-10-02",
|
||||
},
|
||||
expEvent: item.Event{
|
||||
ID: eid,
|
||||
expTask: item.Task{
|
||||
ID: tskID,
|
||||
Date: item.NewDate(2024, 10, 2),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: title,
|
||||
Time: aTime,
|
||||
Duration: oneHour,
|
||||
|
@ -100,10 +100,10 @@ func TestUpdateExecute(t *testing.T) {
|
|||
flags: map[string]string{
|
||||
"at": "11:00",
|
||||
},
|
||||
expEvent: item.Event{
|
||||
ID: eid,
|
||||
expTask: item.Task{
|
||||
ID: tskID,
|
||||
Date: item.NewDate(2024, 10, 6),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: title,
|
||||
Time: item.NewTime(11, 0),
|
||||
Duration: oneHour,
|
||||
|
@ -118,10 +118,10 @@ func TestUpdateExecute(t *testing.T) {
|
|||
"on": "2024-10-02",
|
||||
"at": "11:00",
|
||||
},
|
||||
expEvent: item.Event{
|
||||
ID: eid,
|
||||
expTask: item.Task{
|
||||
ID: tskID,
|
||||
Date: item.NewDate(2024, 10, 2),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: title,
|
||||
Time: item.NewTime(11, 0),
|
||||
Duration: oneHour,
|
||||
|
@ -144,10 +144,10 @@ func TestUpdateExecute(t *testing.T) {
|
|||
flags: map[string]string{
|
||||
"for": "2h",
|
||||
},
|
||||
expEvent: item.Event{
|
||||
ID: eid,
|
||||
expTask: item.Task{
|
||||
ID: tskID,
|
||||
Date: item.NewDate(2024, 10, 6),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: title,
|
||||
Time: aTime,
|
||||
Duration: twoHour,
|
||||
|
@ -168,11 +168,11 @@ func TestUpdateExecute(t *testing.T) {
|
|||
flags: map[string]string{
|
||||
"rec": "2024-12-08, daily",
|
||||
},
|
||||
expEvent: item.Event{
|
||||
ID: eid,
|
||||
expTask: item.Task{
|
||||
ID: tskID,
|
||||
Date: aDate,
|
||||
Recurrer: item.NewRecurrer("2024-12-08, daily"),
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: title,
|
||||
Time: aTime,
|
||||
Duration: oneHour,
|
||||
|
@ -181,13 +181,13 @@ func TestUpdateExecute(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
eventRepo := memory.NewEvent()
|
||||
taskRepo := memory.NewTask()
|
||||
localIDRepo := memory.NewLocalID()
|
||||
syncRepo := memory.NewSync()
|
||||
if err := eventRepo.Store(item.Event{
|
||||
ID: eid,
|
||||
if err := taskRepo.Store(item.Task{
|
||||
ID: tskID,
|
||||
Date: aDate,
|
||||
EventBody: item.EventBody{
|
||||
TaskBody: item.TaskBody{
|
||||
Title: title,
|
||||
Time: aTime,
|
||||
Duration: oneHour,
|
||||
|
@ -195,11 +195,11 @@ func TestUpdateExecute(t *testing.T) {
|
|||
}); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
if err := localIDRepo.Store(eid, lid); err != nil {
|
||||
if err := localIDRepo.Store(tskID, lid); err != nil {
|
||||
t.Errorf("exp nil, ,got %v", err)
|
||||
}
|
||||
|
||||
cmd := command.NewUpdate(localIDRepo, eventRepo, syncRepo)
|
||||
cmd := command.NewUpdate(localIDRepo, taskRepo, syncRepo)
|
||||
actParseErr := cmd.Execute(tc.main, tc.flags) != nil
|
||||
if tc.expErr != actParseErr {
|
||||
t.Errorf("exp %v, got %v", tc.expErr, actParseErr)
|
||||
|
@ -208,11 +208,11 @@ func TestUpdateExecute(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
actEvent, err := eventRepo.Find(eid)
|
||||
actTask, err := taskRepo.Find(tskID)
|
||||
if err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
if diff := item.EventDiff(tc.expEvent, actEvent); diff != "" {
|
||||
if diff := item.TaskDiff(tc.expTask, actTask); diff != "" {
|
||||
t.Errorf("(exp -, got +)\n%s", diff)
|
||||
}
|
||||
updated, err := syncRepo.FindAll()
|
||||
|
|
12
plan/main.go
12
plan/main.go
|
@ -27,7 +27,7 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
localIDRepo, eventRepo, syncRepo, err := sqlite.NewSqlites(conf.DBPath)
|
||||
localIDRepo, taskRepo, syncRepo, err := sqlite.NewSqlites(conf.DBPath)
|
||||
if err != nil {
|
||||
fmt.Printf("could not open db file: %s\n", err)
|
||||
os.Exit(1)
|
||||
|
@ -37,11 +37,11 @@ func main() {
|
|||
|
||||
cli := command.CLI{
|
||||
Commands: []command.Command{
|
||||
command.NewAdd(localIDRepo, eventRepo, syncRepo),
|
||||
command.NewList(localIDRepo, eventRepo),
|
||||
command.NewUpdate(localIDRepo, eventRepo, syncRepo),
|
||||
command.NewDelete(localIDRepo, eventRepo, syncRepo),
|
||||
command.NewSync(syncClient, syncRepo, localIDRepo, eventRepo),
|
||||
command.NewAdd(localIDRepo, taskRepo, syncRepo),
|
||||
command.NewList(localIDRepo, taskRepo),
|
||||
command.NewUpdate(localIDRepo, taskRepo, syncRepo),
|
||||
command.NewDelete(localIDRepo, taskRepo, syncRepo),
|
||||
command.NewSync(syncClient, syncRepo, localIDRepo, taskRepo),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
package memory
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"go-mod.ewintr.nl/planner/item"
|
||||
"go-mod.ewintr.nl/planner/plan/storage"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
events map[string]item.Event
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func NewEvent() *Event {
|
||||
return &Event{
|
||||
events: make(map[string]item.Event),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Event) Find(id string) (item.Event, error) {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
event, exists := r.events[id]
|
||||
if !exists {
|
||||
return item.Event{}, storage.ErrNotFound
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (r *Event) FindAll() ([]item.Event, error) {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
events := make([]item.Event, 0, len(r.events))
|
||||
for _, event := range r.events {
|
||||
events = append(events, event)
|
||||
}
|
||||
sort.Slice(events, func(i, j int) bool {
|
||||
return events[i].ID < events[j].ID
|
||||
})
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (r *Event) Store(e item.Event) error {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
||||
r.events[e.ID] = e
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Event) Delete(id string) error {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
||||
if _, exists := r.events[id]; !exists {
|
||||
return storage.ErrNotFound
|
||||
}
|
||||
delete(r.events, id)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package memory
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"go-mod.ewintr.nl/planner/item"
|
||||
"go-mod.ewintr.nl/planner/plan/storage"
|
||||
)
|
||||
|
||||
type Task struct {
|
||||
tasks map[string]item.Task
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func NewTask() *Task {
|
||||
return &Task{
|
||||
tasks: make(map[string]item.Task),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Task) Find(id string) (item.Task, error) {
|
||||
t.mutex.RLock()
|
||||
defer t.mutex.RUnlock()
|
||||
|
||||
task, exists := t.tasks[id]
|
||||
if !exists {
|
||||
return item.Task{}, storage.ErrNotFound
|
||||
}
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func (t *Task) FindAll() ([]item.Task, error) {
|
||||
t.mutex.RLock()
|
||||
defer t.mutex.RUnlock()
|
||||
|
||||
tasks := make([]item.Task, 0, len(t.tasks))
|
||||
for _, event := range t.tasks {
|
||||
tasks = append(tasks, event)
|
||||
}
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].ID < tasks[j].ID
|
||||
})
|
||||
|
||||
return tasks, nil
|
||||
}
|
||||
|
||||
func (t *Task) Store(tsk item.Task) error {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
|
||||
t.tasks[tsk.ID] = tsk
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Task) Delete(id string) error {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
|
||||
if _, exists := t.tasks[id]; !exists {
|
||||
return storage.ErrNotFound
|
||||
}
|
||||
delete(t.tasks, id)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -6,50 +6,50 @@ import (
|
|||
"go-mod.ewintr.nl/planner/item"
|
||||
)
|
||||
|
||||
func TestEvent(t *testing.T) {
|
||||
func TestTask(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
mem := NewEvent()
|
||||
mem := NewTask()
|
||||
|
||||
t.Log("empty")
|
||||
actEvents, actErr := mem.FindAll()
|
||||
actTasks, actErr := mem.FindAll()
|
||||
if actErr != nil {
|
||||
t.Errorf("exp nil, got %v", actErr)
|
||||
}
|
||||
if len(actEvents) != 0 {
|
||||
t.Errorf("exp 0, got %d", len(actEvents))
|
||||
if len(actTasks) != 0 {
|
||||
t.Errorf("exp 0, got %d", len(actTasks))
|
||||
}
|
||||
|
||||
t.Log("store")
|
||||
e1 := item.Event{
|
||||
tsk1 := item.Task{
|
||||
ID: "id-1",
|
||||
}
|
||||
if err := mem.Store(e1); err != nil {
|
||||
if err := mem.Store(tsk1); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
|
||||
e2 := item.Event{
|
||||
tsk2 := item.Task{
|
||||
ID: "id-2",
|
||||
}
|
||||
if err := mem.Store(e2); err != nil {
|
||||
if err := mem.Store(tsk2); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
}
|
||||
|
||||
t.Log("find one")
|
||||
actEvent, actErr := mem.Find(e1.ID)
|
||||
actTask, actErr := mem.Find(tsk1.ID)
|
||||
if actErr != nil {
|
||||
t.Errorf("exp nil, got %v", actErr)
|
||||
}
|
||||
if actEvent.ID != e1.ID {
|
||||
t.Errorf("exp %v, got %v", e1.ID, actEvent.ID)
|
||||
if actTask.ID != tsk1.ID {
|
||||
t.Errorf("exp %v, got %v", tsk1.ID, actTask.ID)
|
||||
}
|
||||
|
||||
t.Log("find all")
|
||||
actEvents, actErr = mem.FindAll()
|
||||
actTasks, actErr = mem.FindAll()
|
||||
if actErr != nil {
|
||||
t.Errorf("exp nil, got %v", actErr)
|
||||
}
|
||||
if diff := item.EventDiffs([]item.Event{e1, e2}, actEvents); diff != "" {
|
||||
if diff := item.TaskDiffs([]item.Task{tsk1, tsk2}, actTasks); diff != "" {
|
||||
t.Errorf("(exp -, got +)\n%s", diff)
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
package sqlite
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go-mod.ewintr.nl/planner/item"
|
||||
"go-mod.ewintr.nl/planner/plan/storage"
|
||||
)
|
||||
|
||||
type SqliteEvent struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s *SqliteEvent) Store(event item.Event) error {
|
||||
var recurStr string
|
||||
if event.Recurrer != nil {
|
||||
recurStr = event.Recurrer.String()
|
||||
}
|
||||
if _, err := s.db.Exec(`
|
||||
INSERT INTO events
|
||||
(id, title, date, time, duration, recurrer)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE
|
||||
SET
|
||||
title=?,
|
||||
date=?,
|
||||
time=?,
|
||||
duration=?,
|
||||
recurrer=?
|
||||
`,
|
||||
event.ID, event.Title, event.Date.String(), event.Time.String(), event.Duration.String(), recurStr,
|
||||
event.Title, event.Date.String(), event.Time.String(), event.Duration.String(), recurStr); err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SqliteEvent) Find(id string) (item.Event, error) {
|
||||
var event item.Event
|
||||
var dateStr, timeStr, recurStr, durStr string
|
||||
err := s.db.QueryRow(`
|
||||
SELECT id, title, date, time, duration, recurrer
|
||||
FROM events
|
||||
WHERE id = ?`, id).Scan(&event.ID, &event.Title, &dateStr, &timeStr, &durStr, &recurStr)
|
||||
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)
|
||||
}
|
||||
event.Date = item.NewDateFromString(dateStr)
|
||||
event.Time = item.NewTimeFromString(timeStr)
|
||||
dur, err := time.ParseDuration(durStr)
|
||||
if err != nil {
|
||||
return item.Event{}, fmt.Errorf("could not unmarshal recurrer: %v", err)
|
||||
}
|
||||
event.Duration = dur
|
||||
event.Recurrer = item.NewRecurrer(recurStr)
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (s *SqliteEvent) FindAll() ([]item.Event, error) {
|
||||
rows, err := s.db.Query(`
|
||||
SELECT id, title, date, time, duration, recurrer
|
||||
FROM events`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
result := make([]item.Event, 0)
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var event item.Event
|
||||
var dateStr, timeStr, recurStr, durStr string
|
||||
if err := rows.Scan(&event.ID, &event.Title, &dateStr, &timeStr, &durStr, &recurStr); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
dur, err := time.ParseDuration(durStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
event.Date = item.NewDateFromString(dateStr)
|
||||
event.Time = item.NewTimeFromString(timeStr)
|
||||
event.Duration = dur
|
||||
event.Recurrer = item.NewRecurrer(recurStr)
|
||||
|
||||
result = append(result, event)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *SqliteEvent) Delete(id string) error {
|
||||
result, err := s.db.Exec(`
|
||||
DELETE FROM events
|
||||
WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return storage.ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -42,6 +42,7 @@ var migrations = []string{
|
|||
`ALTER TABLE events ADD COLUMN date TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE events ADD COLUMN time TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE items ADD COLUMN recur_next TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE events RENAME TO tasks`,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -51,7 +52,7 @@ var (
|
|||
ErrSqliteFailure = errors.New("sqlite returned an error")
|
||||
)
|
||||
|
||||
func NewSqlites(dbPath string) (*LocalID, *SqliteEvent, *SqliteSync, error) {
|
||||
func NewSqlites(dbPath string) (*LocalID, *SqliteTask, *SqliteSync, error) {
|
||||
db, err := sql.Open("sqlite", dbPath)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("%w: %v", ErrInvalidConfiguration, err)
|
||||
|
@ -60,7 +61,7 @@ func NewSqlites(dbPath string) (*LocalID, *SqliteEvent, *SqliteSync, error) {
|
|||
sl := &LocalID{
|
||||
db: db,
|
||||
}
|
||||
se := &SqliteEvent{
|
||||
se := &SqliteTask{
|
||||
db: db,
|
||||
}
|
||||
ss := &SqliteSync{
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package sqlite
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go-mod.ewintr.nl/planner/item"
|
||||
"go-mod.ewintr.nl/planner/plan/storage"
|
||||
)
|
||||
|
||||
type SqliteTask struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (t *SqliteTask) Store(tsk item.Task) error {
|
||||
var recurStr string
|
||||
if tsk.Recurrer != nil {
|
||||
recurStr = tsk.Recurrer.String()
|
||||
}
|
||||
if _, err := t.db.Exec(`
|
||||
INSERT INTO tasks
|
||||
(id, title, date, time, duration, recurrer)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE
|
||||
SET
|
||||
title=?,
|
||||
date=?,
|
||||
time=?,
|
||||
duration=?,
|
||||
recurrer=?
|
||||
`,
|
||||
tsk.ID, tsk.Title, tsk.Date.String(), tsk.Time.String(), tsk.Duration.String(), recurStr,
|
||||
tsk.Title, tsk.Date.String(), tsk.Time.String(), tsk.Duration.String(), recurStr); err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *SqliteTask) Find(id string) (item.Task, error) {
|
||||
var tsk item.Task
|
||||
var dateStr, timeStr, recurStr, durStr string
|
||||
err := t.db.QueryRow(`
|
||||
SELECT id, title, date, time, duration, recurrer
|
||||
FROM tasks
|
||||
WHERE id = ?`, id).Scan(&tsk.ID, &tsk.Title, &dateStr, &timeStr, &durStr, &recurStr)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return item.Task{}, fmt.Errorf("event not found: %w", err)
|
||||
case err != nil:
|
||||
return item.Task{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
tsk.Date = item.NewDateFromString(dateStr)
|
||||
tsk.Time = item.NewTimeFromString(timeStr)
|
||||
dur, err := time.ParseDuration(durStr)
|
||||
if err != nil {
|
||||
return item.Task{}, fmt.Errorf("could not unmarshal recurrer: %v", err)
|
||||
}
|
||||
tsk.Duration = dur
|
||||
tsk.Recurrer = item.NewRecurrer(recurStr)
|
||||
|
||||
return tsk, nil
|
||||
}
|
||||
|
||||
func (t *SqliteTask) FindAll() ([]item.Task, error) {
|
||||
rows, err := t.db.Query(`
|
||||
SELECT id, title, date, time, duration, recurrer
|
||||
FROM tasks`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
result := make([]item.Task, 0)
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var tsk item.Task
|
||||
var dateStr, timeStr, recurStr, durStr string
|
||||
if err := rows.Scan(&tsk.ID, &tsk.Title, &dateStr, &timeStr, &durStr, &recurStr); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
dur, err := time.ParseDuration(durStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
tsk.Date = item.NewDateFromString(dateStr)
|
||||
tsk.Time = item.NewTimeFromString(timeStr)
|
||||
tsk.Duration = dur
|
||||
tsk.Recurrer = item.NewRecurrer(recurStr)
|
||||
|
||||
result = append(result, tsk)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *SqliteTask) Delete(id string) error {
|
||||
result, err := s.db.Exec(`
|
||||
DELETE FROM tasks
|
||||
WHERE id = ?`, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return storage.ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -27,10 +27,10 @@ type Sync interface {
|
|||
LastUpdate() (time.Time, error)
|
||||
}
|
||||
|
||||
type Event interface {
|
||||
Store(event item.Event) error
|
||||
Find(id string) (item.Event, error)
|
||||
FindAll() ([]item.Event, error)
|
||||
type Task interface {
|
||||
Store(task item.Task) error
|
||||
Find(id string) (item.Task, error)
|
||||
FindAll() ([]item.Task, error)
|
||||
Delete(id string) error
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ func TestMemory(t *testing.T) {
|
|||
|
||||
now := time.Now()
|
||||
items := []item.Item{
|
||||
{ID: "a", Kind: item.KindTask, Updated: now.Add(-15 * time.Minute)},
|
||||
{ID: "b", Kind: item.KindEvent, Updated: now.Add(-10 * time.Minute)},
|
||||
{ID: "c", Kind: item.KindTask, Updated: now.Add(-5 * time.Minute)},
|
||||
{ID: "a", Kind: item.KindSchedule, Updated: now.Add(-15 * time.Minute)},
|
||||
{ID: "b", Kind: item.KindTask, Updated: now.Add(-10 * time.Minute)},
|
||||
{ID: "c", Kind: item.KindSchedule, Updated: now.Add(-5 * time.Minute)},
|
||||
}
|
||||
if err := mem.Update(items); err != nil {
|
||||
t.Errorf("exp nil, got %v", err)
|
||||
|
@ -37,12 +37,12 @@ func TestMemory(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "kind",
|
||||
ks: []item.Kind{item.KindEvent},
|
||||
ks: []item.Kind{item.KindTask},
|
||||
expItems: []item.Item{items[1]},
|
||||
},
|
||||
{
|
||||
name: "timestamp",
|
||||
ks: []item.Kind{item.KindTask, item.KindEvent},
|
||||
ks: []item.Kind{item.KindSchedule, item.KindTask},
|
||||
ts: now.Add(-10 * time.Minute),
|
||||
expItems: items[1:],
|
||||
},
|
||||
|
|
|
@ -59,9 +59,9 @@ func TestSyncGet(t *testing.T) {
|
|||
mem := NewMemory()
|
||||
|
||||
items := []item.Item{
|
||||
{ID: "id-0", Kind: item.KindEvent, Updated: now.Add(-10 * time.Minute)},
|
||||
{ID: "id-1", Kind: item.KindEvent, Updated: now.Add(-5 * time.Minute)},
|
||||
{ID: "id-2", Kind: item.KindTask, Updated: now.Add(time.Minute)},
|
||||
{ID: "id-0", Kind: item.KindTask, Updated: now.Add(-10 * time.Minute)},
|
||||
{ID: "id-1", Kind: item.KindTask, Updated: now.Add(-5 * time.Minute)},
|
||||
{ID: "id-2", Kind: item.KindSchedule, Updated: now.Add(time.Minute)},
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
|
@ -93,7 +93,7 @@ func TestSyncGet(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "kind",
|
||||
ks: []string{string(item.KindTask)},
|
||||
ks: []string{string(item.KindSchedule)},
|
||||
expStatus: http.StatusOK,
|
||||
expItems: []item.Item{items[2]},
|
||||
},
|
||||
|
@ -171,20 +171,20 @@ func TestSyncPost(t *testing.T) {
|
|||
{
|
||||
name: "invalid item",
|
||||
reqBody: []byte(`[
|
||||
{"id":"id-1","kind":"event","updated":"2024-09-06T08:00:00Z"},
|
||||
{"id":"id-1","kind":"task","updated":"2024-09-06T08:00:00Z"},
|
||||
]`),
|
||||
expStatus: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "normal",
|
||||
reqBody: []byte(`[
|
||||
{"id":"id-1","kind":"event","updated":"2024-09-06T08:00:00Z","deleted":false,"body":"item"},
|
||||
{"id":"id-2","kind":"event","updated":"2024-09-06T08:12:00Z","deleted":false,"body":"item2"}
|
||||
{"id":"id-1","kind":"task","updated":"2024-09-06T08:00:00Z","deleted":false,"body":"item"},
|
||||
{"id":"id-2","kind":"task","updated":"2024-09-06T08:12:00Z","deleted":false,"body":"item2"}
|
||||
]`),
|
||||
expStatus: http.StatusNoContent,
|
||||
expItems: []item.Item{
|
||||
{ID: "id-1", Kind: item.KindEvent, Updated: time.Date(2024, 9, 6, 8, 0, 0, 0, time.UTC)},
|
||||
{ID: "id-2", Kind: item.KindEvent, Updated: time.Date(2024, 9, 6, 12, 0, 0, 0, time.UTC)},
|
||||
{ID: "id-1", Kind: item.KindTask, Updated: time.Date(2024, 9, 6, 8, 0, 0, 0, time.UTC)},
|
||||
{ID: "id-2", Kind: item.KindTask, Updated: time.Date(2024, 9, 6, 12, 0, 0, 0, time.UTC)},
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
|
|
@ -27,6 +27,7 @@ var migrations = []string{
|
|||
ALTER COLUMN recur_next SET NOT NULL,
|
||||
ALTER COLUMN recur_next SET DEFAULT ''`,
|
||||
`ALTER TABLE items ADD COLUMN date TEXT NOT NULL DEFAULT ''`,
|
||||
`UPDATE items SET kind='task'`,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -19,12 +19,12 @@ func TestRecur(t *testing.T) {
|
|||
|
||||
testItem := item.Item{
|
||||
ID: "test-1",
|
||||
Kind: item.KindEvent,
|
||||
Kind: item.KindTask,
|
||||
Updated: now,
|
||||
Deleted: false,
|
||||
Recurrer: item.NewRecurrer("2024-01-01, daily"),
|
||||
RecurNext: today,
|
||||
Body: `{"title":"Test Event","start":"2024-01-01T10:00:00Z","duration":"30m"}`,
|
||||
Body: `{"title":"Test task","start":"2024-01-01T10:00:00Z","duration":"30m"}`,
|
||||
}
|
||||
|
||||
// Store the item
|
||||
|
@ -38,7 +38,7 @@ func TestRecur(t *testing.T) {
|
|||
}
|
||||
|
||||
// Verify results
|
||||
items, err := mem.Updated([]item.Kind{item.KindEvent}, now)
|
||||
items, err := mem.Updated([]item.Kind{item.KindTask}, now)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get updated items: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue