diff options
Diffstat (limited to 'todolist')
| -rw-r--r-- | todolist/app.go | 56 | ||||
| -rw-r--r-- | todolist/file_store.go | 114 | ||||
| -rw-r--r-- | todolist/file_store_test.go | 69 | ||||
| -rw-r--r-- | todolist/filter_test.go | 20 | ||||
| -rw-r--r-- | todolist/grouper_test.go | 10 | ||||
| -rw-r--r-- | todolist/store.go | 14 | ||||
| -rw-r--r-- | todolist/todo_list.go | 98 | ||||
| -rw-r--r-- | todolist/todo_list_test.go | 73 |
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) +} |
