Search Apps Documentation Source Content File Folder Download Copy Actions Download

render_board.gno

4.70 Kb · 186 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, err := pager.New(req.RawPath, board.Threads.Size(), pager.WithPageSize(pageSizeDefault))
 47	if err != nil {
 48		panic(err)
 49	}
 50
 51	render := func(thread *boards.Post) bool {
 52		res.Write(renderThreadSummary(thread) + "\n")
 53		return false
 54	}
 55
 56	res.Write("Sort by: ")
 57
 58	r := parseRealmPath(req.RawPath)
 59	sortOrder := r.Query.Get("order")
 60	if sortOrder == "desc" {
 61		r.Query.Set("order", "asc")
 62		res.Write(md.Link("newest first", r.String()) + "\n\n")
 63	} else {
 64		r.Query.Set("order", "desc")
 65		res.Write(md.Link("oldest first", r.String()) + "\n\n")
 66	}
 67
 68	count := p.PageSize()
 69	if sortOrder == "desc" {
 70		count = -count // Reverse iterate
 71	}
 72
 73	board.Threads.Iterate(p.Offset(), count, render)
 74
 75	if p.HasPages() {
 76		res.Write(md.HorizontalRule())
 77		res.Write(pager.Picker(p))
 78	}
 79}
 80
 81// renderSubMenu renders a sub-menu with a distinct visual pattern.
 82func renderSubMenu(items []string) string {
 83	if len(items) == 0 {
 84		return ""
 85	}
 86	return "└─ " + strings.Join(items, " • ") + "\n"
 87}
 88
 89func renderBoardMenu(board *boards.Board, req *mux.Request) string {
 90	var (
 91		b               strings.Builder
 92		boardMembersURL = makeBoardURI(board) + "/members"
 93	)
 94
 95	if board.Readonly {
 96		b.WriteString(md.Link("List Members", boardMembersURL))
 97		b.WriteString(" • ")
 98		b.WriteString(md.Link("Unfreeze Board", makeUnfreezeBoardURI(board)))
 99		b.WriteString("\n")
100	} else {
101		b.WriteString("↳ ")
102		b.WriteString(md.Link("Create Thread", makeCreateThreadURI(board)))
103		b.WriteString(" • ")
104		b.WriteString(md.Link("Request Invite", makeRequestInviteURI(board)))
105		b.WriteString(" • ")
106
107		menu := getCurrentMenu(req.RawPath)
108		if menu == menuManageBoard {
109			b.WriteString(md.Bold("Manage Board"))
110		} else {
111			b.WriteString(md.Link("Manage Board", menuURL(menuManageBoard)))
112		}
113
114		b.WriteString("  \n")
115
116		if menu == menuManageBoard {
117			subMenuItems := []string{
118				md.Link("Invite Member", makeInviteMemberURI(board)),
119				md.Link("List Invite Requests", makeBoardURI(board)+"/invites"),
120				md.Link("List Members", boardMembersURL),
121				md.Link("List Banned Users", makeBoardURI(board)+"/banned-users"),
122				md.Link("Freeze Board", makeFreezeBoardURI(board)),
123			}
124			b.WriteString(renderSubMenu(subMenuItems))
125		}
126	}
127
128	b.WriteString("\n")
129	return b.String()
130}
131
132func renderInviteMember(res *mux.ResponseWriter, req *mux.Request) {
133	name := req.GetVar("board")
134	board, found := gBoards.GetByName(name)
135	if !found {
136		res.Write("Board not found")
137		return
138	}
139
140	form := mdform.New("exec", "InviteMember")
141	form.Input(
142		"boardID",
143		"placeholder", "Board ID",
144		"value", board.ID.String(),
145		"readonly", "true",
146	)
147	form.Input(
148		"user",
149		"placeholder", "Address",
150		"required", "true",
151	)
152	form.Select(
153		"role",
154		string(RoleOwner),
155	)
156	form.Select(
157		"role",
158		string(RoleAdmin),
159	)
160	form.Select(
161		"role",
162		string(RoleModerator),
163	)
164	form.Select(
165		"role",
166		string(RoleGuest),
167		"selected", "true",
168	)
169
170	res.Write(md.H1(board.Name + ": Invite Member"))
171	res.Write(
172		md.Paragraph(
173			"Both open and invite only boards can have multiple members with different roles within a "+
174				"board, where members can have a single role at a time.",
175		) +
176			md.Paragraph(
177				"Boards are independent communities which could apply different permissions per role than "+
178					"other boards, but generally Boards2 supports four roles, _owner_, _admin_, _moderator_ "+
179					"and _guest_.",
180			) +
181			md.Paragraph(
182				"Member will be added to "+md.Link(board.Name, makeBoardURI(board))+" board.",
183			),
184	)
185	res.Write(form.String())
186}