this repo has no description
1{{ define "title" }}{{ .Issue.Title }} · issue #{{ .Issue.IssueId }} · {{ .RepoInfo.FullName }}{{ end }}
2
3
4{{ define "extrameta" }}
5 {{ $title := printf "%s · issue #%d · %s" .Issue.Title .Issue.IssueId .RepoInfo.FullName }}
6 {{ $url := printf "https://tangled.sh/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }}
7
8 {{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
9{{ end }}
10
11{{ define "repoContent" }}
12 <header class="pb-4">
13 <h1 class="text-2xl">
14 {{ .Issue.Title }}
15 <span class="text-gray-500 dark:text-gray-400">#{{ .Issue.IssueId }}</span>
16 </h1>
17 </header>
18
19 {{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
20 {{ $icon := "ban" }}
21 {{ if eq .State "open" }}
22 {{ $bgColor = "bg-green-600 dark:bg-green-700" }}
23 {{ $icon = "circle-dot" }}
24 {{ end }}
25
26 <section class="mt-2">
27 <div class="inline-flex items-center gap-2">
28 <div id="state"
29 class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
30 {{ i $icon "w-4 h-4 mr-1.5 text-white" }}
31 <span class="text-white">{{ .State }}</span>
32 </div>
33 <span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
34 opened by
35 {{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
36 {{ template "user/fragments/picHandle" $owner }}
37 <span class="select-none before:content-['\00B7']"></span>
38 <time title="{{ .Issue.Created | longTimeFmt }}">
39 {{ .Issue.Created | timeFmt }}
40 </time>
41 </span>
42 </div>
43
44 {{ if .Issue.Body }}
45 <article id="body" class="mt-8 prose dark:prose-invert">
46 {{ .Issue.Body | markdown }}
47 </article>
48 {{ end }}
49
50 <div class="flex items-center gap-2 mt-2">
51 {{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }}
52 {{ range $kind := .OrderedReactionKinds }}
53 {{
54 template "repo/fragments/reaction"
55 (dict
56 "Kind" $kind
57 "Count" (index $.Reactions $kind)
58 "IsReacted" (index $.UserReacted $kind)
59 "ThreadAt" $.Issue.IssueAt)
60 }}
61 {{ end }}
62 </div>
63 </section>
64{{ end }}
65
66{{ define "repoAfter" }}
67 <section id="comments" class="my-2 mt-2 space-y-2 relative">
68 {{ range $index, $comment := .Comments }}
69 <div
70 id="comment-{{ .CommentId }}"
71 class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-2 px-4 relative w-full md:max-w-3/5 md:w-fit">
72 {{ if gt $index 0 }}
73 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
74 {{ end }}
75 {{ template "repo/issues/fragments/issueComment" (dict "RepoInfo" $.RepoInfo "LoggedInUser" $.LoggedInUser "DidHandleMap" $.DidHandleMap "Issue" $.Issue "Comment" .)}}
76 </div>
77 {{ end }}
78 </section>
79
80 {{ block "newComment" . }} {{ end }}
81
82{{ end }}
83
84{{ define "newComment" }}
85 {{ if .LoggedInUser }}
86 <form
87 id="comment-form"
88 hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
89 hx-on::after-request="if(event.detail.successful) this.reset()"
90 >
91 <div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full md:w-3/5">
92 <div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
93 {{ didOrHandle .LoggedInUser.Did .LoggedInUser.Handle }}
94 </div>
95 <textarea
96 id="comment-textarea"
97 name="body"
98 class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
99 placeholder="Add to the discussion. Markdown is supported."
100 onkeyup="updateCommentForm()"
101 ></textarea>
102 <div id="issue-comment"></div>
103 <div id="issue-action" class="error"></div>
104 </div>
105
106 <div class="flex gap-2 mt-2">
107 <button
108 id="comment-button"
109 hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
110 type="submit"
111 hx-disabled-elt="#comment-button"
112 class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group"
113 disabled
114 >
115 {{ i "message-square-plus" "w-4 h-4" }}
116 comment
117 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
118 </button>
119
120 {{ $isIssueAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Issue.OwnerDid) }}
121 {{ $isRepoCollaborator := .RepoInfo.Roles.IsCollaborator }}
122 {{ $isRepoOwner := .RepoInfo.Roles.IsOwner }}
123 {{ if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "open") }}
124 <button
125 id="close-button"
126 type="button"
127 class="btn flex items-center gap-2"
128 hx-indicator="#close-spinner"
129 hx-trigger="click"
130 >
131 {{ i "ban" "w-4 h-4" }}
132 close
133 <span id="close-spinner" class="group">
134 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
135 </span>
136 </button>
137 <div
138 id="close-with-comment"
139 hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
140 hx-trigger="click from:#close-button"
141 hx-disabled-elt="#close-with-comment"
142 hx-target="#issue-comment"
143 hx-indicator="#close-spinner"
144 hx-vals="js:{body: document.getElementById('comment-textarea').value.trim() !== '' ? document.getElementById('comment-textarea').value : ''}"
145 hx-swap="none"
146 >
147 </div>
148 <div
149 id="close-issue"
150 hx-disabled-elt="#close-issue"
151 hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/close"
152 hx-trigger="click from:#close-button"
153 hx-target="#issue-action"
154 hx-indicator="#close-spinner"
155 hx-swap="none"
156 >
157 </div>
158 <script>
159 document.addEventListener('htmx:configRequest', function(evt) {
160 if (evt.target.id === 'close-with-comment') {
161 const commentText = document.getElementById('comment-textarea').value.trim();
162 if (commentText === '') {
163 evt.detail.parameters = {};
164 evt.preventDefault();
165 }
166 }
167 });
168 </script>
169 {{ else if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "closed") }}
170 <button
171 type="button"
172 class="btn flex items-center gap-2"
173 hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/reopen"
174 hx-indicator="#reopen-spinner"
175 hx-swap="none"
176 >
177 {{ i "refresh-ccw-dot" "w-4 h-4" }}
178 reopen
179 <span id="reopen-spinner" class="group">
180 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
181 </span>
182 </button>
183 {{ end }}
184
185 <script>
186 function updateCommentForm() {
187 const textarea = document.getElementById('comment-textarea');
188 const commentButton = document.getElementById('comment-button');
189 const closeButton = document.getElementById('close-button');
190
191 if (textarea.value.trim() !== '') {
192 commentButton.removeAttribute('disabled');
193 } else {
194 commentButton.setAttribute('disabled', '');
195 }
196
197 if (closeButton) {
198 if (textarea.value.trim() !== '') {
199 closeButton.innerHTML = `
200{{ i "ban" "w-4 h-4" }}
201<span>close with comment</span>
202<span id="close-spinner" class="group">
203 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
204</span>`;
205 } else {
206 closeButton.innerHTML = `
207{{ i "ban" "w-4 h-4" }}
208<span>close</span>
209<span id="close-spinner" class="group">
210 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
211</span>`;
212 }
213 }
214 }
215
216 document.addEventListener('DOMContentLoaded', function() {
217 updateCommentForm();
218 });
219 </script>
220 </div>
221 </form>
222 {{ else }}
223 <div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-fit">
224 <a href="/login" class="underline">login</a> to join the discussion
225 </div>
226 {{ end }}
227{{ end }}