update command

This commit is contained in:
Erik Winter 2021-07-29 07:01:24 +02:00
parent 05db15c62d
commit f3c64cca5a
6 changed files with 241 additions and 39 deletions

View File

@ -2,13 +2,16 @@ package command
import ( import (
"errors" "errors"
"fmt"
"strconv" "strconv"
"git.ewintr.nl/gte/internal/configuration" "git.ewintr.nl/gte/internal/configuration"
"git.ewintr.nl/gte/internal/storage"
) )
var ( var (
ErrInvalidAmountOfArgs = errors.New("invalid amount of args") ErrInvalidAmountOfArgs = errors.New("invalid amount of args")
ErrCouldNotFindTask = errors.New("could not find task")
) )
type Command interface { type Command interface {
@ -47,11 +50,34 @@ func parseTaskCommand(id int, tArgs []string, conf *configuration.Configuration)
return NewShow(id, conf) return NewShow(id, conf)
} }
cmd, _ := tArgs[0], tArgs[1:] cmd, cmdArgs := tArgs[0], tArgs[1:]
switch cmd { switch cmd {
case "done": case "done":
fallthrough
case "del":
return NewDone(id, conf) return NewDone(id, conf)
case "mod":
return NewUpdate(id, conf, cmdArgs)
default: default:
return NewShow(id, conf) return NewShow(id, conf)
} }
} }
func findId(id int, local storage.LocalRepository) (string, error) {
localIds, err := local.LocalIds()
if err != nil {
return "", fmt.Errorf("%w: %v", ErrCouldNotFindTask, err)
}
var tId string
for remoteId, localId := range localIds {
if localId == id {
tId = remoteId
break
}
}
if tId == "" {
return "", ErrCouldNotFindTask
}
return tId, nil
}

View File

@ -1,8 +1,6 @@
package command package command
import ( import (
"fmt"
"git.ewintr.nl/gte/cmd/cli/format" "git.ewintr.nl/gte/cmd/cli/format"
"git.ewintr.nl/gte/internal/configuration" "git.ewintr.nl/gte/internal/configuration"
"git.ewintr.nl/gte/internal/process" "git.ewintr.nl/gte/internal/process"
@ -17,7 +15,7 @@ type Done struct {
func (d *Done) Cmd() string { return "done" } func (d *Done) Cmd() string { return "done" }
func NewDone(id int, conf *configuration.Configuration) (*Done, error) { func NewDone(localId int, conf *configuration.Configuration) (*Done, error) {
local, err := storage.NewSqlite(conf.Sqlite()) local, err := storage.NewSqlite(conf.Sqlite())
if err != nil { if err != nil {
return &Done{}, err return &Done{}, err
@ -25,20 +23,10 @@ func NewDone(id int, conf *configuration.Configuration) (*Done, error) {
disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP())) disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP()))
fields := process.UpdateFields{"done": "true"} fields := process.UpdateFields{"done": "true"}
localIds, err := local.LocalIds() tId, err := findId(localId, local)
if err != nil { if err != nil {
return &Done{}, err return &Done{}, err
} }
var tId string
for remoteId, localId := range localIds {
if localId == id {
tId = remoteId
break
}
}
if tId == "" {
return &Done{}, fmt.Errorf("could not find task")
}
updater := process.NewUpdate(local, disp, tId, fields) updater := process.NewUpdate(local, disp, tId, fields)

86
cmd/cli/command/update.go Normal file
View File

@ -0,0 +1,86 @@
package command
import (
"errors"
"fmt"
"strings"
"git.ewintr.nl/gte/cmd/cli/format"
"git.ewintr.nl/gte/internal/configuration"
"git.ewintr.nl/gte/internal/process"
"git.ewintr.nl/gte/internal/storage"
"git.ewintr.nl/gte/internal/task"
"git.ewintr.nl/gte/pkg/msend"
)
var (
ErrFieldAlreadyUsed = errors.New("field was already used")
)
type Update struct {
updater *process.Update
}
func (u *Update) Cmd() string { return "update" }
func NewUpdate(localId int, conf *configuration.Configuration, cmdArgs []string) (*Update, error) {
local, err := storage.NewSqlite(conf.Sqlite())
if err != nil {
return &Update{}, err
}
disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP()))
fields, err := ParseTaskFieldArgs(cmdArgs)
if err != nil {
return &Update{}, err
}
tId, err := findId(localId, local)
if err != nil {
return &Update{}, err
}
updater := process.NewUpdate(local, disp, tId, fields)
return &Update{
updater: updater,
}, nil
}
func (u *Update) Do() string {
if err := u.updater.Process(); err != nil {
return format.FormatError(err)
}
return "message sent\n"
}
func ParseTaskFieldArgs(args []string) (process.UpdateFields, error) {
result := process.UpdateFields{}
var action []string
for _, f := range args {
split := strings.SplitN(f, ":", 2)
if len(split) == 2 {
switch split[0] {
case "project":
if _, ok := result[task.FIELD_PROJECT]; ok {
return process.UpdateFields{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_PROJECT)
}
result[task.FIELD_PROJECT] = split[1]
case "due":
if _, ok := result[task.FIELD_DUE]; ok {
return process.UpdateFields{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_DUE)
}
result[task.FIELD_DUE] = split[1]
}
} else {
action = append(action, f)
}
}
if len(action) > 0 {
result[task.FIELD_ACTION] = strings.Join(action, " ")
}
return result, nil
}

View File

@ -0,0 +1,64 @@
package command_test
import (
"errors"
"strings"
"testing"
"git.ewintr.nl/go-kit/test"
"git.ewintr.nl/gte/cmd/cli/command"
"git.ewintr.nl/gte/internal/process"
"git.ewintr.nl/gte/internal/task"
)
func TestParseTaskFieldArgs(t *testing.T) {
for _, tc := range []struct {
name string
input string
expField process.UpdateFields
expErr error
}{
{
name: "empty",
expField: process.UpdateFields{
task.FIELD_ACTION: "",
},
},
{
name: "join action",
input: "some things to do",
expField: process.UpdateFields{
task.FIELD_ACTION: "some things to do",
},
},
{
name: "all",
input: "project:project do stuff due:2021-08-06",
expField: process.UpdateFields{
task.FIELD_ACTION: "do stuff",
task.FIELD_PROJECT: "project",
task.FIELD_DUE: "2021-08-06",
},
},
{
name: "no action",
input: "due:2021-08-06",
expField: process.UpdateFields{
task.FIELD_DUE: "2021-08-06",
},
},
{
name: "two projects",
input: "project:project1 project:project2",
expField: process.UpdateFields{},
expErr: command.ErrFieldAlreadyUsed,
},
} {
t.Run(tc.name, func(t *testing.T) {
args := strings.Split(tc.input, " ")
act, err := command.ParseTaskFieldArgs(args)
test.Equals(t, tc.expField, act)
test.Assert(t, errors.Is(err, tc.expErr), "wrong err")
})
}
}

View File

@ -5,10 +5,11 @@ import (
"fmt" "fmt"
"git.ewintr.nl/gte/internal/storage" "git.ewintr.nl/gte/internal/storage"
"git.ewintr.nl/gte/internal/task"
) )
var ( var (
ErrUpdateTask = errors.New("could not update task") ErrUpdateTask = errors.New("could not update tsk")
) )
// Update dispatches an updated version of a task // Update dispatches an updated version of a task
@ -31,21 +32,27 @@ func NewUpdate(local storage.LocalRepository, disp *storage.Dispatcher, taskId s
} }
func (u *Update) Process() error { func (u *Update) Process() error {
task, err := u.local.FindById(u.taskId) tsk, err := u.local.FindById(u.taskId)
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrUpdateTask, err) return fmt.Errorf("%w: %v", ErrUpdateTask, err)
} }
for k, v := range u.updates { for k, v := range u.updates {
switch k { switch k {
case "done": case task.FIELD_DONE:
if v == "true" { if v == "true" {
task.Done = true tsk.Done = true
} }
case task.FIELD_DUE:
tsk.Due = task.NewDateFromString(v)
case task.FIELD_ACTION:
tsk.Action = v
case task.FIELD_PROJECT:
tsk.Project = v
} }
} }
if err := u.disp.Dispatch(task); err != nil { if err := u.disp.Dispatch(tsk); err != nil {
return fmt.Errorf("%w: %v", ErrUpdateTask, err) return fmt.Errorf("%w: %v", ErrUpdateTask, err)
} }

View File

@ -15,29 +15,60 @@ func TestUpdate(t *testing.T) {
Id: "id-1", Id: "id-1",
Project: "project1", Project: "project1",
Action: "action1", Action: "action1",
Due: task.NewDate(2021, 7, 29),
Folder: task.FOLDER_PLANNED, Folder: task.FOLDER_PLANNED,
} }
local := storage.NewMemory() local := storage.NewMemory()
out := msend.NewMemory()
disp := storage.NewDispatcher(out)
allTasks := []*task.Task{task1} allTasks := []*task.Task{task1}
t.Run("done", func(t *testing.T) { for _, tc := range []struct {
local.SetTasks(allTasks) name string
updates := process.UpdateFields{ updates process.UpdateFields
"done": "true", exp *task.Task
} }{
{
name: "done",
updates: process.UpdateFields{
task.FIELD_DONE: "true",
},
exp: &task.Task{
Id: "id-1",
Project: "project1",
Action: "action1",
Due: task.NewDate(2021, 7, 29),
Folder: task.FOLDER_PLANNED,
Done: true,
},
},
{
name: "fields",
updates: process.UpdateFields{
task.FIELD_PROJECT: "project2",
task.FIELD_ACTION: "action2",
task.FIELD_DUE: "2021-08-01",
},
exp: &task.Task{
Id: "id-1",
Project: "project2",
Action: "action2",
Due: task.NewDate(2021, 8, 1),
Folder: task.FOLDER_PLANNED,
},
},
} {
t.Run(tc.name, func(t *testing.T) {
local.SetTasks(allTasks)
out := msend.NewMemory()
disp := storage.NewDispatcher(out)
update := process.NewUpdate(local, disp, task1.Id, updates) update := process.NewUpdate(local, disp, task1.Id, tc.updates)
test.OK(t, update.Process()) test.OK(t, update.Process())
expTask := task1 expMsg := &msend.Message{
expTask.Done = true Subject: tc.exp.FormatSubject(),
expMsg := &msend.Message{ Body: tc.exp.FormatBody(),
Subject: expTask.FormatSubject(), }
Body: expTask.FormatBody(), test.Assert(t, len(out.Messages) == 1, "amount of messages was not one")
} test.Equals(t, expMsg, out.Messages[0])
test.Assert(t, len(out.Messages) == 1, "amount of messages was not one") })
test.Equals(t, expMsg, out.Messages[0]) }
})
} }