1{{ define "title" }}
2 {{ .Pull.Title }} · pull #{{ .Pull.PullId }} · {{ .RepoInfo.FullName }}
3{{ end }}
4
5{{ define "repoContent" }}
6 <header class="pb-4">
7 <h1 class="text-2xl">
8 {{ .Pull.Title }}
9 <span class="text-gray-500">#{{ .Pull.PullId }}</span>
10 </h1>
11 </header>
12
13 {{ $bgColor := "bg-gray-800" }}
14 {{ $icon := "ban" }}
15
16 {{ if .Pull.State.IsOpen }}
17 {{ $bgColor = "bg-green-600" }}
18 {{ $icon = "git-pull-request" }}
19 {{ else if .Pull.State.IsMerged }}
20 {{ $bgColor = "bg-purple-600" }}
21 {{ $icon = "git-merge" }}
22 {{ end }}
23
24 <section>
25 <div class="flex items-center gap-2">
26 <div
27 id="state"
28 class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
29 >
30 <i
31 data-lucide="{{ $icon }}"
32 class="w-4 h-4 mr-1.5 text-white"
33 ></i>
34 <span class="text-white">{{ .Pull.State.String }}</span>
35 </div>
36 <span class="text-gray-500 text-sm">
37 opened by
38 {{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
39 <a href="/{{ $owner }}" class="no-underline hover:underline"
40 >{{ $owner }}</a
41 >
42 <span class="select-none before:content-['\00B7']"></span>
43 <time>{{ .Pull.Created | timeFmt }}</time>
44 <span class="select-none before:content-['\00B7']"></span>
45 <span>targeting branch
46 <span class="text-xs rounded bg-gray-100 text-black font-mono px-2 mx-1/2 inline-flex items-center">
47 {{ .Pull.TargetBranch }}
48 </span>
49 </span>
50 </span>
51 </div>
52
53 {{ if .Pull.Body }}
54 <article id="body" class="mt-2 prose">
55 {{ .Pull.Body | markdown }}
56 </article>
57 {{ end }}
58 </section>
59
60{{ end }}
61
62{{ define "repoAfter" }}
63 <section id="submissions" class="mt-4">
64 <div class="flex flex-col gap-4">
65 {{ block "submissions" . }} {{ end }}
66 </div>
67 </section>
68
69 {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }}
70 {{ $isPushAllowed := .RepoInfo.Roles.IsPushAllowed }}
71
72 {{ if and $isPullAuthor (not .Pull.State.IsMerged) }}
73 <section id="update-card" class="mt-8 space-y-4 relative">
74 {{ block "resubmitCard" . }} {{ end }}
75 </section>
76 {{ end }}
77
78 <section id="merge-card" class="mt-8 space-y-4 relative">
79 {{ if .Pull.State.IsMerged }}
80 {{ block "alreadyMergedCard" . }} {{ end }}
81 {{ else if .MergeCheck }}
82 {{ if .MergeCheck.IsConflicted }}
83 {{ block "isConflictedCard" $ }} {{ end }}
84 {{ else }}
85 {{ block "noConflictsCard" $ }} {{ end }}
86 {{ end }}
87 {{ end }}
88 </section>
89
90 <div id="pull-close"></div>
91 <div id="pull-reopen"></div>
92{{ end }}
93
94{{ define "submissions" }}
95 {{ $lastIdx := sub (len .Pull.Submissions) 1 }}
96 {{ $targetBranch := .Pull.TargetBranch }}
97 {{ $repoName := .RepoInfo.FullName }}
98 {{ range $idx, $item := .Pull.Submissions }}
99 {{ $diff := $item.AsNiceDiff $targetBranch }}
100 {{ with $item }}
101 {{ $oneIndexedRound := add .RoundNumber 1 }}
102 <details {{ if eq $idx $lastIdx }}open{{ end }}>
103 <summary id="round-#{{ $oneIndexedRound }}" class="list-none cursor-pointer text-sm">
104 <div class="flex gap-2 items-center">
105 <div class="rounded bg-white drop-shadow-sm p-3">
106 #{{ $oneIndexedRound }}
107 </div>
108 <div class="rounded drop-shadow-sm bg-white p-3 text-gray-500">
109 <span>
110 {{ $owner := index $.DidHandleMap $.Pull.OwnerDid }}
111 submitted by <a href="/{{ $owner }}">{{ $owner }}</a>
112 <span class="select-none before:content-['\00B7']"></span>
113 <a href="#round-#{{ $oneIndexedRound }}"><time>{{ .Created | timeFmt }}</time></a>
114 <span class="select-none before:content-['·']"></span>
115 {{ $s := "s" }}
116 {{ if eq (len .Comments) 1 }}
117 {{ $s = "" }}
118 {{ end }}
119 {{ len .Comments }} comment{{$s}}
120 <span class="before:content-['·']"></span>
121 <a href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}">view patch</a>
122 </span>
123 </div>
124 </div>
125 </summary>
126 <div class="pl-12 flex flex-col gap-2 mt-2 relative">
127 {{ range .Comments }}
128 <div id="comment-{{.ID}}" class="bg-white rounded drop-shadow-sm py-2 px-4 relative w-fit">
129 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
130 <div class="text-sm text-gray-500">
131 {{ $owner := index $.DidHandleMap .OwnerDid }}
132 <a href="/{{$owner}}">{{$owner}}</a>
133 <span class="before:content-['·']"></span>
134 <a href="#comment-{{.ID}}"><time>{{ .Created | timeFmt }}</time></a>
135 </div>
136 <div class="prose">
137 {{ .Body }}
138 </div>
139 </div>
140 {{ end }}
141 {{ block "newComment" (list $ .ID) }} {{ end }}
142 </div>
143 </details>
144 <hr />
145 {{ end }}
146 {{ end }}
147{{ end }}
148
149{{ define "newComment" }}
150 {{ $rootObj := index . 0 }}
151 {{ $submissionId := index . 1 }}
152
153 {{ with $rootObj }}
154 {{ if .LoggedInUser }}
155 <div class="bg-white rounded drop-shadow-sm py-2 px-4 relative w-full md:w-96">
156 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
157 <div class="text-sm text-gray-500">
158 {{ index .DidHandleMap .LoggedInUser.Did }}
159 </div>
160 <form
161 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/comment"
162 hx-swap="none">
163 <input type="hidden" name="submissionId" value="{{ $submissionId }}">
164 <textarea
165 name="body"
166 class="w-full border-0 h-8 focus:outline-none focus:ring-0 px-0 py-1"
167 placeholder="Add to the discussion..." /></textarea>
168 <div class="flex justify-end">
169 <button type="submit" class="btn text-sm mt-2">comment</button>
170 </div>
171 <div id="pull-comment"></div>
172 </form>
173 {{ else }}
174 <div class="bg-white rounded drop-shadow-sm px-6 py-4 mt-8">
175 <a href="/login" class="underline">login</a> to join the discussion
176 </div>
177 </div>
178 {{ end }}
179 {{ end }}
180{{ end }}
181
182{{ define "alreadyMergedCard" }}
183 <div
184 id="merge-status-card"
185 class="rounded relative bg-purple-50 border border-purple-200 p-4">
186
187 <div class="flex items-center gap-2 text-purple-500">
188 <i data-lucide="git-merge" class="w-4 h-4"></i>
189 <span class="font-medium"
190 >pull request successfully merged</span
191 >
192 </div>
193
194 <div class="mt-2 text-sm text-gray-700">
195 <p>This pull request has been merged into the base branch.</p>
196 </div>
197 </div>
198{{ end }}
199
200{{ define "isConflictedCard" }}
201 <div
202 id="merge-status-card"
203 class="rounded relative border bg-red-50 border-red-200 p-4">
204
205 <div class="flex items-center gap-2 text-red-500">
206 <i data-lucide="alert-triangle" class="w-4 h-4"></i>
207 <span class="font-medium">merge conflicts detected</span>
208 </div>
209
210 <div class="mt-2">
211 <ul class="text-sm space-y-1">
212 {{ range .MergeCheck.Conflicts }}
213 <li class="flex items-center">
214 <i
215 data-lucide="file-warning"
216 class="w-3 h-3 mr-1.5 text-red-500"
217 ></i>
218 <span class="font-mono"
219 >{{ slice .Filename 0 (sub (len .Filename) 2) }}</span
220 >
221 </li>
222 {{ end }}
223 </ul>
224 </div>
225 <div class="mt-3 text-sm text-gray-700">
226 <p>
227 Please resolve these conflicts locally and update
228 the patch to continue with the merge.
229 </p>
230 </div>
231 </div>
232{{ end }}
233
234
235{{ define "noConflictsCard" }}
236 {{ $isPushAllowed := .RepoInfo.Roles.IsPushAllowed }}
237 {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }}
238 <div
239 id="merge-status-card"
240 class="rounded relative border bg-green-50 border-green-200 p-4">
241
242 <div class="flex items-center gap-2 text-green-500">
243 <i data-lucide="check-circle" class="w-4 h-4"></i>
244 <span class="font-medium">ready to merge</span>
245 </div>
246
247 <div class="mt-2 text-sm text-gray-700">
248 No conflicts detected with the base branch. This
249 pull request can be merged safely.
250 </div>
251
252 <div class="flex items-center gap-2">
253 {{ if $isPushAllowed }}
254 <button
255 class="btn mt-4 flex items-center gap-2"
256 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
257 hx-swap="none"
258 {{ if or .Pull.State.IsClosed .MergeCheck.IsConflicted }}
259 disabled
260 {{ end }}>
261 <i data-lucide="git-merge" class="w-4 h-4"></i>
262 <span>merge</span>
263 </button>
264 {{ end }}
265
266 {{ if and (or $isPullAuthor $isPushAllowed) (not .Pull.State.IsMerged) }}
267 {{ $action := "close" }}
268 {{ $icon := "circle-x" }}
269 {{ $hoverColor := "red" }}
270 {{ if .Pull.State.IsClosed }}
271 {{ $action = "reopen" }}
272 {{ $icon = "circle-dot" }}
273 {{ $hoverColor = "green" }}
274 {{ end }}
275 <button
276 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ $action }}"
277 hx-swap="none"
278 class="btn mt-4 flex items-center gap-2">
279 <i data-lucide="{{ $icon }}" class="w-4 h-4 text-{{ $hoverColor }}-400"></i>
280 <span class="text-black">{{ $action }}</span>
281 </button>
282 {{ end }}
283
284 <div id="pull-merge-error" class="error"></div>
285 <div id="pull-merge-success" class="success"></div>
286 </div>
287 </div>
288{{ end }}
289
290{{ define "resubmitCard" }}
291 <div
292 id="resubmit-pull-card"
293 class="rounded relative border bg-amber-50 border-amber-200 p-4">
294
295 <div class="flex items-center gap-2 text-amber-500">
296 <i data-lucide="edit" class="w-4 h-4"></i>
297 <span class="font-medium">resubmit your patch</span>
298 </div>
299
300 <div class="mt-2 text-sm text-gray-700">
301 You can update this patch to address any reviews.
302 This will begin a new round of reviews,
303 but you'll still be able to view your previous submissions and feedback.
304 </div>
305
306 <div class="mt-4 flex flex-col">
307 <form hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit" class="w-full" hx-swap="none">
308 <textarea
309 name="patch"
310 class="w-full p-2 mb-2 rounded border border-gray-200"
311 placeholder="Paste your updated patch here."
312 ></textarea>
313 <button
314 type="submit"
315 class="btn flex items-center gap-2"
316 {{ if or .Pull.State.IsClosed }}
317 disabled
318 {{ end }}>
319 <i data-lucide="refresh-ccw" class="w-4 h-4"></i>
320 <span>resubmit</span>
321 </button>
322 </form>
323
324 <div id="resubmit-error" class="error"></div>
325 <div id="resubmit-success" class="success"></div>
326 </div>
327 </div>
328{{ end }}