update command
This commit is contained in:
parent
05db15c62d
commit
f3c64cca5a
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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])
|
}
|
||||||
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue