local update restructure
This commit is contained in:
parent
5fcd6de546
commit
06a8f3153a
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
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{
|
||||
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,
|
||||
},
|
||||
} {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
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{
|
||||
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),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
}
|
||||
if lu.Done {
|
||||
lt.Done = lu.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 {
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue