Skip to content

Commit

Permalink
Merge branch 'devx/feature/boardsv2' into feat/support-listing-members
Browse files Browse the repository at this point in the history
  • Loading branch information
jeronimoalbi committed Feb 25, 2025
2 parents 3c8cc84 + edf5629 commit 8feaa36
Show file tree
Hide file tree
Showing 32 changed files with 2,266 additions and 63 deletions.
6 changes: 3 additions & 3 deletions docs/concepts/namespaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ similar to GitHub's user and organization model.

:::warning Not enabled

This feature isn't enabled by default on the portal loop chain and is currently available only on test4.gno.land.
This feature isn't enabled by default on the Portal Loop chain and is currently available only on test5.gno.land.

:::

Expand Down Expand Up @@ -56,7 +56,7 @@ $ gnokey maketx call -pkgpath gno.land/r/demo/users \
-func Register \
-gas-fee 1000000ugnot -gas-wanted 2000000 \
-broadcast \
-chainid=test4 \
-chainid=test5 \
-send=20000000ugnot \
-args '' \
-args 'patrick' \
Expand Down Expand Up @@ -86,6 +86,6 @@ $ gnokey maketx addpkg \
--gas-fee 1000000ugnot \
--gas-wanted 2000000 \
--broadcast \
--chainid test4 \
--chainid test5 \
test1
```
22 changes: 7 additions & 15 deletions docs/concepts/testnets.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,6 @@ Test5 was launched in November 2024.
- **Versioning strategy**:
- Test5 is to be release-based, following releases of the Gno tech stack.

## Test4

Test4 is the first permanent multi-node testnet, launched in July 2024.

- **Persistence of state:**
- State is fully persisted unless there are breaking changes in a new release,
where persistence partly depends on implementing a migration strategy
- **Timeliness of code:**
- Versioning mechanisms for packages & realms will be implemented for test4
- **Intended purpose**
- Running a full node, testing validator coordination, deploying stable Gno
dApps, creating tools that require persisted state & transaction history
- **Versioning strategy**:
- Test4 is the first gno.land testnet to be release-based, following releases
of the Gno tech stack.

## Staging

Expand All @@ -98,6 +83,13 @@ Staging is a testnet that is reset once every 60 minutes.

These testnets are deprecated and currently serve as archives of previous progress.

## Test4

Test4 is the first permanent multi-node testnet. Archived data for test4 can be found [here](https://github.com/gnolang/tx-exports/tree/main/test4.gno.land).

Launch date: July 10th 2024
Release commit: [194903d](https://github.com/gnolang/gno/commit/194903db0350ace7d57910e6c34125d3aa9817da)

### Test3 (archive)

The third Gno testnet. Archived data for test3 can be found [here](https://github.com/gnolang/tx-exports/tree/main/test3.gno.land).
Expand Down
1 change: 0 additions & 1 deletion docs/reference/network-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ id: network-config
|-------------|----------------------------------|---------------|
| Portal Loop | https://rpc.gno.land:443 | `portal-loop` |
| Test5 | https://rpc.test5.gno.land:443 | `test5` |
| Test4 | https://rpc.test4.gno.land:443 | `test4` |
| Staging | https://rpc.staging.gno.land:443 | `staging` |

### WebSocket endpoints
Expand Down
1 change: 1 addition & 0 deletions examples/gno.land/p/jeronimoalbi/pager/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/p/jeronimoalbi/pager
204 changes: 204 additions & 0 deletions examples/gno.land/p/jeronimoalbi/pager/pager.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
// Package pager provides pagination functionality through a generic pager implementation.
//
// Example usage:
//
// import (
// "strconv"
// "strings"
//
// "gno.land/p/jeronimoalbi/pager"
// )
//
// func Render(path string) string {
// // Define the items to paginate
// items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
//
// // Create a pager that paginates 4 items at a time
// p, err := pager.New(path, len(items), pager.WithPageSize(4))
// if err != nil {
// panic(err)
// }
//
// // Render items for the current page
// var output strings.Builder
// p.Iterate(func(i int) bool {
// output.WriteString("- " + strconv.Itoa(items[i]) + "\n")
// return false
// })
//
// // Render page picker
// if p.HasPages() {
// output.WriteString("\n" + pager.Picker(p))
// }
//
// return output.String()
// }
package pager

import (
"errors"
"math"
"net/url"
"strconv"
"strings"
)

var ErrInvalidPageNumber = errors.New("invalid page number")

// PagerIterFn defines a callback to iterate page items.
type PagerIterFn func(index int) (stop bool)

// New creates a new pager.
func New(rawURL string, totalItems int, options ...PagerOption) (Pager, error) {
u, err := url.Parse(rawURL)
if err != nil {
return Pager{}, err
}

p := Pager{
query: u.RawQuery,
pageQueryParam: DefaultPageQueryParam,
pageSize: DefaultPageSize,
page: 1,
totalItems: totalItems,
}
for _, apply := range options {
apply(&p)
}

p.pageCount = int(math.Ceil(float64(p.totalItems) / float64(p.pageSize)))

rawPage := u.Query().Get(p.pageQueryParam)
if rawPage != "" {
p.page, _ = strconv.Atoi(rawPage)
if p.page == 0 || p.page > p.pageCount {
return Pager{}, ErrInvalidPageNumber
}
}

return p, nil
}

// MustNew creates a new pager or panics if there is an error.
func MustNew(rawURL string, totalItems int, options ...PagerOption) Pager {
p, err := New(rawURL, totalItems, options...)
if err != nil {
panic(err)
}
return p
}

// Pager allows paging items.
type Pager struct {
query, pageQueryParam string
pageSize, page, pageCount, totalItems int
}

// TotalItems returns the total number of items to paginate.
func (p Pager) TotalItems() int {
return p.totalItems
}

// PageSize returns the size of each page.
func (p Pager) PageSize() int {
return p.pageSize
}

// Page returns the current page number.
func (p Pager) Page() int {
return p.page
}

// PageCount returns the number pages.
func (p Pager) PageCount() int {
return p.pageCount
}

// Offset returns the index of the first page item.
func (p Pager) Offset() int {
return (p.page - 1) * p.pageSize
}

// HasPages checks if pager has more than one page.
func (p Pager) HasPages() bool {
return p.pageCount > 1
}

// GetPageURI returns the URI for a page.
// An empty string is returned when page doesn't exist.
func (p Pager) GetPageURI(page int) string {
if page < 1 || page > p.PageCount() {
return ""
}

values, _ := url.ParseQuery(p.query)
values.Set(p.pageQueryParam, strconv.Itoa(page))
return "?" + values.Encode()
}

// PrevPageURI returns the URI path to the previous page.
// An empty string is returned when current page is the first page.
func (p Pager) PrevPageURI() string {
if p.page == 1 || !p.HasPages() {
return ""
}
return p.GetPageURI(p.page - 1)
}

// NextPageURI returns the URI path to the next page.
// An empty string is returned when current page is the last page.
func (p Pager) NextPageURI() string {
if p.page == p.pageCount {
// Current page is the last page
return ""
}
return p.GetPageURI(p.page + 1)
}

// Iterate allows iterating page items.
func (p Pager) Iterate(fn PagerIterFn) bool {
if p.totalItems == 0 {
return true
}

start := p.Offset()
end := start + p.PageSize()
if end > p.totalItems {
end = p.totalItems
}

for i := start; i < end; i++ {
if fn(i) {
return true
}
}
return false
}

// TODO: Support different types of pickers (ex. with clickable page numbers)

// Picker returns a string with the pager as Markdown.
// An empty string is returned when the pager has no pages.
func Picker(p Pager) string {
if !p.HasPages() {
return ""
}

var out strings.Builder

if s := p.PrevPageURI(); s != "" {
out.WriteString("[«](" + s + ") | ")
} else {
out.WriteString("\\- | ")
}

out.WriteString("page " + strconv.Itoa(p.Page()) + " of " + strconv.Itoa(p.PageCount()))

if s := p.NextPageURI(); s != "" {
out.WriteString(" | [»](" + s + ")")
} else {
out.WriteString(" | \\-")
}

return out.String()
}
33 changes: 33 additions & 0 deletions examples/gno.land/p/jeronimoalbi/pager/pager_options.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package pager

import "strings"

const (
DefaultPageSize = 50
DefaultPageQueryParam = "page"
)

// PagerOption configures the pager.
type PagerOption func(*Pager)

// WithPageSize assigns a page size to a pager.
func WithPageSize(size int) PagerOption {
return func(p *Pager) {
if size < 1 {
p.pageSize = DefaultPageSize
} else {
p.pageSize = size
}
}
}

// WithPageQueryParam assigns the name of the URL query param for the page value.
func WithPageQueryParam(name string) PagerOption {
return func(p *Pager) {
name = strings.TrimSpace(name)
if name == "" {
name = DefaultPageQueryParam
}
p.pageQueryParam = name
}
}
Loading

0 comments on commit 8feaa36

Please sign in to comment.