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
|
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{
|
return &Done{
|
||||||
doner: updater,
|
doner: updater,
|
||||||
|
|
|
@ -23,7 +23,7 @@ func NewUpdate(localId int, conf *configuration.Configuration, cmdArgs []string)
|
||||||
}
|
}
|
||||||
|
|
||||||
disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP()))
|
disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP()))
|
||||||
fields, err := ParseTaskFieldArgs(cmdArgs)
|
update, err := ParseTaskFieldArgs(cmdArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Update{}, err
|
return &Update{}, err
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,9 @@ func NewUpdate(localId int, conf *configuration.Configuration, cmdArgs []string)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Update{}, err
|
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{
|
return &Update{
|
||||||
updater: updater,
|
updater: updater,
|
||||||
|
@ -47,33 +48,40 @@ func (u *Update) Do() string {
|
||||||
return "message sent\n"
|
return "message sent\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseTaskFieldArgs(args []string) (task.LocalUpdate, error) {
|
func ParseTaskFieldArgs(args []string) (*task.LocalUpdate, error) {
|
||||||
lu := task.LocalUpdate{}
|
lu := &task.LocalUpdate{}
|
||||||
|
|
||||||
var action []string
|
action, fields := []string{}, []string{}
|
||||||
for _, f := range args {
|
for _, f := range args {
|
||||||
split := strings.SplitN(f, ":", 2)
|
split := strings.SplitN(f, ":", 2)
|
||||||
if len(split) == 2 {
|
if len(split) == 2 {
|
||||||
switch split[0] {
|
switch split[0] {
|
||||||
case "project":
|
case "project":
|
||||||
if lu.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]
|
lu.Project = split[1]
|
||||||
|
fields = append(fields, task.FIELD_PROJECT)
|
||||||
case "due":
|
case "due":
|
||||||
if !lu.Due.IsZero() {
|
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])
|
lu.Due = task.NewDateFromString(split[1])
|
||||||
|
fields = append(fields, task.FIELD_DUE)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
action = append(action, f)
|
if len(f) > 0 {
|
||||||
|
action = append(action, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(action) > 0 {
|
if len(action) > 0 {
|
||||||
lu.Action = strings.Join(action, " ")
|
lu.Action = strings.Join(action, " ")
|
||||||
|
fields = append(fields, task.FIELD_ACTION)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lu.Fields = fields
|
||||||
|
|
||||||
return lu, nil
|
return lu, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,24 +14,28 @@ func TestParseTaskFieldArgs(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
input string
|
input string
|
||||||
expUpdate task.LocalUpdate
|
expUpdate *task.LocalUpdate
|
||||||
expErr error
|
expErr error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
expUpdate: task.LocalUpdate{},
|
expUpdate: &task.LocalUpdate{
|
||||||
|
Fields: []string{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "join action",
|
name: "join action",
|
||||||
input: "some things to do",
|
input: "some things to do",
|
||||||
expUpdate: task.LocalUpdate{
|
expUpdate: &task.LocalUpdate{
|
||||||
|
Fields: []string{task.FIELD_ACTION},
|
||||||
Action: "some things to do",
|
Action: "some things to do",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "all",
|
name: "all",
|
||||||
input: "project:project do stuff due:2021-08-06",
|
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",
|
Action: "do stuff",
|
||||||
Project: "project",
|
Project: "project",
|
||||||
Due: task.NewDate(2021, 8, 6),
|
Due: task.NewDate(2021, 8, 6),
|
||||||
|
@ -40,14 +44,15 @@ func TestParseTaskFieldArgs(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "no action",
|
name: "no action",
|
||||||
input: "due:2021-08-06",
|
input: "due:2021-08-06",
|
||||||
expUpdate: task.LocalUpdate{
|
expUpdate: &task.LocalUpdate{
|
||||||
Due: task.NewDate(2021, 8, 6),
|
Fields: []string{task.FIELD_DUE},
|
||||||
|
Due: task.NewDate(2021, 8, 6),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two projects",
|
name: "two projects",
|
||||||
input: "project:project1 project:project2",
|
input: "project:project1 project:project2",
|
||||||
expUpdate: task.LocalUpdate{},
|
expUpdate: &task.LocalUpdate{},
|
||||||
expErr: command.ErrFieldAlreadyUsed,
|
expErr: command.ErrFieldAlreadyUsed,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
|
|
@ -17,10 +17,10 @@ type Update struct {
|
||||||
local storage.LocalRepository
|
local storage.LocalRepository
|
||||||
disp *storage.Dispatcher
|
disp *storage.Dispatcher
|
||||||
taskId string
|
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{
|
return &Update{
|
||||||
local: local,
|
local: local,
|
||||||
disp: disp,
|
disp: disp,
|
||||||
|
@ -34,13 +34,11 @@ func (u *Update) Process() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
|
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
|
||||||
}
|
}
|
||||||
u.update.ForVersion = tsk.Version
|
tsk.AddUpdate(u.update)
|
||||||
if err := u.local.SetLocalUpdate(tsk.LocalId, &u.update); err != nil {
|
if err := u.local.SetLocalUpdate(tsk); err != nil {
|
||||||
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
|
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
|
||||||
}
|
}
|
||||||
|
tsk.ApplyUpdate()
|
||||||
tsk.Apply(u.update)
|
|
||||||
|
|
||||||
if err := u.disp.Dispatch(&tsk.Task); err != nil {
|
if err := u.disp.Dispatch(&tsk.Task); err != nil {
|
||||||
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
|
return fmt.Errorf("%w: %v", ErrUpdateTask, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
func TestUpdate(t *testing.T) {
|
func TestUpdate(t *testing.T) {
|
||||||
task1 := &task.Task{
|
task1 := &task.Task{
|
||||||
Id: "id-1",
|
Id: "id-1",
|
||||||
|
Version: 2,
|
||||||
Project: "project1",
|
Project: "project1",
|
||||||
Action: "action1",
|
Action: "action1",
|
||||||
Due: task.NewDate(2021, 7, 29),
|
Due: task.NewDate(2021, 7, 29),
|
||||||
|
@ -23,16 +24,19 @@ func TestUpdate(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
updates task.LocalUpdate
|
updates *task.LocalUpdate
|
||||||
exp *task.Task
|
exp *task.Task
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "done",
|
name: "done",
|
||||||
updates: task.LocalUpdate{
|
updates: &task.LocalUpdate{
|
||||||
Done: true,
|
ForVersion: 2,
|
||||||
|
Fields: []string{task.FIELD_DONE},
|
||||||
|
Done: true,
|
||||||
},
|
},
|
||||||
exp: &task.Task{
|
exp: &task.Task{
|
||||||
Id: "id-1",
|
Id: "id-1",
|
||||||
|
Version: 2,
|
||||||
Project: "project1",
|
Project: "project1",
|
||||||
Action: "action1",
|
Action: "action1",
|
||||||
Due: task.NewDate(2021, 7, 29),
|
Due: task.NewDate(2021, 7, 29),
|
||||||
|
@ -42,13 +46,16 @@ func TestUpdate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "fields",
|
name: "fields",
|
||||||
updates: task.LocalUpdate{
|
updates: &task.LocalUpdate{
|
||||||
Project: "project2",
|
ForVersion: 2,
|
||||||
Action: "action2",
|
Fields: []string{task.FIELD_ACTION, task.FIELD_PROJECT, task.FIELD_DUE},
|
||||||
Due: task.NewDate(2021, 8, 1),
|
Project: "project2",
|
||||||
|
Action: "action2",
|
||||||
|
Due: task.NewDate(2021, 8, 1),
|
||||||
},
|
},
|
||||||
exp: &task.Task{
|
exp: &task.Task{
|
||||||
Id: "id-1",
|
Id: "id-1",
|
||||||
|
Version: 2,
|
||||||
Project: "project2",
|
Project: "project2",
|
||||||
Action: "action2",
|
Action: "action2",
|
||||||
Due: task.NewDate(2021, 8, 1),
|
Due: task.NewDate(2021, 8, 1),
|
||||||
|
|
|
@ -19,7 +19,7 @@ type LocalRepository interface {
|
||||||
FindAllInProject(project string) ([]*task.LocalTask, error)
|
FindAllInProject(project string) ([]*task.LocalTask, error)
|
||||||
FindById(id string) (*task.LocalTask, error)
|
FindById(id string) (*task.LocalTask, error)
|
||||||
FindByLocalId(id int) (*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 {
|
func NextLocalId(used []int) int {
|
||||||
|
|
|
@ -113,15 +113,10 @@ func (m *Memory) FindByLocalId(localId int) (*task.LocalTask, error) {
|
||||||
return &task.LocalTask{}, ErrTaskNotFound
|
return &task.LocalTask{}, ErrTaskNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Memory) SetLocalUpdate(localId int, localUpdate *task.LocalUpdate) error {
|
func (m *Memory) SetLocalUpdate(tsk *task.LocalTask) error {
|
||||||
t, err := m.FindByLocalId(localId)
|
m.localData[tsk.Id] = localData{
|
||||||
if err != nil {
|
LocalId: tsk.LocalId,
|
||||||
return err
|
LocalUpdate: tsk.LocalUpdate,
|
||||||
}
|
|
||||||
|
|
||||||
m.localData[t.Id] = localData{
|
|
||||||
LocalId: localId,
|
|
||||||
LocalUpdate: localUpdate,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -109,7 +109,12 @@ func TestMemory(t *testing.T) {
|
||||||
Recur: task.NewRecurrer("today, weekly, monday"),
|
Recur: task.NewRecurrer("today, weekly, monday"),
|
||||||
Done: true,
|
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)
|
actTask, err := mem.FindByLocalId(2)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
test.Equals(t, expUpdate, actTask.LocalUpdate)
|
test.Equals(t, expUpdate, actTask.LocalUpdate)
|
||||||
|
|
|
@ -222,11 +222,11 @@ func (s *Sqlite) FindByLocalId(localId int) (*task.LocalTask, error) {
|
||||||
return t, nil
|
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(`
|
if _, err := s.db.Exec(`
|
||||||
UPDATE local_task
|
UPDATE local_task
|
||||||
SET local_update = ?
|
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)
|
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,22 +13,40 @@ type LocalTask struct {
|
||||||
LocalUpdate *LocalUpdate
|
LocalUpdate *LocalUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lt *LocalTask) Apply(lu LocalUpdate) {
|
func (lt *LocalTask) AddUpdate(update *LocalUpdate) {
|
||||||
if lu.Action != "" {
|
if lt.LocalUpdate == nil {
|
||||||
lt.Action = lu.Action
|
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 {
|
u := lt.LocalUpdate
|
||||||
lt.Recur = lu.Recur
|
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 {
|
||||||
if lu.Done {
|
case FIELD_ACTION:
|
||||||
lt.Done = lu.Done
|
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
|
type ByDue []*LocalTask
|
||||||
|
@ -55,6 +73,7 @@ func (lt ByDefault) Less(i, j int) bool {
|
||||||
|
|
||||||
type LocalUpdate struct {
|
type LocalUpdate struct {
|
||||||
ForVersion int
|
ForVersion int
|
||||||
|
Fields []string
|
||||||
Action string
|
Action string
|
||||||
Project string
|
Project string
|
||||||
Due Date
|
Due Date
|
||||||
|
@ -62,6 +81,39 @@ type LocalUpdate struct {
|
||||||
Done bool
|
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) {
|
func (lu LocalUpdate) Value() (driver.Value, error) {
|
||||||
var recurStr string
|
var recurStr string
|
||||||
if lu.Recur != nil {
|
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