render.gno

4.66 Kb ยท 209 lines
  1package hor
  2
  3import (
  4	"net/url"
  5	"strings"
  6
  7	"gno.land/p/demo/avl"
  8	"gno.land/p/demo/avl/pager"
  9	"gno.land/p/demo/fqname"
 10	"gno.land/p/demo/ufmt"
 11	"gno.land/p/moul/md"
 12	"gno.land/p/moul/txlink"
 13
 14	"gno.land/r/sys/users"
 15)
 16
 17const colsPerRow = 3
 18
 19func Render(path string) string {
 20	out := md.H1("The Hall of Realms\n\n")
 21
 22	if !strings.Contains(path, "hall") && !strings.Contains(path, "dashboard") {
 23		out += renderAbout()
 24		return out
 25	}
 26
 27	dashboardEnabled := strings.Contains(path, "dashboard")
 28	if dashboardEnabled {
 29		out += renderDashboard()
 30		out += renderActions(path)
 31		return out
 32	}
 33
 34	out += renderActions(path)
 35	out += exhibition.Render(path, dashboardEnabled)
 36
 37	return out
 38}
 39
 40func (e Exhibition) Render(path string, dashboard bool) string {
 41	tree := getTreeByPath(&e, path)
 42
 43	u, _ := url.Parse(path)
 44	reversed := u.Query().Get("sort") != "oldest"
 45
 46	page := pager.NewPager(tree, colsPerRow*3, reversed).MustGetPageByPath(path)
 47	out := ufmt.Sprintf("%s\n\n", e.description)
 48
 49	if e.items.Size() == 0 {
 50		out += "No items in this exhibition currently.\n\n"
 51		return out
 52	}
 53
 54	str := make([]string, len(page.Items))
 55	for i, item := range page.Items {
 56		itemValue := item.Value.(*Item)
 57		str[i] += itemValue.Render(dashboard)
 58	}
 59
 60	out += md.ColumnsN(str, 3, true)
 61	out += md.H3(page.Picker(path))
 62
 63	return out
 64}
 65
 66func (i Item) Render(dashboard bool) string {
 67	out := ufmt.Sprintf("### [%s](%s)\n",
 68		i.title,
 69		strings.TrimPrefix(i.pkgpath, "gno.land"),
 70	)
 71
 72	if i.description == "" {
 73		i.description = "_No description provided._\n"
 74	}
 75	out += ufmt.Sprintf("%s\n\n", i.description)
 76
 77	namespace := strings.Split(i.pkgpath, "/")[2]
 78	user, _ := users.ResolveAny(namespace)
 79	if user != nil {
 80		namespace = user.RenderLink("")
 81	}
 82	out += ufmt.Sprintf("by %s\n\n", namespace)
 83
 84	blockMsg := "Submitted via the [Monorepo](https://github.com/gnolang/gno)"
 85	if i.blockNum > 0 {
 86		blockMsg = ufmt.Sprintf("Submitted at Block #%d", i.blockNum)
 87	}
 88	out += ufmt.Sprintf("%s\n\n", blockMsg)
 89
 90	out += md.Bold(ufmt.Sprintf("[%d๐Ÿ‘](%s) - [%d๐Ÿ‘Ž](%s)",
 91		i.upvote.Size(), txlink.Call("Upvote", "pkgpath", i.pkgpath),
 92		i.downvote.Size(), txlink.Call("Downvote", "pkgpath", i.pkgpath),
 93	))
 94
 95	if dashboard {
 96		out += md.Link("Delete", txlink.Call("Delete", "pkgpath", i.pkgpath))
 97	}
 98
 99	return out
100}
101
102func renderDashboard() string {
103	out := md.H3("Dashboard\n\n")
104	out += ufmt.Sprintf("Total submissions: %d\n\n", exhibition.items.Size())
105
106	out += ufmt.Sprintf("Exhibition admin: %s\n\n", Ownable.Owner().String())
107
108	if !Pausable.IsPaused() {
109		out += md.Link("Pause exhibition", txlink.Call("Pause"))
110	} else {
111		out += md.Link("Unpause exhibition", txlink.Call("Unpause"))
112	}
113
114	out += "\n\n"
115	return out
116}
117
118func RenderExhibWidget(itemsToRender int) string {
119	if itemsToRender < 1 {
120		return ""
121	}
122
123	out := ""
124	i := 0
125	exhibition.items.Iterate("", "", func(key string, value any) bool {
126		item := value.(*Item)
127
128		out += ufmt.Sprintf("- %s\n", fqname.RenderLink(item.pkgpath, ""))
129
130		i++
131		return i >= itemsToRender
132	})
133
134	return out
135}
136
137func getTreeByPath(e *Exhibition, path string) *avl.Tree {
138	u, _ := url.Parse(path)
139	switch u.Query().Get("sort") {
140	case "upvotes":
141		return e.itemsSortedByUpvotes
142	case "downvotes":
143		return e.itemsSortedByDownvotes
144	case "creation":
145		return e.itemsSortedByCreation
146	case "oldest":
147		return e.itemsSortedByCreation
148	default:
149		return e.itemsSortedByCreation
150	}
151}
152
153func renderAbout() string {
154	out := `
155Welcome, gnomes!
156
157The Hall of Realms is a simple & permissionless dashboard for gnomes to share 
158their work with the community.
159
160Here, anyone is welcome to submit their own code. This realm utilizes a common
161Gno pattern - the registry pattern - to allow anyone to programmatically submit 
162their work. 
163
164Simply import the Hall of Realms in your code, and call the "Register()" function
165inside your realm init, as shown below:
166
167"""go
168package myrealm
169
170import "gno.land/r/leon/hor"
171
172func init() {
173	hor.Register("My Gnome App", "This is my submission to the Hall of Realms.")
174}
175...
176"""
177
178%s
179
180`
181
182	out = ufmt.Sprintf(out, "## [Visit The Hall ->](/r/leon/hor:hall)")
183
184	out = strings.ReplaceAll(out, "\"", "`")
185
186	return out
187}
188
189func renderActions(path string) string {
190	out := md.HorizontalRule()
191	out += md.Link("Reset Sort", "?") + " | "
192	out += md.Link("Sort by Upvotes", "?sort=upvotes") + " | "
193	out += md.Link("Sort by Downvotes", "?sort=downvotes") + " | "
194	out += md.Link("Sort by Most Recent", "?sort=creation") + " | "
195	out += md.Link("Sort by Oldest", "?sort=oldest") + " | "
196
197	if !strings.Contains(path, "dashboard") {
198		out += md.Link("Dashboard", "/r/leon/hor:dashboard")
199	} else {
200		out += md.Link("Dashboard off", "/r/leon/hor:hall")
201	}
202
203	out += " | "
204	out += md.Link("About", "/r/leon/hor") + "\n\n"
205
206	out += md.HorizontalRule()
207
208	return out
209}