render.gno
4.63 Kb · 173 lines
1package treasury
2
3import (
4 "net/url"
5 "strconv"
6 "strings"
7
8 "gno.land/p/moul/md"
9 "gno.land/p/moul/mdtable"
10 "gno.land/p/nt/bptree/v0/pager"
11 "gno.land/p/nt/mux/v0"
12 "gno.land/p/nt/ufmt/v0"
13)
14
15const (
16 DefaultHistoryPreviewSize = 5 // Number of payments in the history preview.
17 DefaultHistoryPageSize = 20 // Number of payments per page in the history.
18)
19
20// Render renders content based on the given path.
21func (t *Treasury) Render(path string) string {
22 return t.router.Render(path)
23}
24
25// RenderLanding renders the landing page of the treasury.
26func (t *Treasury) RenderLanding(path string) string {
27 var out string
28
29 // Render each banker.
30 for _, bankerID := range t.ListBankerIDs() {
31 out += t.RenderBanker(bankerID, path)
32 }
33
34 return out
35}
36
37// RenderBanker renders the details of a specific banker.
38func (t *Treasury) RenderBanker(bankerID string, path string) string {
39 // Get the banker associated to this ID.
40 br, ok := t.bankers.Get(bankerID)
41 if !ok {
42 return md.Paragraph("Banker not found: " + bankerID)
43 }
44 banker := br.(*bankerRecord).banker
45
46 // Render banker title.
47 out := md.H2(bankerID + " Banker")
48
49 // Render address section.
50 out += md.H3("Address")
51 out += md.Paragraph(banker.Address())
52
53 // Render balances section.
54 out += md.H3("Balances")
55 balances := banker.Balances()
56 if len(balances) == 0 {
57 out += md.Paragraph("No balances found.")
58 } else {
59 table := mdtable.Table{Headers: []string{"Denom", "Amount"}}
60 for _, balance := range balances {
61 table.Append([]string{balance.Denom, strconv.FormatInt(balance.Amount, 10)})
62 }
63 out += table.String()
64 }
65
66 historySize := DefaultHistoryPreviewSize
67
68 // Check if the query parameter "history_size" is present and parse it.
69 if req, err := url.Parse(path); err == nil && req.Query() != nil {
70 size, err := strconv.Atoi(req.Query().Get("history_size"))
71 if err == nil && size >= 0 {
72 historySize = size
73 }
74 }
75
76 // Skip history rendering if historySize is 0.
77 if historySize == 0 {
78 return out
79 }
80
81 // Render history section.
82 out += md.H3("History")
83 history, _ := t.History(bankerID, 1, historySize)
84 if len(history) == 0 {
85 out += md.Paragraph("No payments sent yet.")
86 } else {
87 if len(history) == 1 {
88 out += md.Paragraph("Last payment:")
89 } else {
90 count := strconv.FormatInt(int64(len(history)), 10)
91 out += md.Paragraph("Last " + count + " payments:")
92 }
93
94 // Render each payment in the history.
95 for _, payment := range history {
96 out += md.BulletItem(payment.String())
97 }
98 out += "\n"
99
100 // Build the "See full history" link from the owning realm's
101 // path captured at New() time. Skipped if no path was supplied
102 // (e.g. /p/ filetests that don't exercise rendering).
103 if from := strings.IndexRune(t.realmPath, '/'); from >= 0 {
104 out += md.Link(
105 "See full history",
106 ufmt.Sprintf("%s:%s/history", t.realmPath[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}