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