v0.29.0 55fcc8f

inbox.templ RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package web
4
5// Inbox is the owner's inbox: what is open across every repository. The
6// counters, the filter and the lists are fragments with an id that the live
7// stream replaces as a whole (ermiteLive.swap).
8templ Inbox(l Layout, p InboxPage) {
9	@Shell(l, nil) {
10		<h1 class="sr">Inbox</h1>
11		<div class="inbox">
12			@InboxCounters(p)
13			@InboxRepos(p)
14			@InboxPending(p)
15			@InboxMRs(p)
16			@InboxIssues(p)
17		</div>
18	}
19}
20
21templ InboxCounters(p InboxPage) {
22	<p id="inbox-counts" class="inbox-counts">
23		<strong>{ itoa(p.MergeRequests) }</strong> merge requests · <strong>{ itoa(p.Issues) }</strong> issues · <strong>{ itoa(p.PendingCount) }</strong> awaiting moderation
24	</p>
25}
26
27templ InboxRepos(p InboxPage) {
28	<nav id="inbox-repos" class="since" aria-label="Repository">
29		for _, r := range p.Repos {
30			<a
31				href={ templ.SafeURL(r.Href) }
32				if r.Current {
33					aria-current="page"
34				}
35			>{ r.Label }</a>
36		}
37	</nav>
38}
39
40// InboxPending is the issues awaiting moderation, first on the page. Their
41// texts come from anonymous visitors: they are shown as plain text, escaped,
42// never as Markdown.
43templ InboxPending(p InboxPage) {
44	<section id="inbox-pending" aria-labelledby="inbox-pending-h">
45		<h2 id="inbox-pending-h" class="rule-h"><span>Awaiting moderation</span><span class="count">{ itoa(p.PendingCount) }</span></h2>
46		if len(p.Pending) > 0 {
47			<ul class="pending-list">
48				for _, m := range p.Pending {
49					<li class="pending">
50						<div class="p-head">
51							<a href={ templ.SafeURL(m.RepoHref) }>{ m.Repo }</a>
52							<span>{ m.Author }</span>
53							if m.WhenAt != "" {
54								<time datetime={ m.WhenAt } title={ m.WhenAt }>{ m.When }</time>
55							}
56						</div>
57						<p class="p-title">{ m.Title }</p>
58						if m.Preview != "" {
59							<p class="p-body">{ m.Preview }</p>
60						}
61						if m.Approve != "" {
62							<div class="p-btns">
63								<form method="post" action={ templ.SafeURL(m.Approve) }><button type="submit" class="btn primary">Approve</button></form>
64								<form method="post" action={ templ.SafeURL(m.Reject) }><button type="submit" class="btn">Reject</button></form>
65								<form method="post" action={ templ.SafeURL(m.Ban) }><button type="submit" class="btn danger">Reject and ban</button></form>
66							</div>
67						}
68					</li>
69				}
70			</ul>
71		} else {
72			<p class="lede dim">nothing awaits moderation.</p>
73		}
74	</section>
75}
76
77templ InboxMRs(p InboxPage) {
78	<section id="inbox-mrs" aria-labelledby="inbox-mrs-h">
79		<h2 id="inbox-mrs-h" class="rule-h"><span>Open merge requests</span><span class="count">{ itoa(len(p.MRs)) }</span></h2>
80		@inboxRows(p.MRs, "Open merge requests")
81		if len(p.MRs) == 0 {
82			<p class="lede dim">no open merge requests.</p>
83		}
84	</section>
85}
86
87templ InboxIssues(p InboxPage) {
88	<section id="inbox-issues" aria-labelledby="inbox-issues-h">
89		<h2 id="inbox-issues-h" class="rule-h"><span>Open issues</span><span class="count">{ itoa(len(p.IssueRows)) }</span></h2>
90		@inboxRows(p.IssueRows, "Open issues")
91		if len(p.IssueRows) == 0 {
92			<p class="lede dim">no open issues.</p>
93		}
94	</section>
95}
96
97templ inboxRows(rows []InboxRow, label string) {
98	if len(rows) > 0 {
99		<table class="list mrs" aria-label={ label }>
100			<tbody data-rows>
101				for _, m := range rows {
102					<tr data-cursor?={ m.Cursor } data-state="open">
103						<td class="c-n mute">{ m.Number }</td>
104						<td class="c-subject"><a href={ templ.SafeURL(m.Href) }>{ m.Title }</a> <a class="mute" href={ templ.SafeURL(m.RepoHref) }>{ m.Repo }</a></td>
105						<td class="c-when nowrap dim">
106							if m.WhenAt != "" {
107								<time datetime={ m.WhenAt } title={ m.WhenAt }>{ m.When }</time>
108							}
109						</td>
110					</tr>
111				}
112			</tbody>
113		</table>
114	}
115}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 44

↑↓ moveenter openesc close