forked from gnolang/gno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(examples): add todolist package & realm (gnolang#1811)
<!-- please provide a detailed description of the changes made in this pull request. --> <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details>
- Loading branch information
1 parent
ca6566f
commit aab9f4f
Showing
6 changed files
with
417 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module gno.land/p/demo/todolist | ||
|
||
require gno.land/p/demo/avl v0.0.0-latest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package todolist | ||
|
||
import ( | ||
"std" | ||
"strconv" | ||
|
||
"gno.land/p/demo/avl" | ||
) | ||
|
||
type TodoList struct { | ||
Title string | ||
Tasks *avl.Tree | ||
Owner std.Address | ||
} | ||
|
||
type Task struct { | ||
Title string | ||
Done bool | ||
} | ||
|
||
func NewTodoList(title string) *TodoList { | ||
return &TodoList{ | ||
Title: title, | ||
Tasks: avl.NewTree(), | ||
Owner: std.GetOrigCaller(), | ||
} | ||
} | ||
|
||
func NewTask(title string) *Task { | ||
return &Task{ | ||
Title: title, | ||
Done: false, | ||
} | ||
} | ||
|
||
func (tl *TodoList) AddTask(id int, task *Task) { | ||
tl.Tasks.Set(strconv.Itoa(id), task) | ||
} | ||
|
||
func ToggleTaskStatus(task *Task) { | ||
task.Done = !task.Done | ||
} | ||
|
||
func (tl *TodoList) RemoveTask(taskId string) { | ||
tl.Tasks.Remove(taskId) | ||
} | ||
|
||
func (tl *TodoList) GetTasks() []*Task { | ||
tasks := make([]*Task, 0, tl.Tasks.Size()) | ||
tl.Tasks.Iterate("", "", func(key string, value interface{}) bool { | ||
tasks = append(tasks, value.(*Task)) | ||
return false | ||
}) | ||
return tasks | ||
} | ||
|
||
func (tl *TodoList) GetTodolistOwner() std.Address { | ||
return tl.Owner | ||
} | ||
|
||
func (tl *TodoList) GetTodolistTitle() string { | ||
return tl.Title | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package todolist | ||
|
||
import ( | ||
"std" | ||
"testing" | ||
) | ||
|
||
func TestNewTodoList(t *testing.T) { | ||
title := "My Todo List" | ||
todoList := NewTodoList(title) | ||
|
||
if todoList.GetTodolistTitle() != title { | ||
t.Errorf("Expected title %q, got %q", title, todoList.GetTodolistTitle()) | ||
} | ||
|
||
if len(todoList.GetTasks()) != 0 { | ||
t.Errorf("Expected 0 tasks, got %d", len(todoList.GetTasks())) | ||
} | ||
|
||
if todoList.GetTodolistOwner() != std.GetOrigCaller() { | ||
t.Errorf("Expected owner %v, got %v", std.GetOrigCaller(), todoList.GetTodolistOwner()) | ||
} | ||
} | ||
|
||
func TestNewTask(t *testing.T) { | ||
title := "My Task" | ||
task := NewTask(title) | ||
|
||
if task.Title != title { | ||
t.Errorf("Expected title %q, got %q", title, task.Title) | ||
} | ||
|
||
if task.Done { | ||
t.Errorf("Expected task to be not done, but it is done") | ||
} | ||
} | ||
|
||
func TestAddTask(t *testing.T) { | ||
todoList := NewTodoList("My Todo List") | ||
task := NewTask("My Task") | ||
|
||
todoList.AddTask(1, task) | ||
|
||
tasks := todoList.GetTasks() | ||
if len(tasks) != 1 { | ||
t.Errorf("Expected 1 task, got %d", len(tasks)) | ||
} | ||
|
||
if tasks[0] != task { | ||
t.Errorf("Expected task %v, got %v", task, tasks[0]) | ||
} | ||
} | ||
|
||
func TestToggleTaskStatus(t *testing.T) { | ||
task := NewTask("My Task") | ||
|
||
ToggleTaskStatus(task) | ||
|
||
if !task.Done { | ||
t.Errorf("Expected task to be done, but it is not done") | ||
} | ||
|
||
ToggleTaskStatus(task) | ||
|
||
if task.Done { | ||
t.Errorf("Expected task to be not done, but it is done") | ||
} | ||
} | ||
|
||
func TestRemoveTask(t *testing.T) { | ||
todoList := NewTodoList("My Todo List") | ||
task := NewTask("My Task") | ||
todoList.AddTask(1, task) | ||
|
||
todoList.RemoveTask("1") | ||
|
||
tasks := todoList.GetTasks() | ||
if len(tasks) != 0 { | ||
t.Errorf("Expected 0 tasks, got %d", len(tasks)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module gno.land/r/demo/todolist | ||
|
||
require ( | ||
gno.land/p/demo/avl v0.0.0-latest | ||
gno.land/p/demo/seqid v0.0.0-latest | ||
gno.land/p/demo/todolist v0.0.0-latest | ||
gno.land/p/demo/ufmt v0.0.0-latest | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package todolistrealm | ||
|
||
import ( | ||
"bytes" | ||
"strconv" | ||
|
||
"gno.land/p/demo/avl" | ||
"gno.land/p/demo/seqid" | ||
"gno.land/p/demo/todolist" | ||
"gno.land/p/demo/ufmt" | ||
) | ||
|
||
// State variables | ||
var ( | ||
todolistTree *avl.Tree | ||
tlid seqid.ID | ||
) | ||
|
||
// Constructor | ||
func init() { | ||
todolistTree = avl.NewTree() | ||
} | ||
|
||
func NewTodoList(title string) (int, string) { | ||
// Create new Todolist | ||
tl := todolist.NewTodoList(title) | ||
// Update AVL tree with new state | ||
tlid.Next() | ||
todolistTree.Set(strconv.Itoa(int(tlid)), tl) | ||
return int(tlid), "created successfully" | ||
} | ||
|
||
func AddTask(todolistID int, title string) string { | ||
// Get Todolist from AVL tree | ||
tl, ok := todolistTree.Get(strconv.Itoa(todolistID)) | ||
if !ok { | ||
panic("Todolist not found") | ||
} | ||
|
||
// get the number of tasks in the todolist | ||
id := tl.(*todolist.TodoList).Tasks.Size() | ||
|
||
// create the task | ||
task := todolist.NewTask(title) | ||
|
||
// Cast raw data from tree into Todolist struct | ||
tl.(*todolist.TodoList).AddTask(id, task) | ||
|
||
return "task added successfully" | ||
} | ||
|
||
func ToggleTaskStatus(todolistID int, taskID int) string { | ||
// Get Todolist from AVL tree | ||
tl, ok := todolistTree.Get(strconv.Itoa(todolistID)) | ||
if !ok { | ||
panic("Todolist not found") | ||
} | ||
|
||
// Get the task from the todolist | ||
task, found := tl.(*todolist.TodoList).Tasks.Get(strconv.Itoa(taskID)) | ||
if !found { | ||
panic("Task not found") | ||
} | ||
|
||
// Change the status of the task | ||
todolist.ToggleTaskStatus(task.(*todolist.Task)) | ||
|
||
return "task status changed successfully" | ||
} | ||
|
||
func RemoveTask(todolistID int, taskID int) string { | ||
// Get Todolist from AVL tree | ||
tl, ok := todolistTree.Get(strconv.Itoa(todolistID)) | ||
if !ok { | ||
panic("Todolist not found") | ||
} | ||
|
||
// Get the task from the todolist | ||
_, ok = tl.(*todolist.TodoList).Tasks.Get(strconv.Itoa(taskID)) | ||
if !ok { | ||
panic("Task not found") | ||
} | ||
|
||
// Change the status of the task | ||
tl.(*todolist.TodoList).RemoveTask(strconv.Itoa(taskID)) | ||
|
||
return "task status changed successfully" | ||
} | ||
|
||
func RemoveTodoList(todolistID int) string { | ||
// Get Todolist from AVL tree | ||
_, ok := todolistTree.Get(strconv.Itoa(todolistID)) | ||
if !ok { | ||
panic("Todolist not found") | ||
} | ||
|
||
// Remove the todolist | ||
todolistTree.Remove(strconv.Itoa(todolistID)) | ||
|
||
return "Todolist removed successfully" | ||
} | ||
|
||
func Render(path string) string { | ||
if path == "" { | ||
return renderHomepage() | ||
} | ||
|
||
return "unknown page" | ||
} | ||
|
||
func renderHomepage() string { | ||
// Define empty buffer | ||
var b bytes.Buffer | ||
|
||
b.WriteString("# Welcome to ToDolist\n\n") | ||
|
||
// If no todolists have been created | ||
if todolistTree.Size() == 0 { | ||
b.WriteString("### No todolists available currently!") | ||
return b.String() | ||
} | ||
|
||
// Iterate through AVL tree | ||
todolistTree.Iterate("", "", func(key string, value interface{}) bool { | ||
// cast raw data from tree into Todolist struct | ||
tl := value.(*todolist.TodoList) | ||
|
||
// Add Todolist name | ||
b.WriteString( | ||
ufmt.Sprintf( | ||
"## Todolist #%s: %s\n", | ||
key, // Todolist ID | ||
tl.GetTodolistTitle(), | ||
), | ||
) | ||
|
||
// Add Todolist owner | ||
b.WriteString( | ||
ufmt.Sprintf( | ||
"#### Todolist owner : %s\n", | ||
tl.GetTodolistOwner(), | ||
), | ||
) | ||
|
||
// List all todos that are currently Todolisted | ||
if todos := tl.GetTasks(); len(todos) > 0 { | ||
b.WriteString( | ||
ufmt.Sprintf("Currently Todo tasks: %d\n\n", len(todos)), | ||
) | ||
|
||
for index, todo := range todos { | ||
b.WriteString( | ||
ufmt.Sprintf("#%d - %s ", index, todo.Title), | ||
) | ||
// displays a checked box if task is marked as done, an empty box if not | ||
if todo.Done { | ||
b.WriteString( | ||
"☑\n\n", | ||
) | ||
continue | ||
} | ||
|
||
b.WriteString( | ||
"☐\n\n", | ||
) | ||
} | ||
} else { | ||
b.WriteString("No tasks in this list currently\n") | ||
} | ||
|
||
b.WriteString("\n") | ||
return false | ||
}) | ||
|
||
return b.String() | ||
} |
Oops, something went wrong.