A vibe coded tangled fork which supports pijul.
1{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }}
2
3{{ define "extrameta" }}
4 <meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
5 <meta property="og:type" content="profile" />
6 <meta
7 property="og:url"
8 content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
9 <meta
10 property="og:description"
11 content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
12{{ end }}
13
14{{ define "content" }}
15 <div class="grid grid-cols-1 md:grid-cols-11 gap-4">
16 <div class="md:col-span-3 order-1 md:order-1">
17 <div class="grid grid-cols-1 gap-4">
18 {{ template "user/fragments/profileCard" .Card }}
19 {{ block "punchcard" .Punchcard }}{{ end }}
20 </div>
21 </div>
22 <div id="all-repos" class="md:col-span-4 order-2 md:order-2">
23 <div class="grid grid-cols-1 gap-4">
24 {{ block "ownRepos" . }}{{ end }}
25 {{ block "collaboratingRepos" . }}{{ end }}
26 </div>
27 </div>
28 <div class="md:col-span-4 order-3 md:order-3">
29 {{ block "profileTimeline" . }}{{ end }}
30 </div>
31 </div>
32{{ end }}
33
34{{ define "profileTimeline" }}
35 <p class="text-sm font-bold p-2 dark:text-white">ACTIVITY</p>
36 <div class="flex flex-col gap-4 relative">
37 {{ with .ProfileTimeline }}
38 {{ range $idx, $byMonth := .ByMonth }}
39 {{ with $byMonth }}
40 <div
41 class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm">
42 {{ if eq $idx 0 }}
43
44 {{ else }}
45 {{ $s := "s" }}
46 {{ if eq $idx 1 }}
47 {{ $s = "" }}
48 {{ end }}
49 <p class="text-sm font-bold dark:text-white mb-2">
50 {{ $idx }} month{{ $s }} ago
51 </p>
52 {{ end }}
53
54 {{ if .IsEmpty }}
55 <div class="text-gray-500 dark:text-gray-400">
56 No activity for this month
57 </div>
58 {{ else }}
59 <div class="flex flex-col gap-1">
60 {{ block "repoEvents" .RepoEvents }}{{ end }}
61 {{ block "issueEvents" .IssueEvents }}{{ end }}
62 {{ block "pullEvents" .PullEvents }}{{ end }}
63 </div>
64 {{ end }}
65 </div>
66 {{ end }}
67 {{ else }}
68 <p class="dark:text-white">This user does not have any activity yet.</p>
69 {{ end }}
70 {{ end }}
71 </div>
72{{ end }}
73
74{{ define "repoEvents" }}
75 {{ if gt (len .) 0 }}
76 <details>
77 <summary
78 class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
79 <div class="flex flex-wrap items-center gap-2">
80 {{ i "book-plus" "w-4 h-4" }}
81 created {{ len . }}
82 {{ if eq (len .) 1 }}repository{{ else }}repositories{{ end }}
83 </div>
84 </summary>
85 <div class="py-2 text-sm flex flex-col gap-3 mb-2">
86 {{ range . }}
87 <div class="flex flex-wrap items-center gap-2">
88 <span class="text-gray-500 dark:text-gray-400">
89 {{ if .Source }}
90 {{ i "git-fork" "w-4 h-4" }}
91 {{ else }}
92 {{ i "book-plus" "w-4 h-4" }}
93 {{ end }}
94 </span>
95 <a
96 href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}"
97 class="no-underline hover:underline">
98 {{- .Repo.Name -}}
99 </a>
100 </div>
101 {{ end }}
102 </div>
103 </details>
104 {{ end }}
105{{ end }}
106
107{{ define "issueEvents" }}
108 {{ $items := .Items }}
109 {{ $stats := .Stats }}
110
111 {{ if gt (len $items) 0 }}
112 <details>
113 <summary
114 class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
115 <div class="flex flex-wrap items-center gap-2">
116 {{ i "circle-dot" "w-4 h-4" }}
117
118
119 <div>
120 created {{ len $items }}
121 {{ if eq (len $items) 1 }}issue{{ else }}issues{{ end }}
122 </div>
123
124 {{ if gt $stats.Open 0 }}
125 <span
126 class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
127 {{ $stats.Open }} open
128 </span>
129 {{ end }}
130
131 {{ if gt $stats.Closed 0 }}
132 <span
133 class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
134 {{ $stats.Closed }} closed
135 </span>
136 {{ end }}
137
138 </div>
139 </summary>
140 <div class="py-2 text-sm flex flex-col gap-3 mb-2">
141 {{ range $items }}
142 {{ $repoOwner := resolve .Metadata.Repo.Did }}
143 {{ $repoName := .Metadata.Repo.Name }}
144 {{ $repoUrl := printf "%s/%s" $repoOwner $repoName }}
145
146
147 <div class="flex gap-2 text-gray-600 dark:text-gray-300">
148 {{ if .Open }}
149 <span class="text-green-600 dark:text-green-500">
150 {{ i "circle-dot" "w-4 h-4" }}
151 </span>
152 {{ else }}
153 <span class="text-gray-500 dark:text-gray-400">
154 {{ i "ban" "w-4 h-4" }}
155 </span>
156 {{ end }}
157 <div class="flex-none min-w-8 text-right">
158 <span class="text-gray-500 dark:text-gray-400">
159 #{{ .IssueId }}
160 </span>
161 </div>
162 <div class="break-words max-w-full">
163 <a
164 href="/{{ $repoUrl }}/issues/{{ .IssueId }}"
165 class="no-underline hover:underline">
166 {{ .Title -}}
167 </a>
168 on
169 <a
170 href="/{{ $repoUrl }}"
171 class="no-underline hover:underline whitespace-nowrap">
172 {{ $repoUrl }}
173 </a>
174 </div>
175 </div>
176 {{ end }}
177 </div>
178 </details>
179 {{ end }}
180{{ end }}
181
182{{ define "pullEvents" }}
183 {{ $items := .Items }}
184 {{ $stats := .Stats }}
185 {{ if gt (len $items) 0 }}
186 <details>
187 <summary
188 class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
189 <div class="flex flex-wrap items-center gap-2">
190 {{ i "git-pull-request" "w-4 h-4" }}
191
192
193 <div>
194 created {{ len $items }}
195 {{ if eq (len $items) 1 }}
196 pull request
197 {{ else }}
198 pull requests
199 {{ end }}
200 </div>
201
202 {{ if gt $stats.Open 0 }}
203 <span
204 class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
205 {{ $stats.Open }} open
206 </span>
207 {{ end }}
208
209 {{ if gt $stats.Merged 0 }}
210 <span
211 class="px-2 py-1/2 text-sm rounded text-white bg-purple-600 dark:bg-purple-700">
212 {{ $stats.Merged }} merged
213 </span>
214 {{ end }}
215
216 {{ if gt $stats.Closed 0 }}
217 <span
218 class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
219 {{ $stats.Closed }} closed
220 </span>
221 {{ end }}
222
223 </div>
224 </summary>
225 <div class="py-2 text-sm flex flex-col gap-3 mb-2">
226 {{ range $items }}
227 {{ $repoOwner := resolve .Repo.Did }}
228 {{ $repoName := .Repo.Name }}
229 {{ $repoUrl := printf "%s/%s" $repoOwner $repoName }}
230
231
232 <div class="flex gap-2 text-gray-600 dark:text-gray-300">
233 {{ if .State.IsOpen }}
234 <span class="text-green-600 dark:text-green-500">
235 {{ i "git-pull-request" "w-4 h-4" }}
236 </span>
237 {{ else if .State.IsMerged }}
238 <span class="text-purple-600 dark:text-purple-500">
239 {{ i "git-merge" "w-4 h-4" }}
240 </span>
241 {{ else }}
242 <span class="text-gray-600 dark:text-gray-300">
243 {{ i "git-pull-request-closed" "w-4 h-4" }}
244 </span>
245 {{ end }}
246 <div class="flex-none min-w-8 text-right">
247 <span class="text-gray-500 dark:text-gray-400">
248 #{{ .PullId }}
249 </span>
250 </div>
251 <div class="break-words max-w-full">
252 <a
253 href="/{{ $repoUrl }}/pulls/{{ .PullId }}"
254 class="no-underline hover:underline">
255 {{ .Title -}}
256 </a>
257 on
258 <a
259 href="/{{ $repoUrl }}"
260 class="no-underline hover:underline whitespace-nowrap">
261 {{ $repoUrl }}
262 </a>
263 </div>
264 </div>
265 {{ end }}
266 </div>
267 </details>
268 {{ end }}
269{{ end }}
270
271{{ define "ownRepos" }}
272 <div>
273 <div
274 class="text-sm font-bold p-2 pr-0 dark:text-white flex items-center justify-between gap-2">
275 <a
276 href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos"
277 class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group">
278 <span>PINNED REPOS</span>
279 <span
280 class="flex gap-1 items-center font-normal text-sm text-gray-500 dark:text-gray-400 ">
281 view all
282 {{ i "chevron-right" "w-4 h-4" }}
283 </span>
284 </a>
285 {{ if and .LoggedInUser (eq .LoggedInUser.Did .Card.UserDid) }}
286 <button
287 hx-get="profile/edit-pins"
288 hx-target="#all-repos"
289 class="btn py-0 font-normal text-sm flex gap-2 items-center group">
290 {{ i "pencil" "w-3 h-3" }}
291 edit
292 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
293 </button>
294 {{ end }}
295 </div>
296 <div id="repos" class="grid grid-cols-1 gap-4 items-stretch">
297 {{ range .Repos }}
298 {{ template "user/fragments/repoCard" (list $ . false) }}
299 {{ else }}
300 <p class="px-6 dark:text-white">
301 This user does not have any repos yet.
302 </p>
303 {{ end }}
304 </div>
305 </div>
306{{ end }}
307
308{{ define "collaboratingRepos" }}
309 {{ if gt (len .CollaboratingRepos) 0 }}
310 <div>
311 <p class="text-sm font-bold p-2 dark:text-white">COLLABORATING ON</p>
312 <div id="collaborating" class="grid grid-cols-1 gap-4">
313 {{ range .CollaboratingRepos }}
314 {{ template "user/fragments/repoCard" (list $ . true) }}
315 {{ else }}
316 <p class="px-6 dark:text-white">This user is not collaborating.</p>
317 {{ end }}
318 </div>
319 </div>
320 {{ end }}
321{{ end }}
322
323{{ define "punchcard" }}
324 {{ $now := now }}
325 <div>
326 <p class="p-2 flex gap-2 text-sm font-bold dark:text-white">
327 PUNCHCARD
328 <span class="font-normal text-sm text-gray-500 dark:text-gray-400 ">
329 {{ .Total | int64 | commaFmt }} commits
330 </span>
331 </p>
332 <div class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm">
333 <div class="grid grid-cols-28 md:grid-cols-14 gap-y-2 w-full h-full">
334 {{ range .Punches }}
335 {{ $count := .Count }}
336 {{ $theme := "bg-gray-200 dark:bg-gray-700 size-[4px]" }}
337 {{ if lt $count 1 }}
338 {{ $theme = "bg-gray-200 dark:bg-gray-700 size-[4px]" }}
339 {{ else if lt $count 2 }}
340 {{ $theme = "bg-green-200 dark:bg-green-900 size-[5px]" }}
341 {{ else if lt $count 4 }}
342 {{ $theme = "bg-green-300 dark:bg-green-800 size-[5px]" }}
343 {{ else if lt $count 8 }}
344 {{ $theme = "bg-green-400 dark:bg-green-700 size-[6px]" }}
345 {{ else }}
346 {{ $theme = "bg-green-500 dark:bg-green-600 size-[7px]" }}
347 {{ end }}
348
349 {{ if .Date.After $now }}
350 {{ $theme = "border border-gray-200 dark:border-gray-700 size-[4px]" }}
351 {{ end }}
352 <div class="w-full h-full flex justify-center items-center">
353 <div
354 class="aspect-square rounded-full transition-all duration-300 {{ $theme }} max-w-full max-h-full"
355 title="{{ .Date.Format "2006-01-02" }}: {{ .Count }} commits"></div>
356 </div>
357 {{ end }}
358 </div>
359 </div>
360 </div>
361{{ end }}