Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · server/web/templates/issues.html

Line attribution on main · 270 line(s)

f09ef39e
Keenan Nemetz
15d ago
1 {{define "issues"}}
2 {{template "header" .}}
5d440e37
Keenan Nemetz
10d ago
3 {{template "repohead" (nav .Page "issues")}}
f09ef39e
Keenan Nemetz
15d ago
4
5 <div class="page-head">
a464f892
Keenan Nemetz
15d ago
6 <div class="page-head-main">
f09ef39e
Keenan Nemetz
15d ago
7 <h1>Issues</h1>
20d459f5
Keenan Nemetz
11d ago
8 <p class="page-sub">Problems and suggestions from the people who use this project.</p>
f09ef39e
Keenan Nemetz
15d ago
9 </div>
ed03b3d1
Keenan Nemetz
3h ago
10 {{if .CanDiscuss}}<div class="page-head-actions"><a class="button" href="/{{.Name}}/issues/new">{{icon "plus"}}New issue</a></div>{{end}}
f09ef39e
Keenan Nemetz
15d ago
11 </div>
12
13 {{template "issue_list" .}}
14 {{template "footer" .}}
15 {{end}}
16
6813339b
Keenan Nemetz
4d ago
17 {{/* The list's status is the same shape as a change's: a reader scanning two
18 lists should not have to learn two visual languages. */}}
19 {{define "issue_status"}}{{if eq . "open"}}<span class="row-status open">{{icon "circle-dot"}}Open</span>{{else}}<span class="row-status closed">{{icon "circle-check"}}Closed</span>{{end}}{{end}}
20
f09ef39e
Keenan Nemetz
15d ago
21 {{define "issue_list"}}
22 <div id="issue-list">
6c98a271
Keenan Nemetz
9d ago
23 {{/* One row: the state chips and the dropdowns on the left, the search field on
24 the right. The form wraps the chips so a search submits the state too, and
25 so a swap replaces the row with the values the server rendered. */}}
ed03b3d1
Keenan Nemetz
3h ago
26 <form method="get" action="/{{.Name}}/issues" class="filters" role="search" hx-get="/{{.Name}}/issues" hx-target="#issue-list" hx-swap="outerHTML" hx-push-url="true">
6c98a271
Keenan Nemetz
9d ago
27 <div class="chips" hx-boost="true" hx-target="#issue-list" hx-swap="outerHTML" hx-push-url="true">
ed03b3d1
Keenan Nemetz
3h ago
28 <a class="chip{{if eq .State "open"}} active{{end}}" href="/{{.Name}}/issues?state=open{{if .Filter.Query}}&amp;q={{urlquery .Filter.Query}}{{end}}{{if .Filter.Label}}&amp;label={{urlquery .Filter.Label}}{{end}}{{if .Filter.Assignee}}&amp;assignee={{urlquery .Filter.Assignee}}{{end}}">Open <span class="chip-count">{{.Open}}</span></a>
29 <a class="chip{{if eq .State "closed"}} active{{end}}" href="/{{.Name}}/issues?state=closed{{if .Filter.Query}}&amp;q={{urlquery .Filter.Query}}{{end}}{{if .Filter.Label}}&amp;label={{urlquery .Filter.Label}}{{end}}{{if .Filter.Assignee}}&amp;assignee={{urlquery .Filter.Assignee}}{{end}}">Closed <span class="chip-count">{{.Closed}}</span></a>
30 <a class="chip{{if eq .State "all"}} active{{end}}" href="/{{.Name}}/issues?state=all{{if .Filter.Query}}&amp;q={{urlquery .Filter.Query}}{{end}}{{if .Filter.Label}}&amp;label={{urlquery .Filter.Label}}{{end}}{{if .Filter.Assignee}}&amp;assignee={{urlquery .Filter.Assignee}}{{end}}">All <span class="chip-count">{{.Total}}</span></a>
6c98a271
Keenan Nemetz
9d ago
31 </div>
f09ef39e
Keenan Nemetz
15d ago
32 <input type="hidden" name="state" value="{{.State}}">
33 {{if .Labels}}
2e024cc9
Keenan Nemetz
14d ago
34 <label class="filter-field">
55615c7a
Keenan Nemetz
11d ago
35 <span class="filter-label">Label</span>
36 <select name="label" data-autosubmit>
37 <option value="">All</option>
2e024cc9
Keenan Nemetz
14d ago
38 {{range .Labels}}<option value="{{.}}"{{if eq . $.Filter.Label}} selected{{end}}>{{.}}</option>{{end}}
39 </select>
40 </label>
f09ef39e
Keenan Nemetz
15d ago
41 {{end}}
42 {{if .Assignees}}
2e024cc9
Keenan Nemetz
14d ago
43 <label class="filter-field">
55615c7a
Keenan Nemetz
11d ago
44 <span class="filter-label">Assignee</span>
45 <select name="assignee" data-autosubmit>
46 <option value="">All</option>
2e024cc9
Keenan Nemetz
14d ago
47 {{range .Assignees}}<option value="{{.}}"{{if eq . $.Filter.Assignee}} selected{{end}}>@{{.}}</option>{{end}}
48 </select>
49 </label>
f09ef39e
Keenan Nemetz
15d ago
50 {{end}}
6c98a271
Keenan Nemetz
9d ago
51 <div class="filters-search">
52 <input name="q" type="search" placeholder="Search title and body" aria-label="Search title and body" value="{{.Filter.Query}}">
53 <button type="submit">{{icon "search"}}Search</button>
ed03b3d1
Keenan Nemetz
3h ago
54 {{if .Filtered}}<a class="button secondary" href="/{{.Name}}/issues" hx-get="/{{.Name}}/issues" hx-target="#issue-list" hx-swap="outerHTML" hx-push-url="true">{{icon "x"}}Clear</a>{{end}}
6c98a271
Keenan Nemetz
9d ago
55 </div>
f09ef39e
Keenan Nemetz
15d ago
56 </form>
57
58 {{if .Issues}}
59 <div class="panel">
60 <table class="issue-list">
61 <thead>
c67173ca
Keenan Nemetz
4d ago
62 <tr><th>Status</th><th>Issue</th><th>Labels</th><th>Assignees</th><th>Updated</th></tr>
f09ef39e
Keenan Nemetz
15d ago
63 </thead>
64 <tbody>
65 {{range .Issues}}
66 <tr>
6813339b
Keenan Nemetz
4d ago
67 <td class="fit">{{template "issue_status" .State}}</td>
f09ef39e
Keenan Nemetz
15d ago
68 <td>
ed03b3d1
Keenan Nemetz
3h ago
69 <a class="row-title" href="/{{$.Name}}/issues/{{.ID}}">{{.Title}}</a>
f09ef39e
Keenan Nemetz
15d ago
70 <div class="row-meta">
e05f1c48
Keenan Nemetz
13d ago
71 <span class="sha">{{num .Number}}</span>
db4081ec
Keenan Nemetz
4d ago
72 <span>opened by {{template "userlink" (user .Author)}} {{since .Created.Unix}}</span>
946d2fd4
Keenan Nemetz
4d ago
73 {{if .Comments}}<span>{{.Comments}} comment{{if ne .Comments 1}}s{{end}}</span>{{end}}
f09ef39e
Keenan Nemetz
15d ago
74 </div>
75 </td>
db4081ec
Keenan Nemetz
4d ago
76 <td><div class="label-row">{{range .Labels}}<span class="label">{{.}}</span>{{else}}<span class="muted">—</span>{{end}}</div></td>
77 <td class="nowrap">{{range $i, $a := .Assignees}}{{if $i}}, {{end}}{{template "userlink" (user $a)}}{{else}}<span class="muted">—</span>{{end}}</td>
78 <td class="muted nowrap">{{since .Updated.Unix}}</td>
f09ef39e
Keenan Nemetz
15d ago
79 </tr>
80 {{end}}
81 </tbody>
82 </table>
83 </div>
c717d4eb
Keenan Nemetz
13d ago
84 {{template "pager" .Pager}}
f09ef39e
Keenan Nemetz
15d ago
85 {{else if and (eq .State "open") .Closed}}
86 <div class="empty-state">
c7b9094f
Keenan Nemetz
1d ago
87 <p>No open issues.</p>
f09ef39e
Keenan Nemetz
15d ago
88 </div>
89 {{else if .Filtered}}
90 <div class="empty-state">
91 <p>No issues match this filter.</p>
92 </div>
93 {{else}}
94 <div class="empty-state">
95 <p>No issues yet.</p>
96 <p class="muted">From a clone of this repository:</p>
97 <pre>vole issue new --title "..." -m "..."</pre>
98 <p class="muted">An issue is also just a file on the <code>vole</code> branch:
99 <code>issues/&lt;ulid&gt;/issue.md</code> — frontmatter with the title, state and labels,
100 then the body as markdown.</p>
101 </div>
102 {{end}}
103 </div>
104 {{end}}
105
106 {{define "issue_labels"}}
107 <section id="issue-labels">
108 <h2>{{icon "tag"}}Labels</h2>
109 {{if .Error}}<p class="error">{{.Error}}</p>{{end}}
110 {{if .CanEditLabels}}
ed03b3d1
Keenan Nemetz
3h ago
111 <form method="post" action="/{{.Name}}/issues/{{.Issue.ID}}/labels" class="label-form" hx-post="/{{.Name}}/issues/{{.Issue.ID}}/labels" hx-target="#issue-labels" hx-swap="outerHTML" hx-trigger="token-change" hx-sync="this:replace">
f09ef39e
Keenan Nemetz
15d ago
112 <input type="hidden" name="csrf" value="{{.CSRF}}">
306f36fc
Keenan Nemetz
12d ago
113 {{template "token_input" (tokenPicker .Issue.Labels .AllLabels "label" "Add labels…")}}
f09ef39e
Keenan Nemetz
15d ago
114 </form>
115 {{else}}
116 {{if .Issue.Labels}}
117 <div class="label-row">{{range .Issue.Labels}}<span class="label">{{.}}</span>{{end}}</div>
118 {{else}}
119 <p class="muted">No labels.</p>
120 {{end}}
121 {{end}}
122 </section>
123 {{end}}
124
125 {{define "issue_assignees"}}
126 <section id="issue-assignees">
127 <h2>{{icon "users"}}Assignees</h2>
128 {{if .Error}}<p class="error">{{.Error}}</p>{{end}}
129 {{if .CanEditAssignees}}
ed03b3d1
Keenan Nemetz
3h ago
130 <form method="post" action="/{{.Name}}/issues/{{.Issue.ID}}/assignees" class="label-form" hx-post="/{{.Name}}/issues/{{.Issue.ID}}/assignees" hx-target="#issue-assignees" hx-swap="outerHTML" hx-trigger="token-change" hx-sync="this:replace">
f09ef39e
Keenan Nemetz
15d ago
131 <input type="hidden" name="csrf" value="{{.CSRF}}">
306f36fc
Keenan Nemetz
12d ago
132 {{template "token_input" (tokenPicker .Issue.Assignees .Assignable "assignee" "Add assignees…")}}
f09ef39e
Keenan Nemetz
15d ago
133 </form>
134 {{else}}
135 {{if .Issue.Assignees}}
ed03b3d1
Keenan Nemetz
3h ago
136 <div class="label-row">{{range .Issue.Assignees}}<a class="label" href="/{{$.Name}}/issues?assignee={{urlquery .}}">@{{.}}</a>{{end}}</div>
f09ef39e
Keenan Nemetz
15d ago
137 {{else}}
138 <p class="muted">No assignees.</p>
139 {{end}}
140 {{end}}
141 </section>
142 {{end}}
143
802e0e52
Keenan Nemetz
4d ago
144 {{define "issue_head"}}
145 <div class="page-head" id="issue-head">
a464f892
Keenan Nemetz
15d ago
146 <div class="page-head-main">
802e0e52
Keenan Nemetz
4d ago
147 <div class="details-title">
148 <span class="page-num">{{num .Number}}</span>
149 <h1 class="details-title-view" data-details-title-view{{if .Details.Title.Active}} hidden{{end}}>{{.Issue.Title}}</h1>
150 {{if .CanEdit}}
ed03b3d1
Keenan Nemetz
3h ago
151 <a class="title-edit-toggle" href="/{{.Name}}/issues/{{.Issue.ID}}/edit" data-title-edit{{if .Details.Title.Active}} hidden{{end}} aria-label="Edit title" title="Edit title">{{icon "pencil"}}</a>
152 <form class="title-edit-form" data-title-edit-form method="post" action="/{{.Name}}/issues/{{.Issue.ID}}/edit" hx-post="/{{.Name}}/issues/{{.Issue.ID}}/edit" hx-target="#issue-head" hx-swap="outerHTML" hx-disabled-elt="find button[type='submit']"{{if not .Details.Title.Active}} hidden{{end}}>
802e0e52
Keenan Nemetz
4d ago
153 <input type="hidden" name="csrf" value="{{.CSRF}}">
154 <input type="hidden" name="field" value="title">
155 <input class="details-title-input" type="text" name="title" required maxlength="200" aria-label="Title" value="{{if .Details.Title.Active}}{{.Details.Title.Value}}{{else}}{{.Issue.Title}}{{end}}" data-title-edit-input{{if .Details.Title.Active}} autofocus{{end}}>
156 <button class="secondary" type="button" data-title-edit-cancel>Cancel</button>
157 <button type="submit">{{icon "check"}}Save</button>
158 </form>
159 {{end}}
160 </div>
161 {{if .Details.Title.Error}}<p class="error">{{.Details.Title.Error}}</p>{{end}}
f09ef39e
Keenan Nemetz
15d ago
162 <p class="page-sub">
163 <span class="state {{.Issue.State}}">{{.Issue.State}}</span>
a6b42433
Keenan Nemetz
7d ago
164 · opened by {{template "userlink" (user .Issue.Author)}} {{since .Issue.Created.Unix}}
f09ef39e
Keenan Nemetz
15d ago
165 </p>
166 </div>
802e0e52
Keenan Nemetz
4d ago
167 {{if .CanClose}}
564acd4b
Keenan Nemetz
15d ago
168 <div class="page-head-actions">
ed03b3d1
Keenan Nemetz
3h ago
169 <form method="post" action="/{{.Name}}/issues/{{.Issue.ID}}/state">
564acd4b
Keenan Nemetz
15d ago
170 <input type="hidden" name="csrf" value="{{.CSRF}}">
171 <input type="hidden" name="state" value="{{if eq .Issue.State "open"}}closed{{else}}open{{end}}">
f6f4b1db
Keenan Nemetz
15d ago
172 <button class="{{if eq .Issue.State "open"}}danger{{else}}secondary{{end}}" type="submit">{{if eq .Issue.State "open"}}{{icon "circle-x"}}Close{{else}}{{icon "rotate-ccw"}}Reopen{{end}}</button>
564acd4b
Keenan Nemetz
15d ago
173 </form>
174 </div>
175 {{end}}
f09ef39e
Keenan Nemetz
15d ago
176 </div>
802e0e52
Keenan Nemetz
4d ago
177 {{end}}
178
179 {{define "issue_description"}}
180 <article class="comment{{if .Details.Description.Active}} editing{{end}}" id="issue-description">
181 <header class="comment-head">
182 {{$u := user .Issue.Author}}
183 <span class="comment-author">{{template "userlink" $u}}</span>
184 <span class="muted">opened this {{since .Issue.Created.Unix}}</span>
185 <div class="comment-menu" data-comment-menu>
186 <button type="button" class="comment-menu-toggle" data-comment-menu-toggle aria-haspopup="menu" aria-expanded="false" aria-label="Description actions">&#8943;</button>
187 <div class="comment-menu-list" data-comment-menu-list role="menu" hidden>
188 <button type="button" role="menuitem" data-copy-query="{{urlquery .Issue.Description}}">Copy text</button>
189 {{if .CanEdit}}<button type="button" role="menuitem" data-comment-edit>Edit</button>{{end}}
190 </div>
191 </div>
192 </header>
193 <div class="comment-body md">
194 {{if .Description}}{{.Description}}{{else}}<p class="muted">No description.</p>{{end}}
195 </div>
196 {{if .CanEdit}}
ed03b3d1
Keenan Nemetz
3h ago
197 <form class="comment-edit-form details-edit-form" data-comment-edit-form method="post" action="/{{.Name}}/issues/{{.Issue.ID}}/edit" hx-post="/{{.Name}}/issues/{{.Issue.ID}}/edit" hx-target="#issue-description" hx-swap="outerHTML" hx-disabled-elt="find button[type='submit']"{{if not .Details.Description.Active}} hidden{{end}}>
802e0e52
Keenan Nemetz
4d ago
198 <input type="hidden" name="csrf" value="{{.CSRF}}">
199 <input type="hidden" name="field" value="body">
200 {{if .Details.Description.Error}}<p class="error">{{.Details.Description.Error}}</p>{{end}}
201 <textarea name="body" data-autosize aria-label="Description">{{if .Details.Description.Active}}{{.Details.Description.Value}}{{else}}{{.Issue.Description}}{{end}}</textarea>
202 <div class="form-actions">
203 <button class="secondary" type="button" data-comment-edit-cancel>Cancel</button>
204 <button type="submit">{{icon "check"}}Save</button>
205 </div>
206 </form>
207 {{end}}
208 </article>
209 {{end}}
210
fd9aa8ed
Keenan Nemetz
23h ago
211 {{/* A change request that names the issue in its closes list is a reference the
212 issue can show back. The rows are the compact shape the overview and the
213 change sidebar already use, so the reader does not learn a second one. */}}
214 {{define "issue_linked_changes"}}
215 {{if .LinkedChanges}}
216 <section id="issue-changes">
217 <h2>{{icon "git-pull-request"}}Referenced in changes</h2>
218 <div class="side-list">
219 {{range .LinkedChanges}}
ed03b3d1
Keenan Nemetz
3h ago
220 <a class="side-change" href="/{{$.Name}}/changes/{{.ID}}">
fd9aa8ed
Keenan Nemetz
23h ago
221 <span class="side-subject"><span class="side-num">{{num .Number}}</span>{{.Title}}</span>
222 <span class="side-meta"><span class="state {{.State}}">{{.State}}</span>{{who .Author}}{{if not .Created.IsZero}}<span>{{since .Created.Unix}}</span>{{end}}</span>
223 </a>
224 {{end}}
225 </div>
226 </section>
227 {{end}}
228 {{end}}
229
230 {{/* Commits are the other way a branch mentions an issue. git does the search,
231 so the section shows the same rows the full-width table did, in the side
232 column's compact shape. */}}
233 {{define "issue_backlinks"}}
234 {{if .Backlinks}}
235 <section id="issue-commits">
236 <h2>{{icon "git-commit-horizontal"}}Referenced in commits</h2>
237 <div class="side-list">
238 {{range .Backlinks}}
ed03b3d1
Keenan Nemetz
3h ago
239 <a class="side-commit" href="/{{$.Name}}/commit/{{.SHA}}">
fd9aa8ed
Keenan Nemetz
23h ago
240 <span class="side-subject">{{.Subject}}</span>
241 <span class="side-meta"><span class="sha">{{short .SHA}}</span>{{if .Author}}<span>{{.Author}}</span>{{end}}<span>{{since .When}}</span></span>
242 </a>
243 {{end}}
244 </div>
245 </section>
246 {{end}}
247 {{end}}
248
802e0e52
Keenan Nemetz
4d ago
249 {{define "issue"}}
250 {{template "header" .}}
251 {{template "repohead" (nav .Page "issues")}}
252
253 {{template "issue_head" .}}
f09ef39e
Keenan Nemetz
15d ago
254
255 <div class="thread">
256 <div class="thread-main">
802e0e52
Keenan Nemetz
4d ago
257 {{template "issue_description" .}}
f09ef39e
Keenan Nemetz
15d ago
258
c717d4eb
Keenan Nemetz
13d ago
259 {{template "comment_thread" .Thread}}
f09ef39e
Keenan Nemetz
15d ago
260 </div>
261
262 <aside class="thread-side">
263 {{template "issue_labels" .}}
264 {{template "issue_assignees" .}}
fd9aa8ed
Keenan Nemetz
23h ago
265 {{template "issue_linked_changes" .}}
266 {{template "issue_backlinks" .}}
f09ef39e
Keenan Nemetz
15d ago
267 </aside>
268 </div>
269 {{template "footer" .}}
270 {{end}}