+7
-20
appview/pages/funcmap.go
+7
-20
appview/pages/funcmap.go
···
334
},
335
"deref": func(v any) any {
336
val := reflect.ValueOf(v)
337
-
if val.Kind() == reflect.Pointer && !val.IsNil() {
338
return val.Elem().Interface()
339
}
340
return nil
···
366
return p.AvatarUrl(handle, "")
367
},
368
"langColor": enry.GetColor,
369
-
"reverse": func(s any) any {
370
-
if s == nil {
371
-
return nil
372
-
}
373
374
-
v := reflect.ValueOf(s)
375
-
376
-
if v.Kind() != reflect.Slice {
377
-
return s
378
-
}
379
-
380
-
length := v.Len()
381
-
reversed := reflect.MakeSlice(v.Type(), length, length)
382
-
383
-
for i := range length {
384
-
reversed.Index(i).Set(v.Index(length - 1 - i))
385
-
}
386
-
387
-
return reversed.Interface()
388
-
},
389
"normalizeForHtmlId": func(s string) string {
390
normalized := strings.ReplaceAll(s, ":", "_")
391
normalized = strings.ReplaceAll(normalized, ".", "_")
···
334
},
335
"deref": func(v any) any {
336
val := reflect.ValueOf(v)
337
+
if val.Kind() == reflect.Ptr && !val.IsNil() {
338
return val.Elem().Interface()
339
}
340
return nil
···
366
return p.AvatarUrl(handle, "")
367
},
368
"langColor": enry.GetColor,
369
+
"layoutSide": func() string {
370
+
return "col-span-1 md:col-span-2 lg:col-span-3"
371
+
},
372
+
"layoutCenter": func() string {
373
+
return "col-span-1 md:col-span-8 lg:col-span-6"
374
+
},
375
376
"normalizeForHtmlId": func(s string) string {
377
normalized := strings.ReplaceAll(s, ":", "_")
378
normalized = strings.ReplaceAll(normalized, ".", "_")
-2
appview/pages/pages.go
-2
appview/pages/pages.go
+1
-1
appview/pages/templates/layouts/repobase.html
+1
-1
appview/pages/templates/layouts/repobase.html
+22
-35
appview/pages/templates/repo/issues/fragments/commentList.html
+22
-35
appview/pages/templates/repo/issues/fragments/commentList.html
···
1
{{ define "repo/issues/fragments/commentList" }}
2
-
<div class="flex flex-col gap-4">
3
{{ range $item := .CommentList }}
4
{{ template "commentListing" (list $ .) }}
5
{{ end }}
···
19
<div class="rounded border border-gray-200 dark:border-gray-700 w-full overflow-hidden shadow-sm bg-gray-50 dark:bg-gray-800/50">
20
{{ template "topLevelComment" $params }}
21
22
-
<div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700">
23
{{ range $index, $reply := $comment.Replies }}
24
-
<div class="-ml-4">
25
-
{{
26
-
template "replyComment"
27
-
(dict
28
-
"RepoInfo" $root.RepoInfo
29
-
"LoggedInUser" $root.LoggedInUser
30
-
"Issue" $root.Issue
31
-
"Comment" $reply)
32
-
}}
33
</div>
34
{{ end }}
35
</div>
···
39
{{ end }}
40
41
{{ define "topLevelComment" }}
42
-
<div class="rounded px-6 py-4 bg-white dark:bg-gray-800 flex gap-2 ">
43
-
<div class="flex-shrink-0">
44
-
<img
45
-
src="{{ tinyAvatar .Comment.Did }}"
46
-
alt=""
47
-
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
48
-
/>
49
-
</div>
50
-
<div class="flex-1 min-w-0">
51
-
{{ template "repo/issues/fragments/issueCommentHeader" . }}
52
-
{{ template "repo/issues/fragments/issueCommentBody" . }}
53
-
</div>
54
</div>
55
{{ end }}
56
57
{{ define "replyComment" }}
58
-
<div class="py-4 pr-4 w-full mx-auto overflow-hidden flex gap-2 ">
59
-
<div class="flex-shrink-0">
60
-
<img
61
-
src="{{ tinyAvatar .Comment.Did }}"
62
-
alt=""
63
-
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
64
-
/>
65
-
</div>
66
-
<div class="flex-1 min-w-0">
67
-
{{ template "repo/issues/fragments/issueCommentHeader" . }}
68
-
{{ template "repo/issues/fragments/issueCommentBody" . }}
69
-
</div>
70
</div>
71
{{ end }}
···
1
{{ define "repo/issues/fragments/commentList" }}
2
+
<div class="flex flex-col gap-8">
3
{{ range $item := .CommentList }}
4
{{ template "commentListing" (list $ .) }}
5
{{ end }}
···
19
<div class="rounded border border-gray-200 dark:border-gray-700 w-full overflow-hidden shadow-sm bg-gray-50 dark:bg-gray-800/50">
20
{{ template "topLevelComment" $params }}
21
22
+
<div class="relative ml-4 border-l-2 border-gray-200 dark:border-gray-700">
23
{{ range $index, $reply := $comment.Replies }}
24
+
<div class="relative ">
25
+
<!-- Horizontal connector -->
26
+
<div class="absolute left-0 top-6 w-4 h-1 bg-gray-200 dark:bg-gray-700"></div>
27
+
28
+
<div class="pl-2">
29
+
{{
30
+
template "replyComment"
31
+
(dict
32
+
"RepoInfo" $root.RepoInfo
33
+
"LoggedInUser" $root.LoggedInUser
34
+
"Issue" $root.Issue
35
+
"Comment" $reply)
36
+
}}
37
+
</div>
38
</div>
39
{{ end }}
40
</div>
···
44
{{ end }}
45
46
{{ define "topLevelComment" }}
47
+
<div class="rounded px-6 py-4 bg-white dark:bg-gray-800">
48
+
{{ template "repo/issues/fragments/issueCommentHeader" . }}
49
+
{{ template "repo/issues/fragments/issueCommentBody" . }}
50
</div>
51
{{ end }}
52
53
{{ define "replyComment" }}
54
+
<div class="p-4 w-full mx-auto overflow-hidden">
55
+
{{ template "repo/issues/fragments/issueCommentHeader" . }}
56
+
{{ template "repo/issues/fragments/issueCommentBody" . }}
57
</div>
58
{{ end }}
+63
appview/pages/templates/repo/issues/fragments/globalIssueListing.html
+63
appview/pages/templates/repo/issues/fragments/globalIssueListing.html
···
···
1
+
{{ define "repo/issues/fragments/globalIssueListing" }}
2
+
<div class="flex flex-col gap-2">
3
+
{{ range .Issues }}
4
+
<div class="rounded drop-shadow-sm bg-white px-6 py-4 dark:bg-gray-800 dark:border-gray-700">
5
+
<div class="pb-2 mb-3">
6
+
<div class="flex items-center gap-3 mb-2">
7
+
<a
8
+
href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}"
9
+
class="text-blue-600 dark:text-blue-400 font-medium hover:underline text-sm"
10
+
>
11
+
{{ resolve .Repo.Did }}/{{ .Repo.Name }}
12
+
</a>
13
+
</div>
14
+
<a
15
+
href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}/issues/{{ .IssueId }}"
16
+
class="no-underline hover:underline"
17
+
>
18
+
{{ .Title | description }}
19
+
<span class="text-gray-500">#{{ .IssueId }}</span>
20
+
</a>
21
+
</div>
22
+
<div class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
23
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
24
+
{{ $icon := "ban" }}
25
+
{{ $state := "closed" }}
26
+
{{ if .Open }}
27
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
28
+
{{ $icon = "circle-dot" }}
29
+
{{ $state = "open" }}
30
+
{{ end }}
31
+
32
+
<span class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
33
+
{{ i $icon "w-3 h-3 mr-1.5 text-white dark:text-white" }}
34
+
<span class="text-white dark:text-white">{{ $state }}</span>
35
+
</span>
36
+
37
+
<span class="ml-1">
38
+
{{ template "user/fragments/picHandleLink" .Did }}
39
+
</span>
40
+
41
+
<span class="before:content-['ยท']">
42
+
{{ template "repo/fragments/time" .Created }}
43
+
</span>
44
+
45
+
<span class="before:content-['ยท']">
46
+
{{ $s := "s" }}
47
+
{{ if eq (len .Comments) 1 }}
48
+
{{ $s = "" }}
49
+
{{ end }}
50
+
<a href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}/issues/{{ .IssueId }}" class="text-gray-500 dark:text-gray-400">{{ len .Comments }} comment{{$s}}</a>
51
+
</span>
52
+
53
+
{{ $state := .Labels }}
54
+
{{ range $k, $d := $.LabelDefs }}
55
+
{{ range $v, $s := $state.GetValSet $d.AtUri.String }}
56
+
{{ template "labels/fragments/label" (dict "def" $d "val" $v "withPrefix" true) }}
57
+
{{ end }}
58
+
{{ end }}
59
+
</div>
60
+
</div>
61
+
{{ end }}
62
+
</div>
63
+
{{ end }}
+1
-2
appview/pages/templates/repo/issues/fragments/issueCommentHeader.html
+1
-2
appview/pages/templates/repo/issues/fragments/issueCommentHeader.html
···
1
{{ define "repo/issues/fragments/issueCommentHeader" }}
2
<div class="flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400 ">
3
-
{{ resolve .Comment.Did }}
4
{{ template "hats" $ }}
5
-
<span class="before:content-['ยท']"></span>
6
{{ template "timestamp" . }}
7
{{ $isCommentOwner := and .LoggedInUser (eq .LoggedInUser.Did .Comment.Did) }}
8
{{ if and $isCommentOwner (not .Comment.Deleted) }}
···
1
{{ define "repo/issues/fragments/issueCommentHeader" }}
2
<div class="flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400 ">
3
+
{{ template "user/fragments/picHandleLink" .Comment.Did }}
4
{{ template "hats" $ }}
5
{{ template "timestamp" . }}
6
{{ $isCommentOwner := and .LoggedInUser (eq .LoggedInUser.Did .Comment.Did) }}
7
{{ if and $isCommentOwner (not .Comment.Deleted) }}
+2
-2
appview/pages/templates/repo/issues/fragments/issueListing.html
+2
-2
appview/pages/templates/repo/issues/fragments/issueListing.html
+1
-1
appview/pages/templates/repo/issues/fragments/putIssue.html
+1
-1
appview/pages/templates/repo/issues/fragments/putIssue.html
+3
-3
appview/pages/templates/repo/issues/fragments/replyIssueCommentPlaceholder.html
+3
-3
appview/pages/templates/repo/issues/fragments/replyIssueCommentPlaceholder.html
···
1
{{ define "repo/issues/fragments/replyIssueCommentPlaceholder" }}
2
-
<div class="py-2 px-6 border-t flex gap-2 items-center border-gray-300 dark:border-gray-700">
3
{{ if .LoggedInUser }}
4
<img
5
src="{{ tinyAvatar .LoggedInUser.Did }}"
6
alt=""
7
-
class="rounded-full size-8 mr-1 border-2 border-gray-300 dark:border-gray-700"
8
/>
9
{{ end }}
10
<input
11
-
class="w-full p-0 border-none focus:outline-none"
12
placeholder="Leave a reply..."
13
hx-get="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment/{{ .Comment.Id }}/reply"
14
hx-trigger="focus"
···
1
{{ define "repo/issues/fragments/replyIssueCommentPlaceholder" }}
2
+
<div class="p-2 border-t flex gap-2 items-center border-gray-300 dark:border-gray-700">
3
{{ if .LoggedInUser }}
4
<img
5
src="{{ tinyAvatar .LoggedInUser.Did }}"
6
alt=""
7
+
class="rounded-full h-6 w-6 mr-1 border border-gray-300 dark:border-gray-700"
8
/>
9
{{ end }}
10
<input
11
+
class="w-full py-2 border-none focus:outline-none"
12
placeholder="Leave a reply..."
13
hx-get="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment/{{ .Comment.Id }}/reply"
14
hx-trigger="focus"
+5
-5
appview/pages/templates/repo/issues/issue.html
+5
-5
appview/pages/templates/repo/issues/issue.html
···
58
{{ $icon = "circle-dot" }}
59
{{ end }}
60
<div class="inline-flex items-center gap-2">
61
-
<span class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }}">
62
-
{{ i $icon "w-3 h-3 mr-1.5 text-white dark:text-white" }}
63
-
<span class="text-white dark:text-white text-sm">{{ .Issue.State }}</span>
64
-
</span>
65
-
66
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
67
opened by
68
{{ template "user/fragments/picHandleLink" .Issue.Did }}
···
58
{{ $icon = "circle-dot" }}
59
{{ end }}
60
<div class="inline-flex items-center gap-2">
61
+
<div id="state"
62
+
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
63
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
64
+
<span class="text-white">{{ .Issue.State }}</span>
65
+
</div>
66
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
67
opened by
68
{{ template "user/fragments/picHandleLink" .Issue.Did }}
+1
-1
appview/pages/templates/repo/pulls/fragments/pullActions.html
+1
-1
appview/pages/templates/repo/pulls/fragments/pullActions.html
···
22
{{ $isLastRound := eq $roundNumber $lastIdx }}
23
{{ $isSameRepoBranch := .Pull.IsBranchBased }}
24
{{ $isUpToDate := .ResubmitCheck.No }}
25
-
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2 relative py-2 px-4">
26
<button
27
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment"
28
hx-target="#actions-{{$roundNumber}}"
···
22
{{ $isLastRound := eq $roundNumber $lastIdx }}
23
{{ $isSameRepoBranch := .Pull.IsBranchBased }}
24
{{ $isUpToDate := .ResubmitCheck.No }}
25
+
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2 relative">
26
<button
27
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment"
28
hx-target="#actions-{{$roundNumber}}"
+7
-6
appview/pages/templates/repo/pulls/fragments/pullHeader.html
+7
-6
appview/pages/templates/repo/pulls/fragments/pullHeader.html
···
1
{{ define "repo/pulls/fragments/pullHeader" }}
2
-
<header class="pb-2">
3
<h1 class="text-2xl dark:text-white">
4
{{ .Pull.Title | description }}
5
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
···
17
{{ $icon = "git-merge" }}
18
{{ end }}
19
20
-
<section>
21
<div class="flex items-center gap-2">
22
-
<span
23
-
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm"
24
>
25
-
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
26
<span class="text-white">{{ .Pull.State.String }}</span>
27
-
</span>
28
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
29
opened by
30
{{ template "user/fragments/picHandleLink" .Pull.OwnerDid }}
···
1
{{ define "repo/pulls/fragments/pullHeader" }}
2
+
<header class="pb-4">
3
<h1 class="text-2xl dark:text-white">
4
{{ .Pull.Title | description }}
5
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
···
17
{{ $icon = "git-merge" }}
18
{{ end }}
19
20
+
<section class="mt-2">
21
<div class="flex items-center gap-2">
22
+
<div
23
+
id="state"
24
+
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
25
>
26
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
27
<span class="text-white">{{ .Pull.State.String }}</span>
28
+
</div>
29
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
30
opened by
31
{{ template "user/fragments/picHandleLink" .Pull.OwnerDid }}
-20
appview/pages/templates/repo/pulls/fragments/replyPullCommentPlaceholder.html
-20
appview/pages/templates/repo/pulls/fragments/replyPullCommentPlaceholder.html
···
1
-
{{ define "repo/pulls/fragments/replyPullCommentPlaceholder" }}
2
-
<div class="py-2 px-6 border-t flex gap-2 items-center border-gray-300 dark:border-gray-700">
3
-
{{ if .LoggedInUser }}
4
-
<img
5
-
src="{{ tinyAvatar .LoggedInUser.Did }}"
6
-
alt=""
7
-
class="rounded-full size-8 mr-1 border-2 border-gray-300 dark:border-gray-700"
8
-
/>
9
-
{{ end }}
10
-
<input
11
-
class="w-full p-0 border-none focus:outline-none"
12
-
placeholder="Leave a reply..."
13
-
hx-get="/{{ .Submission.ID }}/reply"
14
-
hx-trigger="focus"
15
-
hx-target="closest div"
16
-
hx-swap="outerHTML"
17
-
>
18
-
</input>
19
-
</div>
20
-
{{ end }}
···
+27
-229
appview/pages/templates/repo/pulls/pull.html
+27
-229
appview/pages/templates/repo/pulls/pull.html
···
6
{{ template "repo/pulls/fragments/og" (dict "RepoInfo" .RepoInfo "Pull" .Pull) }}
7
{{ end }}
8
9
-
{{ define "mainLayout" }}
10
-
<div class="px-1 col-span-full flex-grow flex flex-col gap-4">
11
-
{{ block "contentLayout" . }}
12
-
{{ block "content" . }}{{ end }}
13
-
{{ end }}
14
-
</div>
15
-
{{ end }}
16
-
17
{{ define "repoContentLayout" }}
18
<div class="grid grid-cols-1 md:grid-cols-10 gap-4 w-full">
19
-
<div class="col-span-1 md:col-span-7">
20
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto dark:text-white">
21
{{ block "repoContent" . }}{{ end }}
22
</section>
23
{{ block "repoAfter" . }}{{ end }}
24
</div>
25
-
<div class="col-span-1 md:col-span-3 flex flex-col gap-6">
26
{{ template "repo/fragments/labelPanel"
27
(dict "RepoInfo" $.RepoInfo
28
"Defs" $.LabelDefs
···
34
"Backlinks" $.Backlinks) }}
35
{{ template "repo/fragments/externalLinkPanel" $.Pull.AtUri }}
36
</div>
37
-
38
-
<div class="col-span-1 md:col-span-7">
39
-
{{ template "repo/fragments/diff" (list .Diff .DiffOpts) }}
40
-
</div>
41
-
<div class="col-span-1 md:col-span-3 flex flex-col max-h-dvh sticky top-0">
42
-
<div class="z-20 sticky top-0 rounded-t p-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700">
43
-
<h2 class="font-bold uppercase">history</h2>
44
-
</div>
45
-
<div class="flex flex-col-reverse gap-4 overflow-y-auto">
46
-
{{ template "submissions2" . }}
47
-
</div>
48
-
</div>
49
</div>
50
{{ end }}
51
···
60
{{ end }}
61
62
{{ define "repoAfter" }}
63
-
<div id="pull-close"></div>
64
-
<div id="pull-reopen"></div>
65
-
{{ end }}
66
-
67
-
{{ define "submissions2" }}
68
-
{{ $lastIdx := sub (len .Pull.Submissions) 1 }}
69
-
{{ range $ridx, $item := reverse .Pull.Submissions }}
70
-
{{ $idx := sub $lastIdx $ridx }}
71
-
<div class="rounded border border-gray-200 dark:border-gray-700 w-full shadow-sm bg-gray-50 dark:bg-gray-800/50">
72
-
{{ with $item }}
73
-
{{ $patches := .AsFormatPatch }}
74
-
{{ $round := .RoundNumber }}
75
-
<div class="rounded px-6 py-4 bg-white dark:bg-gray-800 flex gap-2">
76
-
<div class="flex-shrink-0">
77
-
<img
78
-
src="{{ tinyAvatar $.Pull.OwnerDid }}"
79
-
alt=""
80
-
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
81
-
/>
82
-
</div>
83
-
<!-- right column: name and body in two rows -->
84
-
<div class="flex-1 min-w-0 flex flex-col gap-2">
85
-
<div class="flex gap-2 items-center justify-between mb-1">
86
-
<span class="inline-flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-500">
87
-
{{ resolve $.Pull.OwnerDid }} submitted v{{ $round }}
88
-
<span class="select-none before:content-['\00B7']"></span>
89
-
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ $round }}">{{ template "repo/fragments/shortTimeAgo" .Created }}</a>
90
-
</span>
91
-
{{ if ne $idx 0 }}
92
-
<a class="flex items-center gap-2 no-underline hover:no-underline text-sm"
93
-
hx-boost="true"
94
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{$round}}/interdiff">
95
-
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
96
-
<span class="hidden md:inline">interdiff</span>
97
-
</a>
98
-
{{ end }}
99
-
</div>
100
-
<div>
101
-
{{ if eq 1 (len $patches) }}
102
-
<!-- only one commit, just inline the message into the round header -->
103
-
{{ $commit := index $patches 0 }}
104
-
<span>{{ $commit.Title | description }}</span>
105
-
{{ if gt (len $commit.Body) 0 }}
106
-
<p id="body-{{$round}}-{{$commit.SHA}}" class="mt-1 pb-2">
107
-
{{ nl2br $commit.Body }}
108
-
</p>
109
-
{{ end }}
110
-
{{ else }}
111
-
<span>Commits:</span>
112
-
{{ range $patches }}
113
-
<div id="commit-{{.SHA}}" class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
114
-
<div class="flex items-center gap-2">
115
-
{{ i "git-commit-horizontal" "w-4 h-4 flex-shrink-0" }}
116
-
<div class="flex items-center">
117
-
<span>{{ .Title | description }}</span>
118
-
{{ if gt (len .Body) 0 }}
119
-
<button
120
-
class="py-1/2 px-1 mx-2 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
121
-
hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
122
-
>
123
-
{{ i "ellipsis" "w-3 h-3" }}
124
-
</button>
125
-
{{ end }}
126
-
</div>
127
-
</div>
128
-
{{ if gt (len .Body) 0 }}
129
-
<p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 text-sm pb-2">
130
-
{{ nl2br .Body }}
131
-
</p>
132
-
{{ end }}
133
-
</div>
134
-
{{ end }}
135
-
{{ end }}
136
-
</div>
137
-
<div>
138
-
{{ block "pipelineStatus" (list $ .) }} {{ end }}
139
-
</div>
140
-
</div>
141
-
</div>
142
-
<div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700">
143
-
{{ range $cidx, $c := .Comments }}
144
-
<div id="comment-{{$c.ID}}" class="flex gap-2 -ml-4 py-4 w-full mx-auto">
145
-
<!-- left column: profile picture -->
146
-
<div class="flex-shrink-0">
147
-
<img
148
-
src="{{ tinyAvatar $c.OwnerDid }}"
149
-
alt=""
150
-
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
151
-
/>
152
-
</div>
153
-
<!-- right column: name and body in two rows -->
154
-
<div class="flex-1 min-w-0">
155
-
<!-- Row 1: Author and timestamp -->
156
-
<div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
157
-
<span>{{ resolve $c.OwnerDid }}</span>
158
-
<span class="before:content-['ยท']"></span>
159
-
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="#comment-{{.ID}}">{{ template "repo/fragments/time" $c.Created }}</a>
160
-
</div>
161
-
<!-- Row 2: Body text -->
162
-
<div class="prose dark:prose-invert mt-1">
163
-
{{ $c.Body | markdown }}
164
-
</div>
165
-
</div>
166
-
</div>
167
-
{{ end }}
168
-
</div>
169
-
{{ end }}
170
-
{{ if eq $lastIdx .RoundNumber }}
171
-
{{ block "mergeStatus" $ }} {{ end }}
172
-
{{ block "resubmitStatus" $ }} {{ end }}
173
-
{{ end }}
174
-
{{ if $.LoggedInUser }}
175
-
{{ if eq $lastIdx .RoundNumber }}
176
-
{{ template "newComment" (list $ .) }}
177
-
{{ else }}
178
-
{{ template "repo/pulls/fragments/replyPullCommentPlaceholder" (dict "LoggedInUser" $.LoggedInUser "Submission" .) }}
179
-
{{ end }}
180
-
{{ else }}
181
-
<div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm p-2 relative flex gap-2 items-center">
182
-
<a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
183
-
sign up
184
-
</a>
185
-
<span class="text-gray-500 dark:text-gray-400">or</span>
186
-
<a href="/login" class="underline">login</a>
187
-
to add to the discussion
188
-
</div>
189
-
{{ end }}
190
-
</div>
191
-
{{ end }}
192
-
{{ end }}
193
-
194
-
{{ define "newComment" }}
195
-
{{ $root := index . 0 }}
196
-
{{ $submission := index . 1 }}
197
-
<form
198
-
id="comment-form"
199
-
hx-post="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $submission.RoundNumber }}/comment"
200
-
hx-on::after-request="if(event.detail.successful) this.reset()"
201
-
>
202
-
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full">
203
-
<div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
204
-
{{ template "user/fragments/picHandleLink" $root.LoggedInUser.Did }}
205
</div>
206
-
<textarea
207
-
id="comment-textarea"
208
-
name="body"
209
-
class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
210
-
placeholder="Add to the discussion"
211
-
rows="8"
212
-
></textarea>
213
-
<div id="pull-comment"></div>
214
-
</div>
215
-
{{ template "replyActions" . }}
216
-
</form>
217
-
{{ end }}
218
-
219
-
{{ define "replyActions" }}
220
-
<div class="flex flex-wrap items-stretch justify-end gap-2 text-gray-500 dark:text-gray-400 text-sm">
221
-
{{ template "cancel" . }}
222
-
{{ template "reply" . }}
223
-
</div>
224
-
{{ end }}
225
-
226
-
{{ define "cancel" }}
227
-
<button
228
-
class="btn text-red-500 dark:text-red-400 flex gap-2 items-center group"
229
-
hx-get="TODO"
230
-
hx-target="TODO"
231
-
hx-swap="outerHTML">
232
-
{{ i "x" "size-4" }}
233
-
cancel
234
-
</button>
235
-
{{ end }}
236
237
-
{{ define "reply" }}
238
-
<button
239
-
id="TODO"
240
-
type="submit"
241
-
class="btn-create flex items-center gap-2 no-underline hover:no-underline">
242
-
{{ i "reply" "w-4 h-4 inline group-[.htmx-request]:hidden" }}
243
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
244
-
reply
245
-
</button>
246
{{ end }}
247
248
{{ define "submissions" }}
···
411
412
{{ define "mergeStatus" }}
413
{{ if .Pull.State.IsClosed }}
414
-
<div class="bg-gray-50 dark:bg-gray-700 border border-black dark:border-gray-500 rounded drop-shadow-sm px-6 py-2 relative">
415
<div class="flex items-center gap-2 text-black dark:text-white">
416
{{ i "ban" "w-4 h-4" }}
417
<span class="font-medium">closed without merging</span
···
419
</div>
420
</div>
421
{{ else if .Pull.State.IsMerged }}
422
-
<div class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative">
423
<div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
424
{{ i "git-merge" "w-4 h-4" }}
425
<span class="font-medium">pull request successfully merged</span
···
427
</div>
428
</div>
429
{{ else if .Pull.State.IsDeleted }}
430
-
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative">
431
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
432
{{ i "git-pull-request-closed" "w-4 h-4" }}
433
<span class="font-medium">This pull has been deleted (possibly by jj abandon or jj squash)</span>
434
</div>
435
</div>
436
{{ else if and .MergeCheck .MergeCheck.Error }}
437
-
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative">
438
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
439
{{ i "triangle-alert" "w-4 h-4" }}
440
<span class="font-medium">{{ .MergeCheck.Error }}</span>
441
</div>
442
</div>
443
{{ else if and .MergeCheck .MergeCheck.IsConflicted }}
444
-
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative">
445
-
<details class="text-red-500 dark:text-red-300 group">
446
-
<summary class="flex items-center justify-between cursor-pointer list-none">
447
-
<div class="flex items-center gap-2 ">
448
-
{{ i "triangle-alert" "w-4 h-4" }}
449
-
<span class="font-medium">merge conflicts detected</span>
450
-
</div>
451
-
<div>
452
-
<span class="group-open:hidden inline">{{ i "chevrons-up-down" "w-4 h-4" }}</span>
453
-
<span class="hidden group-open:inline">{{ i "chevrons-down-up" "w-4 h-4" }}</span>
454
-
</div>
455
-
</summary>
456
{{ if gt (len .MergeCheck.Conflicts) 0 }}
457
-
<ul class="space-y-1 mt-2">
458
{{ range .MergeCheck.Conflicts }}
459
{{ if .Filename }}
460
-
<li class="flex items-center">
461
-
{{ i "file-warning" "inline-flex w-4 h-4 mr-1.5 text-red-500 dark:text-red-300 flex-shrink-0" }}
462
-
<span class="font-mono" style="word-break: keep-all; overflow-wrap: break-word;">{{ .Filename }}</span>
463
-
</li>
464
{{ else if .Reason }}
465
<li class="flex items-center">
466
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
···
470
{{ end }}
471
</ul>
472
{{ end }}
473
-
</details>
474
</div>
475
{{ else if .MergeCheck }}
476
-
<div class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative">
477
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
478
{{ i "circle-check-big" "w-4 h-4" }}
479
<span class="font-medium">no conflicts, ready to merge</span>
···
484
485
{{ define "resubmitStatus" }}
486
{{ if .ResubmitCheck.Yes }}
487
-
<div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative">
488
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
489
{{ i "triangle-alert" "w-4 h-4" }}
490
<span class="font-medium">this branch has been updated, consider resubmitting</span>
···
500
{{ with $pipeline }}
501
{{ $id := .Id }}
502
{{ if .Statuses }}
503
-
<span>Workflows:</span>
504
-
<div class=" grid grid-cols-1 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
505
{{ range $name, $all := .Statuses }}
506
<a href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
507
<div
···
6
{{ template "repo/pulls/fragments/og" (dict "RepoInfo" .RepoInfo "Pull" .Pull) }}
7
{{ end }}
8
9
{{ define "repoContentLayout" }}
10
<div class="grid grid-cols-1 md:grid-cols-10 gap-4 w-full">
11
+
<div class="col-span-1 md:col-span-8">
12
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto dark:text-white">
13
{{ block "repoContent" . }}{{ end }}
14
</section>
15
{{ block "repoAfter" . }}{{ end }}
16
</div>
17
+
<div class="col-span-1 md:col-span-2 flex flex-col gap-6">
18
{{ template "repo/fragments/labelPanel"
19
(dict "RepoInfo" $.RepoInfo
20
"Defs" $.LabelDefs
···
26
"Backlinks" $.Backlinks) }}
27
{{ template "repo/fragments/externalLinkPanel" $.Pull.AtUri }}
28
</div>
29
</div>
30
{{ end }}
31
···
40
{{ end }}
41
42
{{ define "repoAfter" }}
43
+
<section id="submissions" class="mt-4">
44
+
<div class="flex flex-col gap-4">
45
+
{{ block "submissions" . }} {{ end }}
46
</div>
47
+
</section>
48
49
+
<div id="pull-close"></div>
50
+
<div id="pull-reopen"></div>
51
{{ end }}
52
53
{{ define "submissions" }}
···
216
217
{{ define "mergeStatus" }}
218
{{ if .Pull.State.IsClosed }}
219
+
<div class="bg-gray-50 dark:bg-gray-700 border border-black dark:border-gray-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
220
<div class="flex items-center gap-2 text-black dark:text-white">
221
{{ i "ban" "w-4 h-4" }}
222
<span class="font-medium">closed without merging</span
···
224
</div>
225
</div>
226
{{ else if .Pull.State.IsMerged }}
227
+
<div class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
228
<div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
229
{{ i "git-merge" "w-4 h-4" }}
230
<span class="font-medium">pull request successfully merged</span
···
232
</div>
233
</div>
234
{{ else if .Pull.State.IsDeleted }}
235
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
236
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
237
{{ i "git-pull-request-closed" "w-4 h-4" }}
238
<span class="font-medium">This pull has been deleted (possibly by jj abandon or jj squash)</span>
239
</div>
240
</div>
241
{{ else if and .MergeCheck .MergeCheck.Error }}
242
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
243
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
244
{{ i "triangle-alert" "w-4 h-4" }}
245
<span class="font-medium">{{ .MergeCheck.Error }}</span>
246
</div>
247
</div>
248
{{ else if and .MergeCheck .MergeCheck.IsConflicted }}
249
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
250
+
<div class="flex flex-col gap-2 text-red-500 dark:text-red-300">
251
+
<div class="flex items-center gap-2">
252
+
{{ i "triangle-alert" "w-4 h-4" }}
253
+
<span class="font-medium">merge conflicts detected</span>
254
+
</div>
255
{{ if gt (len .MergeCheck.Conflicts) 0 }}
256
+
<ul class="space-y-1">
257
{{ range .MergeCheck.Conflicts }}
258
{{ if .Filename }}
259
+
<li class="flex items-center">
260
+
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
261
+
<span class="font-mono">{{ .Filename }}</span>
262
+
</li>
263
{{ else if .Reason }}
264
<li class="flex items-center">
265
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
···
269
{{ end }}
270
</ul>
271
{{ end }}
272
+
</div>
273
</div>
274
{{ else if .MergeCheck }}
275
+
<div class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
276
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
277
{{ i "circle-check-big" "w-4 h-4" }}
278
<span class="font-medium">no conflicts, ready to merge</span>
···
283
284
{{ define "resubmitStatus" }}
285
{{ if .ResubmitCheck.Yes }}
286
+
<div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
287
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
288
{{ i "triangle-alert" "w-4 h-4" }}
289
<span class="font-medium">this branch has been updated, consider resubmitting</span>
···
299
{{ with $pipeline }}
300
{{ $id := .Id }}
301
{{ if .Statuses }}
302
+
<div class="max-w-80 grid grid-cols-1 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
303
{{ range $name, $all := .Statuses }}
304
<a href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
305
<div
+2
-11
appview/pulls/pulls.go
+2
-11
appview/pulls/pulls.go
···
232
defs[l.AtUri().String()] = &l
233
}
234
235
-
patch := pull.LatestSubmission().CombinedPatch()
236
-
diff := patchutil.AsNiceDiff(patch, pull.TargetBranch)
237
-
var diffOpts types.DiffOpts
238
-
if d := r.URL.Query().Get("diff"); d == "split" {
239
-
diffOpts.Split = true
240
-
}
241
-
242
-
log.Println(s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
243
LoggedInUser: user,
244
RepoInfo: s.repoResolver.GetRepoInfo(r, user),
245
Pull: pull,
···
250
MergeCheck: mergeCheckResponse,
251
ResubmitCheck: resubmitResult,
252
Pipelines: m,
253
-
Diff: &diff,
254
-
DiffOpts: diffOpts,
255
256
OrderedReactionKinds: models.OrderedReactionKinds,
257
Reactions: reactionMap,
258
UserReacted: userReactions,
259
260
LabelDefs: defs,
261
-
}))
262
}
263
264
func (s *Pulls) mergeCheck(r *http.Request, f *models.Repo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
···
232
defs[l.AtUri().String()] = &l
233
}
234
235
+
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
236
LoggedInUser: user,
237
RepoInfo: s.repoResolver.GetRepoInfo(r, user),
238
Pull: pull,
···
243
MergeCheck: mergeCheckResponse,
244
ResubmitCheck: resubmitResult,
245
Pipelines: m,
246
247
OrderedReactionKinds: models.OrderedReactionKinds,
248
Reactions: reactionMap,
249
UserReacted: userReactions,
250
251
LabelDefs: defs,
252
+
})
253
}
254
255
func (s *Pulls) mergeCheck(r *http.Request, f *models.Repo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
+5
-6
docs/template.html
+5
-6
docs/template.html
+3
nix/modules/appview.nix
+3
nix/modules/appview.nix