this repo has no description
1{{ define "title" }}
2 {{ .Pull.Title }} · pull #{{ .Pull.PullId }} ·
3 {{ .RepoInfo.FullName }}
4{{ end }}
5
6{{ define "repoContent" }}
7 <header class="pb-4">
8 <h1 class="text-2xl">
9 {{ .Pull.Title }}
10 <span class="text-gray-500">#{{ .Pull.PullId }}</span>
11 </h1>
12 </header>
13
14 {{ $bgColor := "bg-gray-800" }}
15 {{ $icon := "ban" }}
16
17 {{ if .Pull.State.IsOpen }}
18 {{ $bgColor = "bg-green-600" }}
19 {{ $icon = "git-pull-request" }}
20 {{ else if .Pull.State.IsMerged }}
21 {{ $bgColor = "bg-purple-600" }}
22 {{ $icon = "git-merge" }}
23 {{ end }}
24
25
26 <section>
27 <div class="flex items-center gap-2">
28 <div
29 id="state"
30 class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
31 >
32 <i
33 data-lucide="{{ $icon }}"
34 class="w-4 h-4 mr-1.5 text-white"
35 ></i>
36 <span class="text-white">{{ .Pull.State.String }}</span>
37 </div>
38 <span class="text-gray-500 text-sm">
39 opened by
40 {{ $owner := index $.DidHandleMap .Pull.OwnerDid }}
41 <a href="/{{ $owner }}" class="no-underline hover:underline"
42 >{{ $owner }}</a
43 >
44 <span class="select-none before:content-['\00B7']"></span>
45 <time>{{ .Pull.Created | timeFmt }}</time>
46 <span class="select-none before:content-['\00B7']"></span>
47 <time>targeting branch {{ .Pull.TargetBranch }}</time>
48 </span>
49 </div>
50
51 {{ if .Pull.Body }}
52 <article id="body" class="mt-8 prose">
53 {{ .Pull.Body | markdown }}
54 </article>
55 {{ end }}
56 </section>
57
58 <div class="flex flex-col justify-end mt-4">
59 <details>
60 <summary
61 class="list-none cursor-pointer sticky top-0 bg-white rounded-sm px-3 py-2 border border-gray-200 flex items-center text-gray-700 hover:bg-gray-50 transition-colors mt-auto"
62 >
63 <i data-lucide="code" class="w-4 h-4 mr-2"></i>
64 <span>patch</span>
65 </summary>
66 <div class="relative">
67 <pre
68 id="patch-preview"
69 class="font-mono overflow-x-scroll bg-gray-50 p-4 rounded-b border border-gray-200 text-sm"
70 >
71 {{- .Pull.Patch -}}
72 </pre
73 >
74 <form
75 id="patch-form"
76 hx-patch="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/patch"
77 hx-swap="none"
78 >
79 <textarea
80 id="patch"
81 name="patch"
82 class="font-mono w-full h-full p-4 rounded-b border border-gray-200 text-sm hidden"
83 >{{- .Pull.Patch -}}</textarea>
84
85 <div class="flex gap-2 justify-end mt-2">
86 <button
87 id="edit-patch-btn"
88 type="button"
89 class="btn btn-sm"
90 onclick="togglePatchEdit(true)"
91 {{ if or .Pull.State.IsMerged .Pull.State.IsClosed }}
92 disabled title="Cannot edit closed or merged
93 pull requests"
94 {{ end }}
95 >
96 <i data-lucide="edit" class="w-4 h-4 mr-1"></i>Edit
97 </button>
98 <button
99 id="save-patch-btn"
100 type="submit"
101 class="btn btn-sm bg-green-500 hidden"
102 >
103 <i data-lucide="save" class="w-4 h-4 mr-1"></i>Save
104 </button>
105 <button
106 id="cancel-patch-btn"
107 type="button"
108 class="btn btn-sm bg-gray-300 hidden"
109 onclick="togglePatchEdit(false)"
110 >
111 Cancel
112 </button>
113 </div>
114 </form>
115
116 <div id="pull-error" class="error"></div>
117 <div id="pull-success" class="success"></div>
118 </div>
119 <script>
120 function togglePatchEdit(editMode) {
121 const preview = document.getElementById("patch-preview");
122 const editor = document.getElementById("patch");
123 const editBtn = document.getElementById("edit-patch-btn");
124 const saveBtn = document.getElementById("save-patch-btn");
125 const cancelBtn =
126 document.getElementById("cancel-patch-btn");
127
128 if (editMode) {
129 preview.classList.add("hidden");
130 editor.classList.remove("hidden");
131 editBtn.classList.add("hidden");
132 saveBtn.classList.remove("hidden");
133 cancelBtn.classList.remove("hidden");
134 } else {
135 preview.classList.remove("hidden");
136 editor.classList.add("hidden");
137 editBtn.classList.remove("hidden");
138 saveBtn.classList.add("hidden");
139 cancelBtn.classList.add("hidden");
140 }
141 }
142
143 document
144 .getElementById("save-patch-btn")
145 .addEventListener("click", function () {
146 togglePatchEdit(false);
147 });
148 </script>
149 </details>
150 </div>
151{{ end }}
152
153{{ define "repoAfter" }}
154 {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }}
155 {{ $isRepoCollaborator := .RepoInfo.Roles.IsCollaborator }}
156
157 <section id="comments" class="mt-8 space-y-4 relative">
158 {{ block "comments" . }} {{ end }}
159
160 {{ if .Pull.State.IsMerged }}
161 {{ block "alreadyMergedCard" . }} {{ end }}
162 {{ else if .MergeCheck }}
163 {{ if .MergeCheck.IsConflicted }}
164 {{ block "isConflictedCard" . }} {{ end }}
165 {{ else }}
166 {{ block "noConflictsCard" . }} {{ end }}
167 {{ end }}
168 {{ end }}
169 </section>
170
171 {{ block "newComment" . }} {{ end }}
172
173 {{ if and (or $isPullAuthor $isRepoCollaborator) (not .Pull.State.IsMerged) }}
174 {{ $action := "close" }}
175 {{ $icon := "circle-x" }}
176 {{ $hoverColor := "red" }}
177 {{ if .Pull.State.IsClosed }}
178 {{ $action = "reopen" }}
179 {{ $icon = "circle-dot" }}
180 {{ $hoverColor = "green" }}
181 {{ end }}
182 <button
183 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/{{ $action }}"
184 hx-swap="none"
185 class="btn mt-8 text-sm flex items-center gap-2">
186 <i data-lucide="{{ $icon }}" class="w-4 h-4 mr-2 text-{{ $hoverColor }}-400"></i>
187 <span class="text-black">{{ $action }}</span>
188 </button>
189 {{ end }}
190
191 <div id="pull-close"></div>
192 <div id="pull-reopen"></div>
193{{ end }}
194
195{{ define "comments" }}
196 {{ range $index, $comment := .Comments }}
197 <div
198 id="comment-{{ .CommentId }}"
199 class="rounded bg-white p-4 relative drop-shadow-sm"
200 >
201 {{ if eq $index 0 }}
202 <div
203 class="absolute left-8 -top-8 w-px h-8 bg-gray-300"
204 ></div>
205 {{ else }}
206 <div
207 class="absolute left-8 -top-4 w-px h-4 bg-gray-300"
208 ></div>
209 {{ end }}
210 <div class="flex items-center gap-2 mb-2 text-gray-400">
211 {{ $owner := index $.DidHandleMap .OwnerDid }}
212 <span class="text-sm">
213 <a
214 href="/{{ $owner }}"
215 class="no-underline hover:underline"
216 >{{ $owner }}</a
217 >
218 </span>
219 <span
220 class="px-1 select-none before:content-['\00B7']"
221 ></span>
222 <a
223 href="#{{ .CommentId }}"
224 class="text-gray-500 text-sm hover:text-gray-500 hover:underline no-underline"
225 id="{{ .CommentId }}"
226 >
227 {{ .Created | timeFmt }}
228 </a>
229 </div>
230 <div class="prose">
231 {{ .Body | markdown }}
232 </div>
233 </div>
234 {{ end }}
235{{ end }}
236
237{{ define "newComment" }}
238 {{ if .LoggedInUser }}
239 <form
240 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/comment"
241 class="mt-8"
242 hx-swap="none">
243 <textarea
244 name="body"
245 class="w-full p-2 rounded border border-gray-200"
246 placeholder="Add to the discussion..."
247 ></textarea>
248 <button type="submit" class="btn mt-2">comment</button>
249 <div id="pull-comment"></div>
250 </form>
251 {{ else }}
252 <div class="bg-white rounded drop-shadow-sm px-6 py-4 mt-8">
253 <a href="/login" class="underline">login</a> to join the discussion
254 </div>
255 {{ end }}
256{{ end }}
257
258{{ define "alreadyMergedCard" }}
259 <div
260 id="merge-status-card"
261 class="rounded relative bg-purple-50 border border-purple-200 p-4">
262 {{ if gt (len .Comments) 0 }}
263 <div
264 class="absolute left-8 -top-4 w-px h-4 bg-gray-300"
265 ></div>
266 {{ else }}
267 <div
268 class="absolute left-8 -top-8 w-px h-8 bg-gray-300"
269 ></div>
270 {{ end }}
271
272
273 <div class="flex items-center gap-2 text-purple-500">
274 <i data-lucide="git-merge" class="w-4 h-4"></i>
275 <span class="font-medium"
276 >Pull request successfully merged</span
277 >
278 </div>
279
280 <div class="mt-2 text-sm text-gray-700">
281 <p>This pull request has been merged into the base branch.</p>
282 </div>
283 </div>
284{{ end }}
285
286{{ define "isConflictedCard" }}
287 <div
288 id="merge-status-card"
289 class="rounded relative border bg-red-50 border-red-200 p-4">
290 {{ if gt (len .Comments) 0 }}
291 <div class="absolute left-8 -top-4 w-px h-4 bg-gray-300"></div>
292 {{ else }}
293 <div class="absolute left-8 -top-8 w-px h-8 bg-gray-300"></div>
294 {{ end }}
295
296 <div class="flex items-center gap-2 text-red-500">
297 <i data-lucide="alert-triangle" class="w-4 h-4"></i>
298 <span class="font-medium">merge conflicts detected</span>
299 </div>
300
301 <div class="mt-2">
302 <ul class="text-sm space-y-1">
303 {{ range .MergeCheck.Conflicts }}
304 <li class="flex items-center">
305 <i
306 data-lucide="file-warning"
307 class="w-3 h-3 mr-1.5 text-red-500"
308 ></i>
309 <span class="font-mono"
310 >{{ slice .Filename 0 (sub (len .Filename) 2) }}</span
311 >
312 </li>
313 {{ end }}
314 </ul>
315 </div>
316 <div class="mt-3 text-sm text-gray-700">
317 <p>
318 Please resolve these conflicts locally and update
319 the patch to continue with the merge.
320 </p>
321 </div>
322 </div>
323{{ end }}
324
325
326{{ define "noConflictsCard" }}
327 {{ $isRepoCollaborator := .RepoInfo.Roles.IsCollaborator }}
328 <div
329 id="merge-status-card"
330 class="rounded relative border bg-green-50 border-green-200 p-4">
331 {{ if gt (len .Comments) 0 }}
332 <div class="absolute left-8 -top-4 w-px h-4 bg-gray-300"></div>
333 {{ else }}
334 <div class="absolute left-8 -top-8 w-px h-8 bg-gray-300"></div>
335 {{ end }}
336
337 <div class="flex items-center gap-2 text-green-500">
338 <i data-lucide="check-circle" class="w-4 h-4"></i>
339 <span class="font-medium">ready to merge</span>
340 </div>
341
342 <div class="mt-2 text-sm text-gray-700">
343 No conflicts detected with the base branch. This
344 pull request can be merged safely.
345 </div>
346
347 <div class="mt-4 flex items-center gap-2">
348 {{ if $isRepoCollaborator }}
349 <button
350 class="btn flex items-center gap-2"
351 hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
352 hx-swap="none"
353 {{ if or .Pull.State.IsClosed .MergeCheck.IsConflicted }}
354 disabled
355 {{ end }}>
356 <i data-lucide="git-merge" class="w-4 h-4 text-purple-500"></i>
357 <span>merge</span>
358 </button>
359 {{ end }}
360
361 <div id="pull-merge-error" class="error"></div>
362 <div id="pull-merge-success" class="success"></div>
363 </div>
364 </div>
365{{ end }}