improve list options

This commit is contained in:
Erik Winter 2025-01-04 11:03:57 +01:00
parent c1698a9ec3
commit 6158f76517
12 changed files with 169 additions and 91 deletions

BIN
dist/plan vendored

Binary file not shown.

View File

@ -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)
} }

View File

@ -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 {

View File

@ -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
} }

View File

@ -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 {

View File

@ -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):

View File

@ -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 {

View File

@ -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):

View File

@ -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)

View File

@ -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 = ?`)

View File

@ -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

View File

@ -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,
}, },
}, },
{ {