local update restructure

This commit is contained in:
Erik Winter 2021-08-22 13:29:04 +02:00
parent 5fcd6de546
commit 06a8f3153a
11 changed files with 198 additions and 56 deletions

View File

@ -26,7 +26,12 @@ func NewDone(localId int, conf *configuration.Configuration) (*Done, error) {
return &Done{}, err
}
updater := process.NewUpdate(local, disp, localTask.Id, task.LocalUpdate{Done: true})
update := &task.LocalUpdate{
ForVersion: localTask.Version,
Fields: []string{task.FIELD_DONE},
Done: true,
}
updater := process.NewUpdate(local, disp, localTask.Id, update)
return &Done{
doner: updater,

View File

@ -23,7 +23,7 @@ func NewUpdate(localId int, conf *configuration.Configuration, cmdArgs []string)
}
disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP()))
fields, err := ParseTaskFieldArgs(cmdArgs)
update, err := ParseTaskFieldArgs(cmdArgs)
if err != nil {
return &Update{}, err
}
@ -31,8 +31,9 @@ func NewUpdate(localId int, conf *configuration.Configuration, cmdArgs []string)
if err != nil {
return &Update{}, err
}
update.ForVersion = localTask.Version
updater := process.NewUpdate(local, disp, localTask.Id, fields)
updater := process.NewUpdate(local, disp, localTask.Id, update)
return &Update{
updater: updater,
@ -47,33 +48,40 @@ func (u *Update) Do() string {
return "message sent\n"
}
func ParseTaskFieldArgs(args []string) (task.LocalUpdate, error) {
lu := task.LocalUpdate{}
func ParseTaskFieldArgs(args []string) (*task.LocalUpdate, error) {
lu := &task.LocalUpdate{}
var action []string
action, fields := []string{}, []string{}
for _, f := range args {
split := strings.SplitN(f, ":", 2)
if len(split) == 2 {
switch split[0] {
case "project":
if lu.Project != "" {
return task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_PROJECT)
return &task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_PROJECT)
}
lu.Project = split[1]
fields = append(fields, task.FIELD_PROJECT)
case "due":
if !lu.Due.IsZero() {
return task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_DUE)
return &task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_DUE)
}
lu.Due = task.NewDateFromString(split[1])
fields = append(fields, task.FIELD_DUE)
}
} else {
action = append(action, f)
if len(f) > 0 {
action = append(action, f)
}
}
}
if len(action) > 0 {
lu.Action = strings.Join(action, " ")
fields = append(fields, task.FIELD_ACTION)
}
lu.Fields = fields
return lu, nil
}

View File

@ -14,24 +14,28 @@ func TestParseTaskFieldArgs(t *testing.T) {
for _, tc := range []struct {
name string
input string
expUpdate task.LocalUpdate
expUpdate *task.LocalUpdate
expErr error
}{
{
name: "empty",
expUpdate: task.LocalUpdate{},
name: "empty",
expUpdate: &task.LocalUpdate{
Fields: []string{},
},
},
{
name: "join action",
input: "some things to do",
expUpdate: task.LocalUpdate{
expUpdate: &task.LocalUpdate{
Fields: []string{task.FIELD_ACTION},
Action: "some things to do",
},
},
{
name: "all",
input: "project:project do stuff due:2021-08-06",
expUpdate: task.LocalUpdate{
expUpdate: &task.LocalUpdate{
Fields: []string{task.FIELD_PROJECT, task.FIELD_DUE, task.FIELD_ACTION},
Action: "do stuff",
Project: "project",
Due: task.NewDate(2021, 8, 6),
@ -40,14 +44,15 @@ func TestParseTaskFieldArgs(t *testing.T) {
{
name: "no action",
input: "due:2021-08-06",
expUpdate: task.LocalUpdate{
Due: task.NewDate(2021, 8, 6),
expUpdate: &task.LocalUpdate{
Fields: []string{task.FIELD_DUE},
Due: task.NewDate(2021, 8, 6),
},
},
{
name: "two projects",
input: "project:project1 project:project2",
expUpdate: task.LocalUpdate{},
expUpdate: &task.LocalUpdate{},
expErr: command.ErrFieldAlreadyUsed,
},
} {

View File

@ -17,10 +17,10 @@ type Update struct {
local storage.LocalRepository
disp *storage.Dispatcher
taskId string
update task.LocalUpdate
update *task.LocalUpdate
}
func NewUpdate(local storage.LocalRepository, disp *storage.Dispatcher, taskId string, update task.LocalUpdate) *Update {
func NewUpdate(local storage.LocalRepository, disp *storage.Dispatcher, taskId string, update *task.LocalUpdate) *Update {
return &Update{
local: local,
disp: disp,
@ -34,13 +34,11 @@ func (u *Update) Process() error {
if err != nil {
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
}
u.update.ForVersion = tsk.Version
if err := u.local.SetLocalUpdate(tsk.LocalId, &u.update); err != nil {
tsk.AddUpdate(u.update)
if err := u.local.SetLocalUpdate(tsk); err != nil {
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
}
tsk.Apply(u.update)
tsk.ApplyUpdate()
if err := u.disp.Dispatch(&tsk.Task); err != nil {
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
}

View File

@ -13,6 +13,7 @@ import (
func TestUpdate(t *testing.T) {
task1 := &task.Task{
Id: "id-1",
Version: 2,
Project: "project1",
Action: "action1",
Due: task.NewDate(2021, 7, 29),
@ -23,16 +24,19 @@ func TestUpdate(t *testing.T) {
for _, tc := range []struct {
name string
updates task.LocalUpdate
updates *task.LocalUpdate
exp *task.Task
}{
{
name: "done",
updates: task.LocalUpdate{
Done: true,
updates: &task.LocalUpdate{
ForVersion: 2,
Fields: []string{task.FIELD_DONE},
Done: true,
},
exp: &task.Task{
Id: "id-1",
Version: 2,
Project: "project1",
Action: "action1",
Due: task.NewDate(2021, 7, 29),
@ -42,13 +46,16 @@ func TestUpdate(t *testing.T) {
},
{
name: "fields",
updates: task.LocalUpdate{
Project: "project2",
Action: "action2",
Due: task.NewDate(2021, 8, 1),
updates: &task.LocalUpdate{
ForVersion: 2,
Fields: []string{task.FIELD_ACTION, task.FIELD_PROJECT, task.FIELD_DUE},
Project: "project2",
Action: "action2",
Due: task.NewDate(2021, 8, 1),
},
exp: &task.Task{
Id: "id-1",
Version: 2,
Project: "project2",
Action: "action2",
Due: task.NewDate(2021, 8, 1),

View File

@ -19,7 +19,7 @@ type LocalRepository interface {
FindAllInProject(project string) ([]*task.LocalTask, error)
FindById(id string) (*task.LocalTask, error)
FindByLocalId(id int) (*task.LocalTask, error)
SetLocalUpdate(localId int, localUpdate *task.LocalUpdate) error
SetLocalUpdate(tsk *task.LocalTask) error
}
func NextLocalId(used []int) int {

View File

@ -113,15 +113,10 @@ func (m *Memory) FindByLocalId(localId int) (*task.LocalTask, error) {
return &task.LocalTask{}, ErrTaskNotFound
}
func (m *Memory) SetLocalUpdate(localId int, localUpdate *task.LocalUpdate) error {
t, err := m.FindByLocalId(localId)
if err != nil {
return err
}
m.localData[t.Id] = localData{
LocalId: localId,
LocalUpdate: localUpdate,
func (m *Memory) SetLocalUpdate(tsk *task.LocalTask) error {
m.localData[tsk.Id] = localData{
LocalId: tsk.LocalId,
LocalUpdate: tsk.LocalUpdate,
}
return nil

View File

@ -109,7 +109,12 @@ func TestMemory(t *testing.T) {
Recur: task.NewRecurrer("today, weekly, monday"),
Done: true,
}
test.OK(t, mem.SetLocalUpdate(2, expUpdate))
lt := &task.LocalTask{
Task: *task2,
LocalId: 2,
LocalUpdate: expUpdate,
}
test.OK(t, mem.SetLocalUpdate(lt))
actTask, err := mem.FindByLocalId(2)
test.OK(t, err)
test.Equals(t, expUpdate, actTask.LocalUpdate)

View File

@ -222,11 +222,11 @@ func (s *Sqlite) FindByLocalId(localId int) (*task.LocalTask, error) {
return t, nil
}
func (s *Sqlite) SetLocalUpdate(localId int, localUpdate *task.LocalUpdate) error {
func (s *Sqlite) SetLocalUpdate(tsk *task.LocalTask) error {
if _, err := s.db.Exec(`
UPDATE local_task
SET local_update = ?
WHERE local_id = ?`, localUpdate, localId); err != nil {
WHERE local_id = ?`, tsk.LocalUpdate, tsk.LocalId); err != nil {
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
}

View File

@ -13,22 +13,40 @@ type LocalTask struct {
LocalUpdate *LocalUpdate
}
func (lt *LocalTask) Apply(lu LocalUpdate) {
if lu.Action != "" {
lt.Action = lu.Action
func (lt *LocalTask) AddUpdate(update *LocalUpdate) {
if lt.LocalUpdate == nil {
lt.LocalUpdate = &LocalUpdate{}
}
if lu.Project != "" {
lt.Project = lu.Project
lt.LocalUpdate.Add(update)
}
func (lt *LocalTask) ApplyUpdate() {
if lt.LocalUpdate == nil {
return
}
if lu.Recur != nil {
lt.Recur = lu.Recur
u := lt.LocalUpdate
if u.ForVersion == 0 || u.ForVersion != lt.Version {
lt.LocalUpdate = &LocalUpdate{}
return
}
if !lu.Due.IsZero() {
lt.Due = lu.Due
}
if lu.Done {
lt.Done = lu.Done
for _, field := range u.Fields {
switch field {
case FIELD_ACTION:
lt.Action = u.Action
case FIELD_PROJECT:
lt.Project = u.Project
case FIELD_DUE:
lt.Due = u.Due
case FIELD_RECUR:
lt.Recur = u.Recur
case FIELD_DONE:
lt.Done = u.Done
}
}
lt.LocalUpdate = &LocalUpdate{}
}
type ByDue []*LocalTask
@ -55,6 +73,7 @@ func (lt ByDefault) Less(i, j int) bool {
type LocalUpdate struct {
ForVersion int
Fields []string
Action string
Project string
Due Date
@ -62,6 +81,39 @@ type LocalUpdate struct {
Done bool
}
func (lu *LocalUpdate) Add(newUpdate *LocalUpdate) {
if lu.ForVersion > newUpdate.ForVersion {
return
}
lu.ForVersion = newUpdate.ForVersion
for _, nf := range newUpdate.Fields {
switch nf {
case FIELD_ACTION:
lu.Action = newUpdate.Action
case FIELD_PROJECT:
lu.Project = newUpdate.Project
case FIELD_DUE:
lu.Due = newUpdate.Due
case FIELD_RECUR:
lu.Recur = newUpdate.Recur
case FIELD_DONE:
lu.Done = newUpdate.Done
}
add := true
for _, of := range lu.Fields {
if nf == of {
add = false
break
}
}
if add {
lu.Fields = append(lu.Fields, nf)
}
}
}
func (lu LocalUpdate) Value() (driver.Value, error) {
var recurStr string
if lu.Recur != nil {

View File

@ -0,0 +1,67 @@
package task_test
import (
"testing"
"git.ewintr.nl/go-kit/test"
"git.ewintr.nl/gte/internal/task"
)
func TestLocalTaskApply(t *testing.T) {
for _, tc := range []struct {
name string
input *task.LocalTask
exp *task.LocalTask
}{
{
name: "empty",
input: &task.LocalTask{
Task: task.Task{
Action: "action",
Project: "project",
Due: task.NewDate(2021, 8, 22),
},
LocalUpdate: &task.LocalUpdate{},
},
exp: &task.LocalTask{
Task: task.Task{
Action: "action",
Project: "project",
Due: task.NewDate(2021, 8, 22),
},
LocalUpdate: &task.LocalUpdate{},
},
},
{
name: "all",
input: &task.LocalTask{
Task: task.Task{
Version: 3,
},
LocalUpdate: &task.LocalUpdate{
ForVersion: 3,
Fields: []string{task.FIELD_ACTION, task.FIELD_PROJECT, task.FIELD_DUE, task.FIELD_DONE},
Action: "action",
Project: "project",
Due: task.NewDate(2021, 8, 22),
Done: true,
},
},
exp: &task.LocalTask{
Task: task.Task{
Version: 3,
Action: "action",
Project: "project",
Due: task.NewDate(2021, 8, 22),
Done: true,
},
LocalUpdate: &task.LocalUpdate{},
},
},
} {
t.Run(tc.name, func(t *testing.T) {
tc.input.ApplyUpdate()
test.Equals(t, tc.exp, tc.input)
})
}
}