Skip to content

Commit

Permalink
feat: add r/docs/home (#3160)
Browse files Browse the repository at this point in the history
Introducing the `r/docs` namespace, where the homepage currently lists
subrealms manually. In the future, we may implement a registry, but for
now, we’re keeping the source code as lean as possible. The namespace
includes several interactive examples to guide users through key
concepts.

The `r/docs/hello` example provides a simple Render function and invites
users to click on "view source" to understand the basics of
customization. The `r/docs/avl_pager` example demonstrates path-based
interactions, allowing users to explore an avl tree structure with
pagination links to navigate between items. Users are encouraged to
click on these links for inspiration before manually adjusting
parameters in the URL. The added `r/docs/add` example introduces
interactivity through transactions, allowing users to adjust a number by
submitting transactions, and see the updated result with each
interaction.

These examples are designed to engage users with Render-based UI
interactions, path handling, and transaction-based updates. Once we have
more content in r/docs, this section could serve as the main
documentation link in the navbar, providing a comprehensive, hands-on
introduction to Gno.

Addresses #3084 
Addresses
gnolang/docs-v2#27 (comment)
Addresses #2953

---------

Signed-off-by: moul <[email protected]>
  • Loading branch information
moul authored Nov 20, 2024
1 parent 732bb0b commit 4646ae6
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 19 deletions.
1 change: 0 additions & 1 deletion examples/gno.land/r/demo/hello_world/gno.mod

This file was deleted.

17 changes: 0 additions & 17 deletions examples/gno.land/r/demo/hello_world/hello.gno

This file was deleted.

42 changes: 42 additions & 0 deletions examples/gno.land/r/docs/add/add.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package add

import (
"strconv"
"time"

"gno.land/p/moul/txlink"
)

// Global variables to store the current number and last update timestamp
var (
number int
lastUpdate time.Time
)

// Add function to update the number and timestamp
func Add(n int) {
number += n
lastUpdate = time.Now()
}

// Render displays the current number value, last update timestamp, and a link to call Add with 42
func Render(path string) string {
// Display the current number and formatted last update time
result := "# Add Example\n\n"
result += "Current Number: " + strconv.Itoa(number) + "\n\n"
result += "Last Updated: " + formatTimestamp(lastUpdate) + "\n\n"

// Generate a transaction link to call Add with 42 as the default parameter
txLink := txlink.URL("Add", "n", "42")
result += "[Increase Number](" + txLink + ")\n"

return result
}

// Helper function to format the timestamp for readability
func formatTimestamp(timestamp time.Time) string {
if timestamp.IsZero() {
return "Never"
}
return timestamp.Format("2006-01-02 15:04:05")
}
44 changes: 44 additions & 0 deletions examples/gno.land/r/docs/add/add_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package add

import (
"testing"
)

func TestRenderAndAdd(t *testing.T) {
// Initial Render output
output := Render("")
expected := `# Add Example
Current Number: 0
Last Updated: Never
[Increase Number](/r/docs/add$help&func=Add&n=42)
`
if output != expected {
t.Errorf("Initial Render failed, got:\n%s", output)
}

// Call Add with a value of 10
Add(10)

// Call Add again with a value of -5
Add(-5)

// Render after two Add calls
finalOutput := Render("")

// Initial Render output
output = Render("")
expected = `# Add Example
Current Number: 5
Last Updated: 2009-02-13 23:31:30
[Increase Number](/r/docs/add$help&func=Add&n=42)
`
if output != expected {
t.Errorf("Final Render failed, got:\n%s", output)
}
}
3 changes: 3 additions & 0 deletions examples/gno.land/r/docs/add/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module gno.land/r/docs/add

require gno.land/p/moul/txlink v0.0.0-latest
40 changes: 40 additions & 0 deletions examples/gno.land/r/docs/avl_pager/avl_pager.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package avl_pager

import (
"strconv"

"gno.land/p/demo/avl"
"gno.land/p/demo/avl/pager"
)

// Tree instance for 100 items
var tree *avl.Tree

// Initialize a tree with 100 items.
func init() {
tree = avl.NewTree()
for i := 1; i <= 100; i++ {
key := "Item" + strconv.Itoa(i)
tree.Set(key, "Value of "+key)
}
}

// Render paginated content based on the given URL path.
// URL format: `...?page=<page>&size=<size>` (default is page 1 and size 10).
func Render(path string) string {
p := pager.NewPager(tree, 10) // Default page size is 10
page := p.MustGetPageByPath(path)

// Header and pagination info
result := "# Paginated Items\n"
result += "Page " + strconv.Itoa(page.PageNumber) + " of " + strconv.Itoa(page.TotalPages) + "\n\n"
result += page.Selector() + "\n\n"

// Display items on the current page
for _, item := range page.Items {
result += "- " + item.Key + ": " + item.Value.(string) + "\n"
}

result += "\n" + page.Selector() // Repeat selector for ease of navigation
return result
}
55 changes: 55 additions & 0 deletions examples/gno.land/r/docs/avl_pager/avl_pager_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package avl_pager

import (
"testing"
)

func TestRender(t *testing.T) {
// Test default Render output (first page)
output := Render("")
expected := `# Paginated Items
Page 1 of 10
**1** | [2](?page=2) | [3](?page=3) | … | [10](?page=10)
- Item1: Value of Item1
- Item10: Value of Item10
- Item100: Value of Item100
- Item11: Value of Item11
- Item12: Value of Item12
- Item13: Value of Item13
- Item14: Value of Item14
- Item15: Value of Item15
- Item16: Value of Item16
- Item17: Value of Item17
**1** | [2](?page=2) | [3](?page=3) | … | [10](?page=10)`
if output != expected {
t.Errorf("Render(\"\") failed, got:\n%s", output)
}
}

func TestRender_page2(t *testing.T) {
// Test Render output for a custom page (page 2)
output := Render("?page=2&size=10")
expected := `# Paginated Items
Page 2 of 10
[1](?page=1) | **2** | [3](?page=3) | [4](?page=4) | … | [10](?page=10)
- Item18: Value of Item18
- Item19: Value of Item19
- Item2: Value of Item2
- Item20: Value of Item20
- Item21: Value of Item21
- Item22: Value of Item22
- Item23: Value of Item23
- Item24: Value of Item24
- Item25: Value of Item25
- Item26: Value of Item26
[1](?page=1) | **2** | [3](?page=3) | [4](?page=4) | … | [10](?page=10)`
if output != expected {
t.Errorf("Render(\"\") failed, got:\n%s", output)
}
}
6 changes: 6 additions & 0 deletions examples/gno.land/r/docs/avl_pager/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module gno.land/r/docs/avl_pager

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/avl/pager v0.0.0-latest
)
1 change: 1 addition & 0 deletions examples/gno.land/r/docs/hello/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/docs/hello
11 changes: 11 additions & 0 deletions examples/gno.land/r/docs/hello/hello.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Package hello_world demonstrates basic usage of Render().
// Try adding `:World` at the end of the URL, like `.../hello:World`.
package hello

// Render outputs a greeting. It customizes the message based on the provided path.
func Render(path string) string {
if path == "" {
return "# Hello, 世界!"
}
return "# Hello, " + path + "!"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package hello_world
package hello

import (
"testing"
Expand Down
1 change: 1 addition & 0 deletions examples/gno.land/r/docs/home/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/docs/home
20 changes: 20 additions & 0 deletions examples/gno.land/r/docs/home/home.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package home

func Render(_ string) string {
return `# Gno Examples Documentation
Welcome to the Gno examples documentation index.
Explore various examples to learn more about Gno functionality and usage.
## Examples
- [Hello World](/r/docs/hello) - A simple introductory example.
- [Add](/r/docs/add) - An interactive example to update a number with transactions.
- [AVL Pager](/r/docs/avl_pager) - Paginate through AVL tree items.
- ...
## Other resources
- [Official documentation](https://github.com/gnolang/gno/tree/master/docs) <!-- should be /docs with gnoweb embedding the docs/ folder. -->
`
}
22 changes: 22 additions & 0 deletions examples/gno.land/r/docs/home/home_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package home

import (
"strings"
"testing"
)

func TestRenderHome(t *testing.T) {
output := Render("")

// Check for the presence of key sections
if !contains(output, "# Gno Examples Documentation") {
t.Errorf("Render output is missing the title.")
}
if !contains(output, "Official documentation") {
t.Errorf("Render output is missing the official documentation link.")
}
}

func contains(s, substr string) bool {
return strings.Index(s, substr) >= 0
}

0 comments on commit 4646ae6

Please sign in to comment.