Skip to content

Commit

Permalink
feat(examples): add todolist package & realm (gnolang#1811)
Browse files Browse the repository at this point in the history
<!-- 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
MalekLahbib authored Apr 11, 2024
1 parent ca6566f commit aab9f4f
Show file tree
Hide file tree
Showing 6 changed files with 417 additions and 0 deletions.
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/todolist/gno.mod
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
63 changes: 63 additions & 0 deletions examples/gno.land/p/demo/todolist/todolist.gno
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
}
81 changes: 81 additions & 0 deletions examples/gno.land/p/demo/todolist/todolist_test.gno
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))
}
}
8 changes: 8 additions & 0 deletions examples/gno.land/r/demo/todolist/gno.mod
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
)
176 changes: 176 additions & 0 deletions examples/gno.land/r/demo/todolist/todolist.gno
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()
}
Loading

0 comments on commit aab9f4f

Please sign in to comment.