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}