render_board.gno
4.82 Kb · 189 lines
1package boards2
2
3import (
4 "strings"
5
6 "gno.land/p/gnoland/boards"
7 "gno.land/p/jeronimoalbi/mdform"
8 "gno.land/p/jeronimoalbi/pager"
9 "gno.land/p/moul/md"
10 "gno.land/p/nt/mdalert"
11 "gno.land/p/nt/mux"
12 "gno.land/r/gnoland/boards2/v1/permissions"
13)
14
15func renderBoard(res *mux.ResponseWriter, req *mux.Request) {
16 name := req.GetVar("board")
17 board, found := gBoards.GetByName(name)
18 if !found {
19 res.Write(md.H3("The board you are looking for does not exist"))
20 res.Write("Do you want to " + md.Link("create a new board", createBoardURI) + " ?")
21 return
22 }
23
24 creatorLink := userLink(board.Creator)
25 date := board.CreatedAt.Format(dateFormat)
26
27 res.Write(md.H1(md.Link("Boards", gRealmPath) + " › " + board.Name))
28 if board.Readonly {
29 res.Write(
30 mdalert.Warning("Info", "Creating new threads and commenting are disabled within this board") + "\n",
31 )
32 }
33
34 res.Write("Created by " + creatorLink + " on " + date + ", #" + board.ID.String())
35 res.Write(" \n" + renderBoardMenu(board, req))
36 res.Write(md.HorizontalRule())
37
38 if board.Threads.Size() == 0 {
39 res.Write(md.H3("This board doesn't have any threads"))
40 if !board.Readonly {
41 startConversationLink := md.Link("start a new conversation", makeCreateThreadURI(board))
42 res.Write("Do you want to " + startConversationLink + " in this board ?")
43 }
44 return
45 }
46
47 p, err := pager.New(req.RawPath, board.Threads.Size(), pager.WithPageSize(pageSizeDefault))
48 if err != nil {
49 panic(err)
50 }
51
52 render := func(thread *boards.Post) bool {
53 if !thread.Hidden {
54 res.Write(renderThreadSummary(thread) + "\n")
55 }
56 return false
57 }
58
59 res.Write("Sort by: ")
60
61 r := parseRealmPath(req.RawPath)
62 sortOrder := r.Query.Get("order")
63 if sortOrder == "desc" {
64 r.Query.Set("order", "asc")
65 res.Write(md.Link("newest first", r.String()) + "\n\n")
66 } else {
67 r.Query.Set("order", "desc")
68 res.Write(md.Link("oldest first", r.String()) + "\n\n")
69 }
70
71 count := p.PageSize()
72 if sortOrder == "desc" {
73 count = -count // Reverse iterate
74 }
75
76 board.Threads.Iterate(p.Offset(), count, render)
77
78 if p.HasPages() {
79 res.Write(md.HorizontalRule())
80 res.Write(pager.Picker(p))
81 }
82}
83
84// renderSubMenu renders a sub-menu with a distinct visual pattern.
85func renderSubMenu(items []string) string {
86 if len(items) == 0 {
87 return ""
88 }
89 return "└─ " + strings.Join(items, " • ") + "\n"
90}
91
92func renderBoardMenu(board *boards.Board, req *mux.Request) string {
93 var (
94 b strings.Builder
95 boardMembersURL = makeBoardURI(board) + "/members"
96 )
97
98 if board.Readonly {
99 b.WriteString(md.Link("List Members", boardMembersURL))
100 b.WriteString(" • ")
101 b.WriteString(md.Link("Unfreeze Board", makeUnfreezeBoardURI(board)))
102 b.WriteString("\n")
103 } else {
104 b.WriteString("↳ ")
105 b.WriteString(md.Link("Create Thread", makeCreateThreadURI(board)))
106 b.WriteString(" • ")
107 b.WriteString(md.Link("Request Invite", makeRequestInviteURI(board)))
108 b.WriteString(" • ")
109
110 menu := getCurrentMenu(req.RawPath)
111 if menu == menuManageBoard {
112 b.WriteString(md.Bold("Manage Board"))
113 } else {
114 b.WriteString(md.Link("Manage Board", menuURL(menuManageBoard)))
115 }
116
117 b.WriteString(" \n")
118
119 if menu == menuManageBoard {
120 subMenuItems := []string{
121 md.Link("Invite Member", makeInviteMemberURI(board)),
122 md.Link("List Invite Requests", makeBoardURI(board)+"/invites"),
123 md.Link("List Members", boardMembersURL),
124 md.Link("List Banned Users", makeBoardURI(board)+"/banned-users"),
125 md.Link("Freeze Board", makeFreezeBoardURI(board)),
126 }
127 b.WriteString(renderSubMenu(subMenuItems))
128 }
129 }
130
131 b.WriteString("\n")
132 return b.String()
133}
134
135func renderInviteMember(res *mux.ResponseWriter, req *mux.Request) {
136 name := req.GetVar("board")
137 board, found := gBoards.GetByName(name)
138 if !found {
139 res.Write("Board does not exist: " + name)
140 return
141 }
142
143 form := mdform.New("exec", "InviteMember")
144 form.Input(
145 "boardID",
146 "placeholder", "Board ID",
147 "value", board.ID.String(),
148 "readonly", "true",
149 )
150 form.Input(
151 "user",
152 "placeholder", "Address",
153 "required", "true",
154 )
155 form.Select(
156 "role",
157 string(permissions.RoleOwner),
158 )
159 form.Select(
160 "role",
161 string(permissions.RoleAdmin),
162 )
163 form.Select(
164 "role",
165 string(permissions.RoleModerator),
166 )
167 form.Select(
168 "role",
169 string(permissions.RoleGuest),
170 "selected", "true",
171 )
172
173 res.Write(md.H1(board.Name + ": Invite Member"))
174 res.Write(
175 md.Paragraph(
176 "Both open and invite only boards can have multiple members with different roles within a "+
177 "board, where members can have a single role at a time.",
178 ) +
179 md.Paragraph(
180 "Boards are independent communities which could apply different permissions per role than "+
181 "other boards, but generally Boards2 supports four roles, _owner_, _admin_, _moderator_ "+
182 "and _guest_.",
183 ) +
184 md.Paragraph(
185 "Member will be added to "+md.Link(board.Name, makeBoardURI(board))+" board.",
186 ),
187 )
188 res.Write(form.String())
189}