internal/web/templates/layout.html
242 lines · 19666 bytes
1{{define "layout"}}<!DOCTYPE html>
2<html lang="en"{{with field . "Theme"}} data-theme="{{.}}"{{end}}>
3<head>
4<meta charset="utf-8">
5<meta name="viewport" content="width=device-width, initial-scale=1">
6<title>{{template "title" .}}</title>
7<link rel="stylesheet" href="/static/style.css?v={{styleVersion}}">
8<link rel="icon" href="/favicon.svg" type="image/svg+xml">
9<meta name="theme-color" content="#000000">
10{{with field . "Feed"}}<link rel="alternate" type="application/atom+xml" href="{{.}}">
11{{end}}</head>
12<body>
13<a class="skip" href="#content">Skip to content</a>
14<div class="shell">
15
16<nav class="rail" aria-label="Site">
17 <a class="brand" href="/" aria-label="{{.Site}} home">{{template "mark"}}<span class="vh">{{.Site}}</span></a>
18 {{/* A square is .railopt when the phone rail drops it into the More
19 menu below. The menu repeats those destinations, so the two lists
20 are kept in step by hand: add a square there and add it here. */}}
21 <ul class="raillist">
22 {{if .Viewer}}<li>{{template "raillink" dict "Href" "/" "Icon" "home" "Name" "Dashboard" "Current" (eq (str . "Tab") "dashboard")}}</li>{{end}}
23 <li>{{template "raillink" dict "Href" "/explore" "Icon" "compass" "Name" "Explore" "Current" (eq (str . "Tab") "explore")}}</li>
24 <li>{{template "raillink" dict "Href" "/search" "Icon" "search" "Name" "Search" "Current" (eq (str . "Tab") "sitesearch")}}</li>
25 {{if .Viewer}}<li>{{template "raillink" dict "Href" "/notifications" "Icon" "bell" "Name" "Notifications" "Current" (eq (str . "Tab") "notifications") "Count" .Rail.Unread}}</li>
26 <li class="railopt">{{template "raillink" dict "Href" "/new" "Icon" "plus" "Name" "New repository"}}</li>{{end}}
27 </ul>
28 <span class="railgap"></span>
29 <ul class="raillist">
30 {{if .Viewer}}<li class="railopt">{{template "raillink" dict "Href" "/settings" "Icon" "gear" "Name" "Settings" "Current" (eq (str . "Tab") "account")}}</li>{{end}}
31 {{if .Admin}}<li class="railopt">{{template "raillink" dict "Href" "/admin" "Icon" "shield" "Name" "Admin" "Current" (eq (str . "Tab") "admin")}}</li>{{end}}
32 </ul>
33 <div class="railfoot">
34 {{if .Viewer}}<details class="railmore">
35 <summary class="railicon" aria-label="More" title="More">{{template "icon" "ellipsis"}}<span class="vh">More</span></summary>
36 <div class="raildrop">
37 <a href="/new">{{template "icon" "plus"}} New repository</a>
38 <a href="/settings">{{template "icon" "gear"}} Settings</a>
39 {{if .Admin}}<a href="/admin">{{template "icon" "shield"}} Admin</a>{{end}}
40 <a href="/logout">{{template "icon" "signout"}} Log out</a>
41 </div>
42 </details>
43 <a class="railuser" href="/{{.Viewer}}" aria-label="Your profile" title="{{.Viewer}}"><span class="avatar">{{initial .Viewer}}</span></a>
44 <a class="railopt railicon" href="/logout" aria-label="Log out" title="Log out">{{template "icon" "signout"}}<span class="vh">Log out</span></a>
45 {{else}}<a class="railicon" href="/login" aria-label="Sign in" title="Sign in">{{template "icon" "person"}}<span class="vh">Sign in</span></a>{{end}}
46 </div>
47</nav>
48
49<div class="pane">
50{{with field . "Repo"}}
51<header class="repohead">
52<div class="wrap">
53 {{$top := topTab (str $ "Tab")}}
54 <div class="identity">
55 {{if field $ "RepoHome"}}<h1 class="repotitle"><a class="owner" href="/{{.OwnerName}}">{{.OwnerName}}</a><span class="sep">/</span>{{.Name}}</h1>
56 {{else}}<p class="repotitle"><a class="owner" href="/{{.OwnerName}}">{{.OwnerName}}</a><span class="sep">/</span><a href="/{{.OwnerName}}/{{.Name}}">{{.Name}}</a></p>{{end}}
57 {{if eq .Visibility "private"}}<span class="chip">Private</span>{{end}}
58 {{if .Settings.Archived}}<span class="chip">Archived</span>{{end}}
59 {{/* Description, topics and website belong to the code tab, inline
60 with the name so the header is two rows on every page. */}}
61 {{if eq $top "code"}}{{if or (field $ "Desc") (field $ "Topics") $.Repo.Settings.Website}}<p class="repodesc">{{with field $ "Desc"}}{{.}}{{end}} {{with field $ "Topics"}}{{range .}}<a class="chip topic" href="/explore?q={{.}}">{{.}}</a> {{end}}{{end}}{{with $.Repo.Settings.Website}}<a class="site" href="{{.}}" rel="nofollow">{{.}}</a>{{end}}</p>{{end}}{{end}}
62 <span class="grow"></span>
63 {{if $.Viewer}}<form method="post" action="/{{.OwnerName}}/{{.Name}}/pin" class="inline"><button type="submit" class="btn" aria-pressed="{{if field $ "Pinned"}}true{{else}}false{{end}}" title="Pinned repositories show on your dashboard"><span aria-hidden="true">{{if field $ "Pinned"}}★{{else}}☆{{end}}</span> {{if field $ "Pinned"}}Pinned{{else}}Pin{{end}}</button></form>
64 <form method="post" action="/{{.OwnerName}}/{{.Name}}/watch" class="inline"><button type="submit" class="btn" aria-pressed="{{if eq (str $ "Watch") "watching"}}true{{else}}false{{end}}" title="Watching sends every issue, request and build to your inbox">{{if eq (str $ "Watch") "watching"}}Watching{{else}}Watch{{end}}</button></form>
65 <form method="post" action="/{{.OwnerName}}/{{.Name}}/bookmark" class="inline"><button type="submit" class="btn" aria-pressed="{{if field $ "Marked"}}true{{else}}false{{end}}" title="Bookmarked lists it under Bookmarks">{{if field $ "Marked"}}Bookmarked{{else}}Bookmark{{end}}</button></form>
66 <a class="button btn" href="/{{.OwnerName}}/{{.Name}}/fork">Fork</a>{{end}}
67 </div>
68 {{if eq $top "code"}}{{if field $ "Mirrors"}}<p class="repometa">{{range $i, $m := field $ "Mirrors"}}{{if $i}} · {{end}}{{if eq $m.Direction "push"}}mirrors to{{else}}mirrors from{{end}} <a href="{{$m.URL}}" rel="nofollow">{{$m.Target}}</a>{{if $m.Error}}, <span class="bad">sync error: {{$m.Error}}</span>{{else if $m.Synced}}, synced {{$m.Synced}}{{end}}{{end}}</p>{{end}}{{end}}
69 <nav class="tabs" aria-label="Repository">
70 <a {{if eq $top "code"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}">Code</a>
71 <a {{if eq $top "issues"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/issues">Issues{{with field $ "OpenIssues"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a>
72 <a {{if eq $top "mrs"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/mrs">Merge requests{{with field $ "OpenMRs"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a>
73 <a {{if eq $top "builds"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/builds">Builds</a>
74 <a {{if eq $top "releases"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/releases">Releases</a>
75 {{if field $ "HasWiki"}}<a {{if eq $top "wiki"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/wiki">Wiki</a>{{end}}
76 {{if field $ "CanAdmin"}}<a {{if eq $top "settings"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/settings">Settings</a>{{end}}
77 </nav>
78</div>
79</header>
80{{end}}
81
82<main id="content" class="content {{template "width" .}}">
83{{template "content" .}}
84</main>
85
86<footer>
87 <p>Powered by <a href="https://gitbay.org/krz/gitbay">gitbay</a>{{with gitbayVersion}} · <code><a href="https://gitbay.org/krz/gitbay/commit/{{gitbayCommit}}">{{.}}</a></code>{{end}} · <a href="https://apps.apple.com/us/app/gitbay/id6806399095">iOS app</a> · <a href="/privacy">Privacy</a></p>
88</footer>
89</div>
90</div>
91</body>
92</html>{{end}}
93
94{{/* icon draws one 16px glyph for the rail. The argument names it. The
95 paths are stroked with currentColor, so a link's own colour and the
96 current marker carry through, and every one is hidden from the
97 accessibility tree — the link around it carries the name. */}}
98{{define "icon"}}<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
99{{- if eq . "home"}}<path d="M2.25 7 8 2.5 13.75 7v6.25a.5.5 0 0 1-.5.5H2.75a.5.5 0 0 1-.5-.5Z"/><path d="M6.25 13.75V9.25h3.5v4.5"/>
100{{- else if eq . "search"}}<circle cx="6.75" cy="6.75" r="4.25"/><path d="m9.9 9.9 3.6 3.6"/>
101{{- else if eq . "bell"}}<path d="M4.25 7a3.75 3.75 0 0 1 7.5 0v2.25l1.25 2.25H3l1.25-2.25Z"/><path d="M6.5 11.5a1.5 1.5 0 0 0 3 0"/>
102{{- else if eq . "bookmark"}}<path d="M4 2.75h8v11L8 10.5l-4 3.25Z"/>
103{{- else if eq . "compass"}}<circle cx="8" cy="8" r="6"/><path d="m10.5 5.5-1.25 3.75-3.75 1.25 1.25-3.75Z"/>
104{{- else if eq . "plus"}}<path d="M8 3.25v9.5M3.25 8h9.5"/>
105{{- else if eq . "gear"}}<path d="M6.63 1.13L9.37 1.13L9.51 3.02L10.45 3.41L11.89 2.18L13.82 4.11L12.59 5.55L12.98 6.49L14.87 6.63L14.87 9.37L12.98 9.51L12.59 10.45L13.82 11.89L11.89 13.82L10.45 12.59L9.51 12.98L9.37 14.87L6.63 14.87L6.49 12.98L5.55 12.59L4.11 13.82L2.18 11.89L3.41 10.45L3.02 9.51L1.13 9.37L1.13 6.63L3.02 6.49L3.41 5.55L2.18 4.11L4.11 2.18L5.55 3.41L6.49 3.02Z"/><circle cx="8" cy="8" r="2.2"/>
106{{- else if eq . "shield"}}<path d="M8 1.75 13 3.5v4.25c0 3.1-2 5.4-5 6.5-3-1.1-5-3.4-5-6.5V3.5Z"/><path d="m5.9 7.75 1.6 1.6 2.85-3.1"/>
107{{- else if eq . "signout"}}<path d="M6.5 2.25H3.25a1 1 0 0 0-1 1v9.5a1 1 0 0 0 1 1H6.5"/><path d="M7.75 8h6M11.25 5.5 13.75 8l-2.5 2.5"/>
108{{- else if eq . "ellipsis"}}<circle cx="3.25" cy="8" r="1.1" fill="currentColor" stroke="none"/><circle cx="8" cy="8" r="1.1" fill="currentColor" stroke="none"/><circle cx="12.75" cy="8" r="1.1" fill="currentColor" stroke="none"/>
109{{- else if eq . "snippet"}}<path d="M3.25 2.75h6L12.75 6v7.25a.5.5 0 0 1-.5.5H3.75a.5.5 0 0 1-.5-.5Z"/><path d="M9 2.75V6h3.75"/><path d="m6.75 8.75-1.5 1.5 1.5 1.5M9.75 8.75l1.5 1.5-1.5 1.5"/>
110{{- else if eq . "person"}}<circle cx="8" cy="5.5" r="2.75"/><path d="M2.75 14a5.25 5.25 0 0 1 10.5 0"/>
111{{- else if eq . "folder"}}<path d="M1.75 3.25h4l1.5 1.75h6.5v7.5a.5.5 0 0 1-.5.5H2.25a.5.5 0 0 1-.5-.5Z"/>
112{{- else if eq . "file"}}<path d="M3.25 2.75h6L12.75 6v7.25a.5.5 0 0 1-.5.5H3.75a.5.5 0 0 1-.5-.5Z"/><path d="M9 2.75V6h3.75"/>
113{{- end}}</svg>{{end}}
114
115{{/* raillink draws one square in the rail: the icon, the name for a
116 screen reader and in the tooltip, and the bell's unread badge. */}}
117{{define "raillink"}}<a class="railicon" {{if .Current}}aria-current="page" {{end}}href="{{.Href}}" aria-label="{{.Name}}" title="{{.Name}}">{{template "icon" .Icon}}<span class="vh">{{.Name}}</span>{{with .Count}}<b class="count">{{.}}</b>{{end}}</a>{{end}}
118
119{{define "mark"}}<svg class="mark" width="19" height="19" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2.25 18.75 12H5.25z" fill="#ff6b3d"/><rect x="3" y="13.5" width="18" height="3" fill="currentColor"/><rect x="7.5" y="18" width="9" height="3" fill="currentColor"/></svg>{{end}}
120{{define "width"}}reading{{end}}
121
122{{define "reporow"}}<li>
123 <p class="reponame"><a href="/{{.OwnerName}}/{{.Name}}">{{.OwnerName}}<span class="sep">/</span><strong>{{.Name}}</strong></a>{{if eq .Visibility "private"}} <span class="chip">Private</span>{{end}}{{if .Archived}} <span class="chip">Archived</span>{{end}}</p>
124 {{if .Desc}}<p class="desc">{{.Desc}}</p>{{end}}
125 {{if .Topics}}<p class="topics">{{range .Topics}}<a class="chip topic" href="/explore?q={{.}}">{{.}}</a> {{end}}</p>{{end}}
126 <p class="meta">{{template "branchicon"}} {{.DefaultBranch}}{{if .License}} · {{.License}}{{end}}{{if .Updated}} · updated {{.Updated}}{{end}}</p>
127</li>{{end}}
128
129{{define "refmenu"}}{{if .Branches}}<details class="refmenu">
130 <summary class="refchip">{{template "branchicon"}} {{.Ref}}</summary>
131 <div class="refdrop">
132 {{range .Branches}}<a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/{{$.RefKind}}/{{.Name}}/{{$.DirPath}}">{{.Name}}</a>
133 {{end}}<a class="allrefs" href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/refs">All refs →</a>
134 </div>
135</details>{{else}}<span class="refchip">{{template "branchicon"}} {{.Ref}}</span>{{end}}{{end}}
136
137{{define "filenav"}}<nav class="filenav" aria-label="Files">
138 <h2 class="colhead">{{.Title}}</h2>
139 <ul>
140 {{with .Parent}}<li><a class="up" href="{{.}}">..</a></li>{{end}}
141 {{range .Entries}}<li><a{{if .Dir}} class="dir"{{end}}{{if .Current}} aria-current="page"{{end}} href="{{.URL}}">{{.Name}}</a></li>
142 {{end}}</ul>
143</nav>{{end}}
144
145{{/* Every side column's groups sit in a details.sidedrop. Below 62rem
146 that disclosure is what the reader sees of the column: one closed
147 line they open. Above it style.css hides the summary and shows the
148 content whatever the open state, so the column reads as it always
149 has (#237). The facet columns name the filters in force in the
150 summary; the section navs head with the word alone. */}}
151{{define "sidecol"}}<nav class="sidecol" aria-label="Filters">
152<details class="sidedrop">
153<summary><span class="sideword">Filters</span>{{range .}}{{range .Items}}{{if .Active}} <span class="sideon">{{.Label}}</span>{{end}}{{end}}{{end}}</summary>
154 {{range .}}{{if .Items}}<div class="grp">
155 <h2 class="colhead">{{.Title}}</h2>
156 <ul>{{range .Items}}<li><a{{if .Active}} aria-current="page"{{end}} href="{{.Href}}">{{.Label}}{{if .Count}} <i>{{.Count}}</i>{{end}}</a></li>{{end}}</ul>
157 </div>{{end}}{{end}}
158</details>
159</nav>{{end}}
160
161{{define "branchicon"}}<svg class="icon" width="12" height="12" viewBox="0 0 16 16" aria-hidden="true" fill="currentColor"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628a2.25 2.25 0 0 1-1.5-2.122ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM3.5 3.25a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"/></svg>{{end}}
162
163{{define "sigbadge"}}<span class="badge badge-{{.State}}" title="{{.Fingerprint}}">{{sigLabel .State}}{{if .Signer}} · {{.Signer}}{{end}}</span>{{end}}
164
165{{define "authorname"}}{{if .User}}<a class="authorlink" href="/{{.User}}" title="{{.Email}}">{{.Name}}</a>{{else}}<span title="{{.Email}}">{{.Name}}</span>{{end}}{{end}}
166
167{{/* formatpicker is the md/org choice on a body: issue and MR create.
168 The argument is the currently selected format; empty selects
169 Markdown, today's default. */}}
170{{define "formatpicker"}}<p class="branchpick">
171 <label for="format">Body markup</label>
172 <select id="format" name="format">
173 <option value="md"{{if ne . "org"}} selected{{end}}>Markdown</option>
174 <option value="org"{{if eq . "org"}} selected{{end}}>Org</option>
175 </select>
176</p>{{end}}
177
178{{/* previewbtn is the Preview submit beside a markup form's own submit.
179 It posts the form to its usual action, which renders the body and
180 hands the page back instead of writing (#235). */}}
181{{define "previewbtn"}}<button type="submit" name="preview" value="1" class="btn">Preview</button>{{end}}
182
183{{/* previewblock shows a draft as it will read. The argument is the
184 rendered HTML; it sits above the textarea it came from. */}}
185{{define "previewblock"}}<div class="preview">
186 <p class="previewmark">Preview</p>
187 <div class="rendered">{{.}}</div>
188</div>{{end}}
189
190{{/* confirmfield is the typed-name check beside a destructive control.
191 The argument is the text the person must type. */}}
192{{define "confirmfield"}}<input type="text" name="confirm" aria-label="Type {{.}} to confirm" placeholder="type {{.}} to confirm" size="{{len .}}" autocomplete="off">{{end}}
193
194{{/* difffiles renders a parsed diff: one foldable section per file, with
195 line-number gutters and review threads inline. Base is the MR's
196 endpoint and Viewer the signed-in account; the commit page passes
197 neither and gets the same diff without review controls. */}}
198{{define "difffiles"}}{{$base := .Base}}{{$viewer := .Viewer}}
199{{range $fi, $f := .Files}}<details class="difffold" id="f{{$fi}}"{{if .Open}} open{{end}}>
200 <summary>
201 <span class="fpath">{{if eq .Status "renamed"}}<span class="was">{{.OldPath}} →</span> {{end}}{{.Path}}</span>
202 {{if ne .Status "modified"}}<span class="chip">{{.Status}}</span>{{end}}
203 <span class="fstat">{{if .Adds}}<span class="add">+{{.Adds}}</span>{{end}}{{if .Dels}} <span class="del">−{{.Dels}}</span>{{end}}</span>
204 </summary>
205 {{if .Binary}}<p class="none">Binary file not shown.</p>
206 {{else}}<div class="tablewrap"><table class="difftable">
207 {{range .Lines}}{{if eq .Class "hunk"}}<tr class="hunk"><td class="ln" colspan="2"></td><td class="src">{{.Text}}</td></tr>
208 {{else if eq .Class "meta"}}<tr class="dmeta"><td class="ln" colspan="2"></td><td class="src">{{.Text}}</td></tr>
209 {{else}}<tr class="{{.Class}}" id="f{{$fi}}-{{if eq .Class "del"}}o{{.OldLine}}{{else}}n{{.NewLine}}{{end}}"><td class="ln">{{if .OldLine}}{{if eq .Class "del"}}{{template "cmtln" dict "N" .OldLine "Path" .Path "Side" "old" "Base" $base "Viewer" $viewer}}{{else}}{{.OldLine}}{{end}}{{end}}</td><td class="ln">{{if .NewLine}}{{template "cmtln" dict "N" .NewLine "Path" .Path "Side" "new" "Base" $base "Viewer" $viewer}}{{end}}</td><td class="src chroma">{{if .Code}}{{.Code}}{{else}}{{.Content}}{{end}}</td></tr>
210 {{if .Compose}}<tr class="threadrow"><td colspan="3"><form id="compose" method="post" action="{{$base}}/diff-comment" class="thread composing">
211 <input type="hidden" name="path" value="{{.Path}}">
212 <input type="hidden" name="line" value="{{if eq .Class "del"}}{{.OldLine}}{{else}}{{.NewLine}}{{end}}">
213 <input type="hidden" name="side" value="{{if eq .Class "del"}}old{{else}}new{{end}}">
214 <p><textarea name="body" aria-label="Comment on {{.Path}}" rows="3" placeholder="Comment on this line" autofocus></textarea></p>
215 <p><button type="submit" class="btn">Comment</button>
216 <button type="submit" name="pending" value="on" class="btn">Add to review</button>
217 <a href="{{$base}}?view=diff">Cancel</a></p>
218 </form></td></tr>
219 {{end}}{{end}}{{range .Threads}}<tr class="threadrow"><td colspan="3">{{template "thread" dict "T" . "Base" $base "Viewer" $viewer "Class" ""}}</td></tr>
220 {{end}}{{end}}
221 </table></div>{{end}}
222</details>
223{{end}}{{end}}
224
225{{/* cmtln turns a line number into the link that opens the comment form
226 on that line. No JavaScript: the anchor travels in the query. */}}
227{{define "cmtln"}}{{if and .Viewer .Base}}<a class="cmt" aria-label="Comment on line {{.N}}" title="Comment on this line" href="{{.Base}}?view=diff&cpath={{.Path}}&cline={{.N}}&cside={{.Side}}#compose">{{.N}}</a>{{else}}{{.N}}{{end}}{{end}}
228
229{{/* thread renders one review thread with its reply and resolve controls.
230 Class carries "stale" for threads whose anchor is gone. */}}
231{{define "thread"}}{{$t := .T}}<div class="thread{{if $t.Resolved}} resolved{{end}}{{if $t.Pending}} pending{{end}}{{if .Class}} {{.Class}}{{end}}" id="thread-{{$t.ID}}">
232{{if $t.Pending}}<p class="threadstate">pending — only you can see this until you submit your review</p>{{end}}
233{{if or $t.Resolved (and .Class $t.Stale)}}<p class="threadstate">{{if and .Class $t.Stale}}stale{{end}}{{if $t.Resolved}}{{if and .Class $t.Stale}} · {{end}}resolved by {{$t.Resolved}}{{end}}</p>{{end}}
234{{range $t.Comments}}<p class="commenthead"><strong>{{.Author}}</strong> <span class="when">{{when .CreatedAt}}</span></p><div class="rendered">{{.BodyHTML}}</div>{{end}}
235{{if .Viewer}}<details class="threadreply"><summary>Reply</summary>
236<form method="post" action="{{.Base}}/diff-comment">
237 <input type="hidden" name="reply" value="{{$t.ID}}">
238 <p><textarea name="body" aria-label="Reply to thread {{$t.ID}}" rows="2" placeholder="Reply as {{.Viewer}}"></textarea></p>
239 <p><button type="submit" class="btn">Reply</button></p>
240</form></details>{{end}}
241{{if $t.CanResolve}}<form method="post" action="{{.Base}}/thread" class="threadact"><input type="hidden" name="thread" value="{{$t.ID}}"><button type="submit" name="action" value="{{if $t.Resolved}}unresolve{{else}}resolve{{end}}" class="linklike">{{if $t.Resolved}}Reopen thread{{else}}Resolve thread{{end}}</button></form>{{end}}
242</div>{{end}}