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