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