aboutsummaryrefslogtreecommitdiffstats
path: root/todolist
diff options
context:
space:
mode:
authorGrant Ammons <gammons@gmail.com>2016-06-12 09:49:38 -0400
committerGrant Ammons <gammons@gmail.com>2016-06-12 09:49:38 -0400
commitd8d4510d2faebff633d6e98fa4812f2461ae85b6 (patch)
treebe474ce669a994767867f2224d8cdd4103271aee /todolist
parentfd9121e03c18c7dfd947e98ea4cec545f110a804 (diff)
Refactor todolist stuff out of the file store implementation
Diffstat (limited to 'todolist')
-rw-r--r--todolist/app.go56
-rw-r--r--todolist/file_store.go114
-rw-r--r--todolist/file_store_test.go69
-rw-r--r--todolist/filter_test.go20
-rw-r--r--todolist/grouper_test.go10
-rw-r--r--todolist/store.go14
-rw-r--r--todolist/todo_list.go98
-rw-r--r--todolist/todo_list_test.go73
8 files changed, 238 insertions, 216 deletions
diff --git a/todolist/app.go b/todolist/app.go
index 7d3ccb2..81326aa 100644
--- a/todolist/app.go
+++ b/todolist/app.go
@@ -8,33 +8,35 @@ import (
)
type App struct {
- TodoStore Store
+ TodoStore *FileStore
+ TodoList *TodoList
}
func NewApp() *App {
- app := &App{TodoStore: NewFileStore()}
+ app := &App{TodoList: &TodoList{}, TodoStore: NewFileStore()}
return app
}
func (a *App) InitializeRepo() {
a.TodoStore.Initialize()
- fmt.Println("Todo repo initialized.")
}
func (a *App) AddTodo(input string) {
+ a.load()
parser := &Parser{}
todo := parser.ParseNewTodo(input)
- a.TodoStore.Add(todo)
- a.TodoStore.Save()
+ a.TodoList.Add(todo)
+ a.save()
fmt.Println("Todo added.")
}
func (a *App) DeleteTodo(input string) {
+ a.load()
id := a.getId(input)
if id != -1 {
- a.TodoStore.Delete(id)
- a.TodoStore.Save()
+ a.TodoList.Delete(id)
+ a.save()
fmt.Println("Todo deleted.")
} else {
fmt.Println("Could not find id.")
@@ -42,10 +44,11 @@ func (a *App) DeleteTodo(input string) {
}
func (a *App) CompleteTodo(input string) {
+ a.load()
id := a.getId(input)
if id != -1 {
- a.TodoStore.Complete(id)
- a.TodoStore.Save()
+ a.TodoList.Complete(id)
+ a.save()
fmt.Println("Todo completed.")
} else {
fmt.Println("Could not find id.")
@@ -53,10 +56,11 @@ func (a *App) CompleteTodo(input string) {
}
func (a *App) UncompleteTodo(input string) {
+ a.load()
id := a.getId(input)
if id != -1 {
- a.TodoStore.Uncomplete(id)
- a.TodoStore.Save()
+ a.TodoList.Uncomplete(id)
+ a.save()
fmt.Println("Todo uncompleted.")
} else {
fmt.Println("Could not find id.")
@@ -64,10 +68,11 @@ func (a *App) UncompleteTodo(input string) {
}
func (a *App) ArchiveTodo(input string) {
+ a.load()
id := a.getId(input)
if id != -1 {
- a.TodoStore.Archive(id)
- a.TodoStore.Save()
+ a.TodoList.Archive(id)
+ a.save()
fmt.Println("Todo archived.")
} else {
fmt.Println("Could not find id.")
@@ -75,10 +80,11 @@ func (a *App) ArchiveTodo(input string) {
}
func (a *App) UnarchiveTodo(input string) {
+ a.load()
id := a.getId(input)
if id != -1 {
- a.TodoStore.Unarchive(id)
- a.TodoStore.Save()
+ a.TodoList.Unarchive(id)
+ a.save()
fmt.Println("Todo unarchived.")
} else {
fmt.Println("Could not find id.")
@@ -86,12 +92,13 @@ func (a *App) UnarchiveTodo(input string) {
}
func (a *App) EditTodoDue(input string) {
+ a.load()
id := a.getId(input)
if id != -1 {
- todo := a.TodoStore.FindById(id)
+ todo := a.TodoList.FindById(id)
parser := &Parser{}
todo.Due = parser.Due(input, time.Now())
- a.TodoStore.Save()
+ a.save()
fmt.Println("Todo due date updated.")
} else {
fmt.Println("Could not find id.")
@@ -99,17 +106,19 @@ func (a *App) EditTodoDue(input string) {
}
func (a *App) ArchiveCompleted() {
- for _, todo := range a.TodoStore.Todos() {
+ a.load()
+ for _, todo := range a.TodoList.Todos() {
if todo.Completed {
todo.Archived = true
}
}
- a.TodoStore.Save()
+ a.save()
fmt.Println("All archived todos completed.")
}
func (a *App) ListTodos(input string) {
- filtered := NewFilter(a.TodoStore.Todos()).Filter(input)
+ a.load()
+ filtered := NewFilter(a.TodoList.Todos()).Filter(input)
grouped := a.getGroups(input, filtered)
formatter := NewFormatter(grouped)
@@ -143,3 +152,10 @@ func (a *App) getGroups(input string, todos []*Todo) *GroupedTodos {
}
return grouped
}
+
+func (a *App) save() {
+ a.TodoStore.Save(a.TodoList.Data)
+}
+func (a *App) load() {
+ a.TodoList.Load(a.TodoStore.Load())
+}
diff --git a/todolist/file_store.go b/todolist/file_store.go
index faf235f..61e6e7c 100644
--- a/todolist/file_store.go
+++ b/todolist/file_store.go
@@ -5,12 +5,10 @@ import (
"fmt"
"io/ioutil"
"os"
- "sort"
)
type FileStore struct {
FileLocation string
- Data []*Todo
Loaded bool
}
@@ -18,80 +16,7 @@ func NewFileStore() *FileStore {
return &FileStore{FileLocation: ".todos.json", Loaded: false}
}
-func (f *FileStore) Add(todo *Todo) {
- f.Load()
- todo.Id = f.NextId()
- f.Data = append(f.Data, todo)
-}
-
-func (f *FileStore) FindById(id int) *Todo {
- f.Load()
- for _, todo := range f.Data {
- if todo.Id == id {
- return todo
- }
- }
- return nil
-}
-
-func (f *FileStore) Delete(id int) {
- f.Load()
- i := -1
- for index, todo := range f.Data {
- if todo.Id == id {
- i = index
- }
- }
-
- f.Data = append(f.Data[:i], f.Data[i+1:]...)
-}
-
-func (f *FileStore) Complete(id int) {
- f.Load()
- todo := f.FindById(id)
- todo.Completed = true
- f.Delete(id)
- f.Data = append(f.Data, todo)
-}
-
-func (f *FileStore) Uncomplete(id int) {
- f.Load()
- todo := f.FindById(id)
- todo.Completed = false
- f.Delete(id)
- f.Data = append(f.Data, todo)
-}
-
-func (f *FileStore) Archive(id int) {
- f.Load()
- todo := f.FindById(id)
- todo.Archived = true
- f.Delete(id)
- f.Data = append(f.Data, todo)
-}
-
-func (f *FileStore) Unarchive(id int) {
- f.Load()
- todo := f.FindById(id)
- todo.Archived = false
- f.Delete(id)
- f.Data = append(f.Data, todo)
-}
-
-func (f *FileStore) IndexOf(todoToFind *Todo) int {
- for i, todo := range f.Data {
- if todo.Id == todoToFind.Id {
- return i
- }
- }
- return -1
-}
-
-func (f *FileStore) Load() {
- if f.Loaded {
- return
- }
-
+func (f *FileStore) Load() []*Todo {
data, err := ioutil.ReadFile(f.FileLocation)
if err != nil {
fmt.Println("No todo file found!")
@@ -99,12 +24,15 @@ func (f *FileStore) Load() {
os.Exit(0)
}
- jerr := json.Unmarshal(data, &f.Data)
+ var todos []*Todo
+ jerr := json.Unmarshal(data, &todos)
if jerr != nil {
fmt.Println("Error reading json data", jerr)
os.Exit(1)
}
f.Loaded = true
+
+ return todos
}
func (f *FileStore) Initialize() {
@@ -115,38 +43,14 @@ func (f *FileStore) Initialize() {
}
if err := ioutil.WriteFile(f.FileLocation, []byte("[]"), 0644); err != nil {
fmt.Println("Error writing json file", err)
+ os.Exit(1)
}
+ fmt.Println("Todo repo initialized.")
}
-func (f *FileStore) Save() {
- data, _ := json.Marshal(f.Data)
+func (f *FileStore) Save(todos []*Todo) {
+ data, _ := json.Marshal(todos)
if err := ioutil.WriteFile(f.FileLocation, []byte(data), 0644); err != nil {
fmt.Println("Error writing json file", err)
}
}
-
-type ByDate []*Todo
-
-func (a ByDate) Len() int { return len(a) }
-func (a ByDate) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a ByDate) Less(i, j int) bool {
- t1Due := a[i].CalculateDueTime()
- t2Due := a[j].CalculateDueTime()
- return t1Due.Before(t2Due)
-}
-
-func (f *FileStore) Todos() []*Todo {
- f.Load()
- sort.Sort(ByDate(f.Data))
- return f.Data
-}
-
-func (f *FileStore) NextId() int {
- maxId := 0
- for _, todo := range f.Data {
- if todo.Id > maxId {
- maxId = todo.Id
- }
- }
- return maxId + 1
-}
diff --git a/todolist/file_store_test.go b/todolist/file_store_test.go
index a83863b..0bd194d 100644
--- a/todolist/file_store_test.go
+++ b/todolist/file_store_test.go
@@ -9,73 +9,12 @@ import (
func TestFileStore(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(store.Data[0].Subject, "this is the first subject", "")
+ todos := store.Load()
+ assert.Equal(todos[0].Subject, "this is the first subject", "")
}
func TestSave(t *testing.T) {
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- store.Save()
-}
-
-func TestNextId(t *testing.T) {
- assert := assert.New(t)
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(3, store.NextId())
-}
-
-func TestIndexOf(t *testing.T) {
- assert := assert.New(t)
- todo := &Todo{Subject: "Grant"}
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
-
- assert.Equal(-1, store.IndexOf(todo))
- assert.Equal(0, store.IndexOf(store.Data[0]))
-}
-
-func TestDelete(t *testing.T) {
- assert := assert.New(t)
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(2, len(store.Data))
- store.Delete(1)
- assert.Equal(1, len(store.Data))
-}
-
-func TestComplete(t *testing.T) {
- assert := assert.New(t)
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(false, store.FindById(1).Completed)
- store.Complete(1)
- assert.Equal(true, store.FindById(1).Completed)
-}
-
-func TestArchive(t *testing.T) {
- assert := assert.New(t)
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(false, store.FindById(2).Archived)
- store.Archive(2)
- assert.Equal(true, store.FindById(2).Archived)
-}
-func TestUnarchive(t *testing.T) {
- assert := assert.New(t)
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(true, store.FindById(1).Archived)
- store.Unarchive(1)
- assert.Equal(false, store.FindById(1).Archived)
-}
-
-func TestUncomplete(t *testing.T) {
- assert := assert.New(t)
- store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- assert.Equal(true, store.FindById(2).Completed)
- store.Uncomplete(2)
- assert.Equal(false, store.FindById(2).Completed)
+ todos := store.Load()
+ store.Save(todos)
}
diff --git a/todolist/filter_test.go b/todolist/filter_test.go
index 13e2b20..59c0daa 100644
--- a/todolist/filter_test.go
+++ b/todolist/filter_test.go
@@ -9,8 +9,9 @@ import (
func TestFilterArchived(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- filter := NewFilter(store.Todos())
+ list := &TodoList{}
+ list.Load(store.Load())
+ filter := NewFilter(list.Todos())
archived := filter.filterArchived("l archived")
assert.Equal(1, len(archived))
assert.Equal(true, archived[0].Archived)
@@ -19,8 +20,9 @@ func TestFilterArchived(t *testing.T) {
func TestFilterUnarchivedByDefault(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- filter := NewFilter(store.Todos())
+ list := &TodoList{}
+ list.Load(store.Load())
+ filter := NewFilter(list.Todos())
unarchived := filter.filterArchived("l")
assert.Equal(1, len(unarchived))
assert.Equal(false, unarchived[0].Archived)
@@ -29,8 +31,9 @@ func TestFilterUnarchivedByDefault(t *testing.T) {
func TestGetArchived(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- filter := NewFilter(store.Todos())
+ list := &TodoList{}
+ list.Load(store.Load())
+ filter := NewFilter(list.Todos())
archived := filter.getArchived()
assert.Equal(1, len(archived))
assert.Equal(true, archived[0].Archived)
@@ -39,8 +42,9 @@ func TestGetArchived(t *testing.T) {
func TestGetUnarchived(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
- filter := NewFilter(store.Todos())
+ list := &TodoList{}
+ list.Load(store.Load())
+ filter := NewFilter(list.Todos())
unarchived := filter.getUnarchived()
assert.Equal(1, len(unarchived))
assert.Equal(false, unarchived[0].Archived)
diff --git a/todolist/grouper_test.go b/todolist/grouper_test.go
index 0b610f0..4b79703 100644
--- a/todolist/grouper_test.go
+++ b/todolist/grouper_test.go
@@ -10,10 +10,11 @@ func TestGroupByContext(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
+ list := &TodoList{}
+ list.Load(store.Load())
grouper := &Grouper{}
- grouped := grouper.GroupByContext(store.Todos())
+ grouped := grouper.GroupByContext(list.Todos())
assert.Equal(2, len(grouped.Groups["root"]), "")
assert.Equal(1, len(grouped.Groups["more"]), "")
@@ -23,10 +24,11 @@ func TestGroupByProject(t *testing.T) {
assert := assert.New(t)
store := &FileStore{FileLocation: "todos.json"}
- store.Load()
+ list := &TodoList{}
+ list.Load(store.Load())
grouper := &Grouper{}
- grouped := grouper.GroupByProject(store.Todos())
+ grouped := grouper.GroupByProject(list.Todos())
assert.Equal(2, len(grouped.Groups["test1"]), "")
}
diff --git a/todolist/store.go b/todolist/store.go
index b488408..518a30e 100644
--- a/todolist/store.go
+++ b/todolist/store.go
@@ -4,18 +4,4 @@ type Store interface {
Initialize()
Load()
Save()
- Todos() []*Todo
-
- Add(t *Todo)
- Delete(id int)
-
- Complete(id int)
- Uncomplete(id int)
-
- Archive(id int)
- Unarchive(id int)
-
- IndexOf(t *Todo) int
- FindById(id int) *Todo
- NextId() int
}
diff --git a/todolist/todo_list.go b/todolist/todo_list.go
new file mode 100644
index 0000000..d7e1f83
--- /dev/null
+++ b/todolist/todo_list.go
@@ -0,0 +1,98 @@
+package todolist
+
+import "sort"
+
+type TodoList struct {
+ Data []*Todo
+}
+
+func (t *TodoList) Load(todos []*Todo) {
+ t.Data = todos
+}
+
+func (t *TodoList) Add(todo *Todo) {
+ todo.Id = t.NextId()
+ t.Data = append(t.Data, todo)
+}
+
+func (t *TodoList) Delete(id int) {
+ i := -1
+ for index, todo := range t.Data {
+ if todo.Id == id {
+ i = index
+ }
+ }
+
+ t.Data = append(t.Data[:i], t.Data[i+1:]...)
+}
+
+func (t *TodoList) Complete(id int) {
+ todo := t.FindById(id)
+ todo.Completed = true
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+}
+
+func (t *TodoList) Uncomplete(id int) {
+ todo := t.FindById(id)
+ todo.Completed = false
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+}
+
+func (t *TodoList) Archive(id int) {
+ todo := t.FindById(id)
+ todo.Archived = true
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+}
+
+func (t *TodoList) Unarchive(id int) {
+ todo := t.FindById(id)
+ todo.Archived = false
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+}
+
+func (t *TodoList) IndexOf(todoToFind *Todo) int {
+ for i, todo := range t.Data {
+ if todo.Id == todoToFind.Id {
+ return i
+ }
+ }
+ return -1
+}
+
+type ByDate []*Todo
+
+func (a ByDate) Len() int { return len(a) }
+func (a ByDate) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByDate) Less(i, j int) bool {
+ t1Due := a[i].CalculateDueTime()
+ t2Due := a[j].CalculateDueTime()
+ return t1Due.Before(t2Due)
+}
+
+func (t *TodoList) Todos() []*Todo {
+ sort.Sort(ByDate(t.Data))
+ return t.Data
+}
+
+func (t *TodoList) NextId() int {
+ maxId := 0
+ for _, todo := range t.Data {
+ if todo.Id > maxId {
+ maxId = todo.Id
+ }
+ }
+ return maxId + 1
+}
+
+func (t *TodoList) FindById(id int) *Todo {
+ for _, todo := range t.Data {
+ if todo.Id == id {
+ return todo
+ }
+ }
+ return nil
+}
diff --git a/todolist/todo_list_test.go b/todolist/todo_list_test.go
new file mode 100644
index 0000000..941106d
--- /dev/null
+++ b/todolist/todo_list_test.go
@@ -0,0 +1,73 @@
+package todolist
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNextId(t *testing.T) {
+ assert := assert.New(t)
+ list := &TodoList{}
+ assert.Equal(1, list.NextId())
+}
+
+func TestIndexOf(t *testing.T) {
+ assert := assert.New(t)
+ todo := &Todo{Subject: "Grant"}
+ store := &FileStore{FileLocation: "todos.json"}
+ list := &TodoList{}
+ list.Load(store.Load())
+
+ assert.Equal(-1, list.IndexOf(todo))
+ assert.Equal(0, list.IndexOf(list.Data[0]))
+}
+
+func TestDelete(t *testing.T) {
+ assert := assert.New(t)
+ store := &FileStore{FileLocation: "todos.json"}
+ list := &TodoList{}
+ list.Load(store.Load())
+ assert.Equal(2, len(list.Data))
+ list.Delete(1)
+ assert.Equal(1, len(list.Data))
+}
+
+func TestComplete(t *testing.T) {
+ assert := assert.New(t)
+ store := &FileStore{FileLocation: "todos.json"}
+ list := &TodoList{}
+ list.Load(store.Load())
+ assert.Equal(false, list.FindById(1).Completed)
+ list.Complete(1)
+ assert.Equal(true, list.FindById(1).Completed)
+}
+
+func TestArchive(t *testing.T) {
+ assert := assert.New(t)
+ store := &FileStore{FileLocation: "todos.json"}
+ list := &TodoList{}
+ list.Load(store.Load())
+ assert.Equal(false, list.FindById(2).Archived)
+ list.Archive(2)
+ assert.Equal(true, list.FindById(2).Archived)
+}
+func TestUnarchive(t *testing.T) {
+ assert := assert.New(t)
+ store := &FileStore{FileLocation: "todos.json"}
+ list := &TodoList{}
+ list.Load(store.Load())
+ assert.Equal(true, list.FindById(1).Archived)
+ list.Unarchive(1)
+ assert.Equal(false, list.FindById(1).Archived)
+}
+
+func TestUncomplete(t *testing.T) {
+ assert := assert.New(t)
+ store := &FileStore{FileLocation: "todos.json"}
+ list := &TodoList{}
+ list.Load(store.Load())
+ assert.Equal(true, list.FindById(2).Completed)
+ list.Uncomplete(2)
+ assert.Equal(false, list.FindById(2).Completed)
+}