render.gno
4.75 Kb ยท 213 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 if exhibition.items.Size() == 0 {
124 return "No items in the Hall of Realms.\n\n"
125 }
126
127 out := ""
128 i := 0
129 exhibition.items.Iterate("", "", func(key string, value any) bool {
130 item := value.(*Item)
131
132 out += ufmt.Sprintf("- %s\n", fqname.RenderLink(item.pkgpath, ""))
133
134 i++
135 return i >= itemsToRender
136 })
137
138 return out
139}
140
141func getTreeByPath(e *Exhibition, path string) *avl.Tree {
142 u, _ := url.Parse(path)
143 switch u.Query().Get("sort") {
144 case "upvotes":
145 return e.itemsSortedByUpvotes
146 case "downvotes":
147 return e.itemsSortedByDownvotes
148 case "creation":
149 return e.itemsSortedByCreation
150 case "oldest":
151 return e.itemsSortedByCreation
152 default:
153 return e.itemsSortedByCreation
154 }
155}
156
157func renderAbout() string {
158 out := `
159Welcome, gnomes!
160
161The Hall of Realms is a simple & permissionless dashboard for gnomes to share
162their work with the community.
163
164Here, anyone is welcome to submit their own code. This realm utilizes a common
165Gno pattern - the registry pattern - to allow anyone to programmatically submit
166their work.
167
168Simply import the Hall of Realms in your code, and call the "Register()" function
169inside your realm init, as shown below:
170
171"""go
172package myrealm
173
174import "gno.land/r/leon/hor"
175
176func init() {
177 cross(hor.Register)("My Gnome App", "This is my submission to the Hall of Realms.")
178}
179...
180"""
181
182%s
183
184`
185
186 out = ufmt.Sprintf(out, "## [Visit The Hall ->](/r/leon/hor:hall)")
187
188 out = strings.ReplaceAll(out, "\"", "`")
189
190 return out
191}
192
193func renderActions(path string) string {
194 out := md.HorizontalRule()
195 out += md.Link("Reset Sort", "?") + " | "
196 out += md.Link("Sort by Upvotes", "?sort=upvotes") + " | "
197 out += md.Link("Sort by Downvotes", "?sort=downvotes") + " | "
198 out += md.Link("Sort by Most Recent", "?sort=creation") + " | "
199 out += md.Link("Sort by Oldest", "?sort=oldest") + " | "
200
201 if !strings.Contains(path, "dashboard") {
202 out += md.Link("Dashboard", "/r/leon/hor:dashboard")
203 } else {
204 out += md.Link("Dashboard off", "/r/leon/hor:hall")
205 }
206
207 out += " | "
208 out += md.Link("About", "/r/leon/hor") + "\n\n"
209
210 out += md.HorizontalRule()
211
212 return out
213}