improve list options
This commit is contained in:
parent
c1698a9ec3
commit
6158f76517
|
@ -90,7 +90,7 @@ type Add struct {
|
||||||
Args AddArgs
|
Args AddArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Add) Do(deps Dependencies) (CommandResult, error) {
|
func (a Add) Do(deps Dependencies) (CommandResult, error) {
|
||||||
if err := deps.TaskRepo.Store(a.Args.Task); err != nil {
|
if err := deps.TaskRepo.Store(a.Args.Task); err != nil {
|
||||||
return nil, fmt.Errorf("could not store event: %v", err)
|
return nil, fmt.Errorf("could not store event: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ type Delete struct {
|
||||||
Args DeleteArgs
|
Args DeleteArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (del *Delete) Do(deps Dependencies) (CommandResult, error) {
|
func (del Delete) Do(deps Dependencies) (CommandResult, error) {
|
||||||
var id string
|
var id string
|
||||||
idMap, err := deps.LocalIDRepo.FindAll()
|
idMap, err := deps.LocalIDRepo.FindAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,13 +12,19 @@ import (
|
||||||
|
|
||||||
type ListArgs struct {
|
type ListArgs struct {
|
||||||
fieldTPL map[string][]string
|
fieldTPL map[string][]string
|
||||||
params storage.TaskListParams
|
HasRecurrer bool
|
||||||
|
From item.Date
|
||||||
|
To item.Date
|
||||||
|
Project string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListArgs() ListArgs {
|
func NewListArgs() ListArgs {
|
||||||
return ListArgs{
|
return ListArgs{
|
||||||
fieldTPL: map[string][]string{
|
fieldTPL: map[string][]string{
|
||||||
"project": {"p", "project"},
|
"project": {"p", "project"},
|
||||||
|
"from": {"f", "from"},
|
||||||
|
"to": {"t", "to"},
|
||||||
|
"recurring": {"rec", "recurring"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,63 +38,74 @@ func (la ListArgs) Parse(main []string, fields map[string]string) (Command, erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
today := item.NewDate(now.Year(), int(now.Month()), now.Day())
|
today := item.NewDate(now.Year(), int(now.Month()), now.Day())
|
||||||
tomorrow := item.NewDate(now.Year(), int(now.Month()), now.Day()+1)
|
|
||||||
var date item.Date
|
|
||||||
var includeBefore, recurrer bool
|
|
||||||
var project string
|
|
||||||
|
|
||||||
switch len(main) {
|
switch len(main) {
|
||||||
case 0:
|
case 0:
|
||||||
date = today
|
fields["to"] = today.String()
|
||||||
includeBefore = true
|
|
||||||
case 1:
|
case 1:
|
||||||
switch {
|
switch {
|
||||||
case slices.Contains([]string{"today", "tod"}, main[0]):
|
case slices.Contains([]string{"tod", "today"}, main[0]):
|
||||||
date = today
|
fields["to"] = today.String()
|
||||||
includeBefore = true
|
case slices.Contains([]string{"tom", "tomorrow"}, main[0]):
|
||||||
case slices.Contains([]string{"tomorrow", "tom"}, main[0]):
|
fields["from"] = today.Add(1).String()
|
||||||
date = tomorrow
|
fields["to"] = today.Add(1).String()
|
||||||
case main[0] == "list" || main[0] == "l":
|
case main[0] == "week":
|
||||||
|
fields["from"] = today.String()
|
||||||
|
fields["to"] = today.Add(7).String()
|
||||||
|
case main[0] == "recur":
|
||||||
|
fields["recurring"] = "true"
|
||||||
|
case main[0] == "list":
|
||||||
|
fields["from"] = today.String()
|
||||||
|
fields["to"] = today.String()
|
||||||
|
default:
|
||||||
|
return nil, ErrWrongCommand
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fromDate, toDate item.Date
|
||||||
|
var hasRecurrer bool
|
||||||
|
var project string
|
||||||
|
if val, ok := fields["from"]; ok {
|
||||||
|
fromDate = item.NewDateFromString(val)
|
||||||
|
}
|
||||||
|
if val, ok := fields["to"]; ok {
|
||||||
|
toDate = item.NewDateFromString(val)
|
||||||
|
}
|
||||||
|
if val, ok := fields["recurrer"]; ok && val == "true" {
|
||||||
|
hasRecurrer = true
|
||||||
|
}
|
||||||
if val, ok := fields["project"]; ok {
|
if val, ok := fields["project"]; ok {
|
||||||
project = val
|
project = val
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return nil, ErrWrongCommand
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
if main[0] == "list" && main[1] == "recur" {
|
|
||||||
recurrer = true
|
|
||||||
} else {
|
|
||||||
return nil, ErrWrongCommand
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nil, ErrWrongCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
return &List{
|
return List{
|
||||||
args: ListArgs{
|
Args: ListArgs{
|
||||||
params: storage.TaskListParams{
|
HasRecurrer: hasRecurrer,
|
||||||
Date: date,
|
From: fromDate,
|
||||||
IncludeBefore: includeBefore,
|
To: toDate,
|
||||||
Recurrer: recurrer,
|
|
||||||
Project: project,
|
Project: project,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type List struct {
|
type List struct {
|
||||||
args ListArgs
|
Args ListArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *List) Do(deps Dependencies) (CommandResult, error) {
|
func (list List) Do(deps Dependencies) (CommandResult, error) {
|
||||||
localIDs, err := deps.LocalIDRepo.FindAll()
|
localIDs, err := deps.LocalIDRepo.FindAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not get local ids: %v", err)
|
return nil, fmt.Errorf("could not get local ids: %v", err)
|
||||||
}
|
}
|
||||||
all, err := deps.TaskRepo.FindMany(list.args.params)
|
all, err := deps.TaskRepo.FindMany(storage.TaskListParams{
|
||||||
|
HasRecurrer: list.Args.HasRecurrer,
|
||||||
|
From: list.Args.From,
|
||||||
|
To: list.Args.To,
|
||||||
|
Project: list.Args.Project,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,82 @@ package command_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"go-mod.ewintr.nl/planner/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
"go-mod.ewintr.nl/planner/plan/command"
|
"go-mod.ewintr.nl/planner/plan/command"
|
||||||
"go-mod.ewintr.nl/planner/plan/storage/memory"
|
"go-mod.ewintr.nl/planner/plan/storage/memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestListParse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
now := time.Now()
|
||||||
|
today := item.NewDate(now.Year(), int(now.Month()), now.Day())
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
main []string
|
||||||
|
fields map[string]string
|
||||||
|
expArgs command.ListArgs
|
||||||
|
expErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
main: []string{},
|
||||||
|
fields: map[string]string{},
|
||||||
|
expArgs: command.ListArgs{
|
||||||
|
To: today,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "today",
|
||||||
|
main: []string{"tod"},
|
||||||
|
fields: map[string]string{},
|
||||||
|
expArgs: command.ListArgs{
|
||||||
|
To: today,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tomorrow",
|
||||||
|
main: []string{"tom"},
|
||||||
|
fields: map[string]string{},
|
||||||
|
expArgs: command.ListArgs{
|
||||||
|
From: today.Add(1),
|
||||||
|
To: today.Add(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "week",
|
||||||
|
main: []string{"week"},
|
||||||
|
fields: map[string]string{},
|
||||||
|
expArgs: command.ListArgs{
|
||||||
|
From: today,
|
||||||
|
To: today.Add(7),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
nla := command.NewListArgs()
|
||||||
|
cmd, actErr := nla.Parse(tc.main, tc.fields)
|
||||||
|
if tc.expErr != (actErr != nil) {
|
||||||
|
t.Errorf("exp %v, got %v", tc.expErr, actErr != nil)
|
||||||
|
}
|
||||||
|
if tc.expErr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
listCmd, ok := cmd.(command.List)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("exp true, got false")
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tc.expArgs, listCmd.Args, cmpopts.IgnoreTypes(map[string][]string{})); diff != "" {
|
||||||
|
t.Errorf("(+exp, -got)\n%s\n", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestList(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -29,42 +99,25 @@ func TestList(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
main []string
|
cmd command.List
|
||||||
expRes bool
|
expRes bool
|
||||||
expErr bool
|
expErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
main: []string{},
|
|
||||||
expRes: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list",
|
|
||||||
main: []string{"list"},
|
|
||||||
expRes: true,
|
expRes: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty list",
|
name: "empty list",
|
||||||
main: []string{"list", "recur"},
|
cmd: command.List{
|
||||||
|
Args: command.ListArgs{
|
||||||
|
HasRecurrer: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "wrong",
|
|
||||||
main: []string{"delete"},
|
|
||||||
expErr: true,
|
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
// parse
|
res, err := tc.cmd.Do(command.Dependencies{
|
||||||
cmd, actErr := command.NewListArgs().Parse(tc.main, nil)
|
|
||||||
if tc.expErr != (actErr != nil) {
|
|
||||||
t.Errorf("exp %v, got %v", tc.expErr, actErr)
|
|
||||||
}
|
|
||||||
if tc.expErr {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// do
|
|
||||||
res, err := cmd.Do(command.Dependencies{
|
|
||||||
TaskRepo: taskRepo,
|
TaskRepo: taskRepo,
|
||||||
LocalIDRepo: localRepo,
|
LocalIDRepo: localRepo,
|
||||||
})
|
})
|
||||||
|
@ -72,7 +125,6 @@ func TestList(t *testing.T) {
|
||||||
t.Errorf("exp nil, got %v", err)
|
t.Errorf("exp nil, got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check
|
|
||||||
listRes := res.(command.ListResult)
|
listRes := res.(command.ListResult)
|
||||||
actRes := len(listRes.Tasks) > 0
|
actRes := len(listRes.Tasks) > 0
|
||||||
if tc.expRes != actRes {
|
if tc.expRes != actRes {
|
||||||
|
|
|
@ -38,7 +38,7 @@ type Show struct {
|
||||||
args ShowArgs
|
args ShowArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Show) Do(deps Dependencies) (CommandResult, error) {
|
func (s Show) Do(deps Dependencies) (CommandResult, error) {
|
||||||
id, err := deps.LocalIDRepo.FindOne(s.args.localID)
|
id, err := deps.LocalIDRepo.FindOne(s.args.localID)
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, storage.ErrNotFound):
|
case errors.Is(err, storage.ErrNotFound):
|
||||||
|
|
|
@ -25,7 +25,7 @@ func (sa SyncArgs) Parse(main []string, flags map[string]string) (Command, error
|
||||||
|
|
||||||
type Sync struct{}
|
type Sync struct{}
|
||||||
|
|
||||||
func (s *Sync) Do(deps Dependencies) (CommandResult, error) {
|
func (s Sync) Do(deps Dependencies) (CommandResult, error) {
|
||||||
// local new and updated
|
// local new and updated
|
||||||
sendItems, err := deps.SyncRepo.FindAll()
|
sendItems, err := deps.SyncRepo.FindAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -90,7 +90,7 @@ type Update struct {
|
||||||
args UpdateArgs
|
args UpdateArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Update) Do(deps Dependencies) (CommandResult, error) {
|
func (u Update) Do(deps Dependencies) (CommandResult, error) {
|
||||||
id, err := deps.LocalIDRepo.FindOne(u.args.LocalID)
|
id, err := deps.LocalIDRepo.FindOne(u.args.LocalID)
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, storage.ErrNotFound):
|
case errors.Is(err, storage.ErrNotFound):
|
||||||
|
|
|
@ -55,9 +55,9 @@ func TestTask(t *testing.T) {
|
||||||
t.Errorf("(exp -, got +)\n%s", diff)
|
t.Errorf("(exp -, got +)\n%s", diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("fond some")
|
t.Log("find some")
|
||||||
actTasks, actErr = mem.FindMany(storage.TaskListParams{
|
actTasks, actErr = mem.FindMany(storage.TaskListParams{
|
||||||
Date: item.NewDate(2024, 12, 29),
|
From: item.NewDate(2024, 12, 29),
|
||||||
})
|
})
|
||||||
if actErr != nil {
|
if actErr != nil {
|
||||||
t.Errorf("exp nil, got %v", actErr)
|
t.Errorf("exp nil, got %v", actErr)
|
||||||
|
|
|
@ -69,16 +69,16 @@ func (t *SqliteTask) FindMany(params storage.TaskListParams) ([]item.Task, error
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
|
|
||||||
where := []string{`recurrer = ''`}
|
where := []string{`recurrer = ''`}
|
||||||
if params.Recurrer {
|
if params.HasRecurrer {
|
||||||
where[0] = `recurrer != ''`
|
where[0] = `recurrer != ''`
|
||||||
}
|
}
|
||||||
if !params.Date.IsZero() && !params.IncludeBefore {
|
if !params.From.IsZero() {
|
||||||
where = append(where, `date = ?`)
|
where = append(where, `date >= ?`)
|
||||||
args = append(args, params.Date.String())
|
args = append(args, params.From.String())
|
||||||
}
|
}
|
||||||
if !params.Date.IsZero() && params.IncludeBefore {
|
if !params.To.IsZero() {
|
||||||
where = append(where, `date <= ?`)
|
where = append(where, `date <= ?`)
|
||||||
args = append(args, params.Date.String())
|
args = append(args, params.To.String())
|
||||||
}
|
}
|
||||||
if params.Project != "" {
|
if params.Project != "" {
|
||||||
where = append(where, `project = ?`)
|
where = append(where, `project = ?`)
|
||||||
|
|
|
@ -29,9 +29,10 @@ type Sync interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TaskListParams struct {
|
type TaskListParams struct {
|
||||||
Recurrer bool
|
HasRecurrer bool
|
||||||
Date item.Date
|
HasDate bool
|
||||||
IncludeBefore bool
|
From item.Date
|
||||||
|
To item.Date
|
||||||
Project string
|
Project string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,16 +44,17 @@ type Task interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Match(tsk item.Task, params TaskListParams) bool {
|
func Match(tsk item.Task, params TaskListParams) bool {
|
||||||
if params.Recurrer && tsk.Recurrer == nil {
|
if params.HasRecurrer && tsk.Recurrer == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !params.Date.IsZero() {
|
if params.HasDate && tsk.Date.IsZero() {
|
||||||
if !params.IncludeBefore && !params.Date.Equal(tsk.Date) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if params.IncludeBefore && tsk.Date.After(params.Date) {
|
if !params.From.IsZero() && params.From.After(tsk.Date) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !params.To.IsZero() && tsk.Date.After(params.To) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
if params.Project != "" && params.Project != tsk.Project {
|
if params.Project != "" && params.Project != tsk.Project {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -21,7 +21,7 @@ func TestMatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
tskNotMatch := item.Task{
|
tskNotMatch := item.Task{
|
||||||
ID: "id",
|
ID: "id",
|
||||||
Date: item.NewDate(2024, 12, 28),
|
Date: item.NewDate(2024, 12, 20),
|
||||||
TaskBody: item.TaskBody{
|
TaskBody: item.TaskBody{
|
||||||
Title: "name",
|
Title: "name",
|
||||||
Project: "p2",
|
Project: "p2",
|
||||||
|
@ -33,15 +33,22 @@ func TestMatch(t *testing.T) {
|
||||||
params storage.TaskListParams
|
params storage.TaskListParams
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "date",
|
name: "from",
|
||||||
params: storage.TaskListParams{
|
params: storage.TaskListParams{
|
||||||
Date: item.NewDate(2024, 12, 29),
|
From: item.NewDate(2024, 12, 29),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "to",
|
||||||
|
params: storage.TaskListParams{
|
||||||
|
From: item.NewDate(2024, 12, 24),
|
||||||
|
To: item.NewDate(2024, 12, 29),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "recurrer",
|
name: "recurrer",
|
||||||
params: storage.TaskListParams{
|
params: storage.TaskListParams{
|
||||||
Recurrer: true,
|
HasRecurrer: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue