render.gno
4.56 Kb · 173 lines
1package treasury
2
3import (
4 "chain/runtime"
5 "net/url"
6 "strconv"
7 "strings"
8
9 "gno.land/p/moul/md"
10 "gno.land/p/moul/mdtable"
11 "gno.land/p/nt/avl/v0/pager"
12 "gno.land/p/nt/mux/v0"
13 "gno.land/p/nt/ufmt/v0"
14)
15
16const (
17 DefaultHistoryPreviewSize = 5 // Number of payments in the history preview.
18 DefaultHistoryPageSize = 20 // Number of payments per page in the history.
19)
20
21// Render renders content based on the given path.
22func (t *Treasury) Render(path string) string {
23 return t.router.Render(path)
24}
25
26// RenderLanding renders the landing page of the treasury.
27func (t *Treasury) RenderLanding(path string) string {
28 var out string
29
30 // Render each banker.
31 for _, bankerID := range t.ListBankerIDs() {
32 out += t.RenderBanker(bankerID, path)
33 }
34
35 return out
36}
37
38// RenderBanker renders the details of a specific banker.
39func (t *Treasury) RenderBanker(bankerID string, path string) string {
40 // Get the banker associated to this ID.
41 br, ok := t.bankers.Get(bankerID)
42 if !ok {
43 return md.Paragraph("Banker not found: " + bankerID)
44 }
45 banker := br.(*bankerRecord).banker
46
47 // Render banker title.
48 out := md.H2(bankerID + " Banker")
49
50 // Render address section.
51 out += md.H3("Address")
52 out += md.Paragraph(banker.Address())
53
54 // Render balances section.
55 out += md.H3("Balances")
56 balances := banker.Balances()
57 if len(balances) == 0 {
58 out += md.Paragraph("No balances found.")
59 } else {
60 table := mdtable.Table{Headers: []string{"Denom", "Amount"}}
61 for _, balance := range balances {
62 table.Append([]string{balance.Denom, strconv.FormatInt(balance.Amount, 10)})
63 }
64 out += table.String()
65 }
66
67 historySize := DefaultHistoryPreviewSize
68
69 // Check if the query parameter "history_size" is present and parse it.
70 if req, err := url.Parse(path); err == nil && req.Query() != nil {
71 size, err := strconv.Atoi(req.Query().Get("history_size"))
72 if err == nil && size >= 0 {
73 historySize = size
74 }
75 }
76
77 // Skip history rendering if historySize is 0.
78 if historySize == 0 {
79 return out
80 }
81
82 // Render history section.
83 out += md.H3("History")
84 history, _ := t.History(bankerID, 1, historySize)
85 if len(history) == 0 {
86 out += md.Paragraph("No payments sent yet.")
87 } else {
88 if len(history) == 1 {
89 out += md.Paragraph("Last payment:")
90 } else {
91 count := strconv.FormatInt(int64(len(history)), 10)
92 out += md.Paragraph("Last " + count + " payments:")
93 }
94
95 // Render each payment in the history.
96 for _, payment := range history {
97 out += md.BulletItem(payment.String())
98 }
99 out += "\n"
100
101 // Get the current Realm's package path for linking.
102 curRealm := runtime.CurrentRealm().PkgPath()
103 if from := strings.IndexRune(curRealm, '/'); from >= 0 {
104 out += md.Link(
105 "See full history",
106 ufmt.Sprintf("%s:%s/history", curRealm[from:], bankerID),
107 )
108 }
109 }
110
111 return out
112}
113
114// RenderBankerHistory renders the payment history of a specific banker.
115func (t *Treasury) RenderBankerHistory(bankerID string, path string) string {
116 // Get the banker record corresponding to this ID if it exists.
117 br, ok := t.bankers.Get(bankerID)
118 if !ok {
119 return md.Paragraph("Banker not found: " + bankerID)
120 }
121 history := br.(*bankerRecord).history
122
123 // Render banker history title.
124 out := md.H2(bankerID + " Banker History")
125
126 // Get the current page of tokens based on the request path.
127 p := pager.NewPager(history.Tree(), DefaultHistoryPageSize, true)
128 page, err := p.GetPageByPath(path)
129 if err != nil {
130 return md.Paragraph("Error retrieving page: " + err.Error())
131 }
132
133 // Render full history section.
134 if history.Len() == 0 {
135 out += md.Paragraph("No payments sent yet.")
136 } else {
137 if history.Len() == 1 {
138 out += md.Paragraph("1 payment:")
139 } else {
140 count := strconv.FormatInt(int64(history.Len()), 10)
141 out += md.Paragraph(count + " payments (sorted by latest, descending):")
142 }
143 for _, item := range page.Items {
144 out += md.BulletItem(item.Value.(Payment).String())
145 }
146 }
147 out += "\n"
148
149 // Add the page picker.
150 out += md.Paragraph(page.Picker(path))
151
152 return out
153}
154
155// initRenderRouter registers the routes for rendering the treasury pages.
156func (t *Treasury) initRenderRouter() {
157 t.router = mux.NewRouter()
158
159 // Landing page.
160 t.router.HandleFunc("", func(res *mux.ResponseWriter, req *mux.Request) {
161 res.Write(t.RenderLanding(req.RawPath))
162 })
163
164 // Banker details.
165 t.router.HandleFunc("{banker}", func(res *mux.ResponseWriter, req *mux.Request) {
166 res.Write(t.RenderBanker(req.GetVar("banker"), req.RawPath))
167 })
168
169 // Banker full history.
170 t.router.HandleFunc("{banker}/history", func(res *mux.ResponseWriter, req *mux.Request) {
171 res.Write(t.RenderBankerHistory(req.GetVar("banker"), req.RawPath))
172 })
173}