+39
appview/models/pipeline.go
+39
appview/models/pipeline.go
···
1
1
package models
2
2
3
3
import (
4
+
"fmt"
4
5
"slices"
6
+
"strings"
5
7
"time"
6
8
7
9
"github.com/bluesky-social/indigo/atproto/syntax"
···
50
52
}
51
53
52
54
return 0
55
+
}
56
+
57
+
// produces short summary of successes:
58
+
// - "0/4" when zero successes of 4 workflows
59
+
// - "4/4" when all successes of 4 workflows
60
+
// - "0/0" when no workflows run in this pipeline
61
+
func (p Pipeline) ShortStatusSummary() string {
62
+
counts := make(map[spindle.StatusKind]int)
63
+
for _, w := range p.Statuses {
64
+
counts[w.Latest().Status] += 1
65
+
}
66
+
67
+
total := len(p.Statuses)
68
+
successes := counts[spindle.StatusKindSuccess]
69
+
70
+
return fmt.Sprintf("%d/%d", successes, total)
71
+
}
72
+
73
+
// produces a string of the form "3/4 success, 2/4 failed, 1/4 pending"
74
+
func (p Pipeline) LongStatusSummary() string {
75
+
counts := make(map[spindle.StatusKind]int)
76
+
for _, w := range p.Statuses {
77
+
counts[w.Latest().Status] += 1
78
+
}
79
+
80
+
total := len(p.Statuses)
81
+
82
+
var result []string
83
+
// finish states first, followed by start states
84
+
states := append(spindle.FinishStates[:], spindle.StartStates[:]...)
85
+
for _, state := range states {
86
+
if count, ok := counts[state]; ok {
87
+
result = append(result, fmt.Sprintf("%d/%d %s", count, total, state.String()))
88
+
}
89
+
}
90
+
91
+
return strings.Join(result, ", ")
53
92
}
54
93
55
94
func (p Pipeline) Counts() map[string]int {
+7
-17
appview/models/pull.go
+7
-17
appview/models/pull.go
···
171
171
return syntax.ATURI(p.CommentAt)
172
172
}
173
173
174
-
// func (p *PullComment) AsRecord() tangled.RepoPullComment {
175
-
// mentions := make([]string, len(p.Mentions))
176
-
// for i, did := range p.Mentions {
177
-
// mentions[i] = string(did)
178
-
// }
179
-
// references := make([]string, len(p.References))
180
-
// for i, uri := range p.References {
181
-
// references[i] = string(uri)
182
-
// }
183
-
// return tangled.RepoPullComment{
184
-
// Pull: p.PullAt,
185
-
// Body: p.Body,
186
-
// Mentions: mentions,
187
-
// References: references,
188
-
// CreatedAt: p.Created.Format(time.RFC3339),
189
-
// }
190
-
// }
174
+
func (p *Pull) TotalComments() int {
175
+
total := 0
176
+
for _, s := range p.Submissions {
177
+
total += len(s.Comments)
178
+
}
179
+
return total
180
+
}
191
181
192
182
func (p *Pull) LastRoundNumber() int {
193
183
return len(p.Submissions) - 1
+1
-1
appview/pages/templates/fragments/tabSelector.html
+1
-1
appview/pages/templates/fragments/tabSelector.html
+1
-18
appview/pages/templates/repo/commit.html
+1
-18
appview/pages/templates/repo/commit.html
···
116
116
{{ block "content" . }}{{ end }}
117
117
{{ end }}
118
118
119
-
{{ block "contentAfterLayout" . }}
120
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
121
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
122
-
{{ block "contentAfterLeft" . }} {{ end }}
123
-
</div>
124
-
<main class="col-span-1 md:col-span-10">
125
-
{{ block "contentAfter" . }}{{ end }}
126
-
</main>
127
-
</div>
128
-
{{ end }}
119
+
{{ block "contentAfter" . }}{{ end }}
129
120
</div>
130
121
{{ end }}
131
122
···
139
130
{{ template "repo/fragments/diff" (list .Diff .DiffOpts) }}
140
131
{{end}}
141
132
142
-
{{ define "contentAfterLeft" }}
143
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
144
-
{{ template "repo/fragments/diffOpts" .DiffOpts }}
145
-
</div>
146
-
<div class="sticky top-0 flex-grow max-h-screen overflow-y-auto">
147
-
{{ template "repo/fragments/diffChangedFiles" .Diff }}
148
-
</div>
149
-
{{end}}
+1
-19
appview/pages/templates/repo/compare/compare.html
+1
-19
appview/pages/templates/repo/compare/compare.html
···
22
22
{{ block "content" . }}{{ end }}
23
23
{{ end }}
24
24
25
-
{{ block "contentAfterLayout" . }}
26
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
27
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
28
-
{{ block "contentAfterLeft" . }} {{ end }}
29
-
</div>
30
-
<main class="col-span-1 md:col-span-10">
31
-
{{ block "contentAfter" . }}{{ end }}
32
-
</main>
33
-
</div>
34
-
{{ end }}
25
+
{{ block "contentAfter" . }}{{ end }}
35
26
</div>
36
27
{{ end }}
37
28
···
44
35
{{ define "contentAfter" }}
45
36
{{ template "repo/fragments/diff" (list .Diff .DiffOpts) }}
46
37
{{end}}
47
-
48
-
{{ define "contentAfterLeft" }}
49
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
50
-
{{ template "repo/fragments/diffOpts" .DiffOpts }}
51
-
</div>
52
-
<div class="sticky top-0 flex-grow max-h-screen overflow-y-auto">
53
-
{{ template "repo/fragments/diffChangedFiles" .Diff }}
54
-
</div>
55
-
{{end}}
+113
-36
appview/pages/templates/repo/fragments/diff.html
+113
-36
appview/pages/templates/repo/fragments/diff.html
···
1
1
{{ define "repo/fragments/diff" }}
2
+
<style>
3
+
#filesToggle:checked ~ div label[for="filesToggle"] .show-text { display: none; }
4
+
#filesToggle:checked ~ div label[for="filesToggle"] .hide-text { display: inline; }
5
+
#filesToggle:not(:checked) ~ div label[for="filesToggle"] .hide-text { display: none; }
6
+
#filesToggle:checked ~ div div#files { width: 10vw; margin-right: 1rem; }
7
+
#filesToggle:not(:checked) ~ div div#files { width: 0; display: hidden; margin-right: 0; }
8
+
</style>
9
+
10
+
{{ template "diffTopbar" . }}
11
+
{{ block "diffLayout" . }} {{ end }}
12
+
{{ end }}
13
+
14
+
{{ define "diffTopbar" }}
15
+
{{ $diff := index . 0 }}
16
+
{{ $opts := index . 1 }}
17
+
18
+
{{ block "filesCheckbox" $ }} {{ end }}
19
+
{{ block "subsCheckbox" $ }} {{ end }}
20
+
21
+
<!-- top bar -->
22
+
<div class="sticky top-0 z-30 bg-slate-100 dark:bg-gray-900 flex items-center gap-2 col-span-full h-12 p-2">
23
+
<!-- left panel toggle -->
24
+
{{ template "filesToggle" . }}
25
+
26
+
<!-- stats -->
27
+
{{ template "repo/fragments/diffStatPill" $diff.Stat }}
28
+
{{ $diff.Stat.FilesChanged }} changed file{{ if ne $diff.Stat.FilesChanged 1 }}s{{ end }}
29
+
30
+
<!-- spacer -->
31
+
<div class="flex-grow"></div>
32
+
33
+
<!-- diff options -->
34
+
{{ template "repo/fragments/diffOpts" $opts }}
35
+
36
+
<!-- right panel toggle -->
37
+
{{ block "subsToggle" $ }} {{ end }}
38
+
</div>
39
+
40
+
{{ end }}
41
+
42
+
{{ define "diffLayout" }}
43
+
{{ $diff := index . 0 }}
44
+
{{ $opts := index . 1 }}
45
+
46
+
<div class="flex col-span-full">
47
+
<!-- Left panel (same for both desktop and mobile) -->
48
+
<div id="files" class="w-0 overflow-hidden sticky top-12 max-h-screen overflow-y-auto pb-12">
49
+
{{ template "repo/fragments/diffChangedFiles" $diff }}
50
+
</div>
51
+
52
+
<!-- Main content -->
53
+
<div class="flex-1 min-w-0 sticky top-12 pb-12">
54
+
{{ template "diffFiles" (list $diff $opts) }}
55
+
</div>
56
+
57
+
</div>
58
+
{{ end }}
59
+
60
+
{{ define "diffFiles" }}
2
61
{{ $diff := index . 0 }}
3
62
{{ $opts := index . 1 }}
4
63
···
15
74
<p>No differences found between the selected revisions.</p>
16
75
</div>
17
76
{{ else }}
18
-
{{ range $idx, $hunk := $diff }}
19
-
{{ with $hunk }}
20
-
<details open id="file-{{ .Id }}" class="group border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm" tabindex="{{ add $idx 1 }}">
21
-
<summary class="list-none cursor-pointer sticky top-12">
22
-
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
23
-
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
24
-
<span class="group-open:hidden inline">{{ i "chevron-right" "w-4 h-4" }}</span>
25
-
<span class="hidden group-open:inline">{{ i "chevron-down" "w-4 h-4" }}</span>
26
-
{{ template "repo/fragments/diffStatPill" .Stats }}
77
+
{{ range $idx, $file := $diff }}
78
+
{{ template "diffFile" (list $idx $file $isSplit) }}
79
+
{{ end }}
80
+
{{ end }}
81
+
</div>
82
+
{{ end }}
27
83
28
-
<div class="flex gap-2 items-center overflow-x-auto">
29
-
{{ if .IsDelete }}
30
-
{{ .Name.Old }}
31
-
{{ else if (or .IsCopy .IsRename) }}
32
-
{{ .Name.Old }} {{ i "arrow-right" "w-4 h-4" }} {{ .Name.New }}
33
-
{{ else }}
34
-
{{ .Name.New }}
35
-
{{ end }}
36
-
</div>
37
-
</div>
38
-
</div>
39
-
</summary>
84
+
{{ define "diffFile" }}
85
+
{{ $idx := index . 0 }}
86
+
{{ $file := index . 1 }}
87
+
{{ $isSplit := index . 2 }}
88
+
{{ with $file }}
89
+
<details open id="file-{{ .Id }}" class="group border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm" tabindex="{{ add $idx 1 }}">
90
+
<summary class="list-none cursor-pointer sticky top-12 group-open:border-b border-gray-200 dark:border-gray-700">
91
+
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
92
+
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
93
+
<span class="group-open:hidden inline">{{ i "chevron-right" "w-4 h-4" }}</span>
94
+
<span class="hidden group-open:inline">{{ i "chevron-down" "w-4 h-4" }}</span>
95
+
{{ template "repo/fragments/diffStatPill" .Stats }}
40
96
41
-
<div class="transition-all duration-700 ease-in-out">
42
-
{{ if .IsBinary }}
43
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
44
-
This is a binary file and will not be displayed.
45
-
</p>
46
-
{{ else }}
47
-
{{ if $isSplit }}
48
-
{{- template "repo/fragments/splitDiff" .Split -}}
97
+
<div class="flex gap-2 items-center overflow-x-auto">
98
+
{{ if .IsDelete }}
99
+
{{ .Name.Old }}
100
+
{{ else if (or .IsCopy .IsRename) }}
101
+
{{ .Name.Old }} {{ i "arrow-right" "w-4 h-4" }} {{ .Name.New }}
49
102
{{ else }}
50
-
{{- template "repo/fragments/unifiedDiff" . -}}
103
+
{{ .Name.New }}
51
104
{{ end }}
52
-
{{- end -}}
105
+
</div>
53
106
</div>
54
-
</details>
55
-
{{ end }}
56
-
{{ end }}
57
-
{{ end }}
58
-
</div>
107
+
</div>
108
+
</summary>
109
+
110
+
<div class="transition-all duration-700 ease-in-out">
111
+
{{ if .IsBinary }}
112
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
113
+
This is a binary file and will not be displayed.
114
+
</p>
115
+
{{ else }}
116
+
{{ if $isSplit }}
117
+
{{- template "repo/fragments/splitDiff" .Split -}}
118
+
{{ else }}
119
+
{{- template "repo/fragments/unifiedDiff" . -}}
120
+
{{ end }}
121
+
{{- end -}}
122
+
</div>
123
+
</details>
124
+
{{ end }}
125
+
{{ end }}
126
+
127
+
{{ define "filesCheckbox" }}
128
+
<input type="checkbox" id="filesToggle" class="peer/files hidden" checked/>
129
+
{{ end }}
130
+
131
+
{{ define "filesToggle" }}
132
+
<label title="Toggle filetree panel" for="filesToggle" class="hidden md:inline-flex items-center justify-center rounded cursor-pointer text-normal font-normal normalcase">
133
+
<span class="show-text">{{ i "panel-left-open" "size-4" }}</span>
134
+
<span class="hide-text">{{ i "panel-left-close" "size-4" }}</span>
135
+
</label>
59
136
{{ end }}
+2
-3
appview/pages/templates/repo/fragments/interdiff.html
+2
-3
appview/pages/templates/repo/fragments/interdiff.html
···
1
1
{{ define "repo/fragments/interdiff" }}
2
-
{{ $repo := index . 0 }}
3
-
{{ $x := index . 1 }}
4
-
{{ $opts := index . 2 }}
2
+
{{ $x := index . 0 }}
3
+
{{ $opts := index . 1 }}
5
4
{{ $fileTree := fileTree $x.AffectedFiles }}
6
5
{{ $diff := $x.Files }}
7
6
{{ $last := sub (len $diff) 1 }}
+1
-1
appview/pages/templates/repo/fragments/splitDiff.html
+1
-1
appview/pages/templates/repo/fragments/splitDiff.html
···
3
3
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}}
4
4
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
5
5
{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
6
-
{{- $containerStyle := "inline-flex w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
6
+
{{- $containerStyle := "inline-flex w-full items-center target:bg-yellow-200 target:dark:bg-yellow-700 scroll-mt-48" -}}
7
7
{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}}
8
8
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}}
9
9
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
+1
-1
appview/pages/templates/repo/fragments/unifiedDiff.html
+1
-1
appview/pages/templates/repo/fragments/unifiedDiff.html
···
7
7
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
8
8
{{- $lineNrSepStyle1 := "" -}}
9
9
{{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
10
-
{{- $containerStyle := "inline-flex w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
10
+
{{- $containerStyle := "inline-flex w-full items-center target:bg-yellow-200 target:dark:bg-yellow-700 scroll-mt-48" -}}
11
11
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}}
12
12
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
13
13
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
+60
-69
appview/pages/templates/repo/pipelines/fragments/pipelineSymbol.html
+60
-69
appview/pages/templates/repo/pipelines/fragments/pipelineSymbol.html
···
1
1
{{ define "repo/pipelines/fragments/pipelineSymbol" }}
2
-
<div class="cursor-pointer">
3
-
{{ $c := .Counts }}
4
-
{{ $statuses := .Statuses }}
5
-
{{ $total := len $statuses }}
6
-
{{ $success := index $c "success" }}
7
-
{{ $fail := index $c "failed" }}
8
-
{{ $timeout := index $c "timeout" }}
9
-
{{ $empty := eq $total 0 }}
10
-
{{ $allPass := eq $success $total }}
11
-
{{ $allFail := eq $fail $total }}
12
-
{{ $allTimeout := eq $timeout $total }}
13
-
14
-
{{ if $empty }}
15
-
<div class="flex gap-1 items-center">
16
-
{{ i "hourglass" "size-4 text-gray-600 dark:text-gray-400 " }}
17
-
<span>0/{{ $total }}</span>
18
-
</div>
19
-
{{ else if $allPass }}
20
-
<div class="flex gap-1 items-center">
21
-
{{ i "check" "size-4 text-green-600" }}
22
-
<span>{{ $total }}/{{ $total }}</span>
23
-
</div>
24
-
{{ else if $allFail }}
25
-
<div class="flex gap-1 items-center">
26
-
{{ i "x" "size-4 text-red-500" }}
27
-
<span>0/{{ $total }}</span>
28
-
</div>
29
-
{{ else if $allTimeout }}
30
-
<div class="flex gap-1 items-center">
31
-
{{ i "clock-alert" "size-4 text-orange-500" }}
32
-
<span>0/{{ $total }}</span>
33
-
</div>
2
+
<div class="cursor-pointer flex gap-2 items-center">
3
+
{{ template "symbol" .Pipeline }}
4
+
{{ if .ShortSummary }}
5
+
{{ .Pipeline.ShortStatusSummary }}
34
6
{{ else }}
35
-
{{ $radius := f64 8 }}
36
-
{{ $circumference := mulf64 2.0 (mulf64 3.1416 $radius) }}
37
-
{{ $offset := 0.0 }}
38
-
<div class="flex gap-1 items-center">
39
-
<svg class="w-4 h-4 transform -rotate-90" viewBox="0 0 20 20">
40
-
<circle cx="10" cy="10" r="{{ $radius }}" fill="none" stroke="#f3f4f633" stroke-width="2"/>
7
+
{{ .Pipeline.LongStatusSummary }}
8
+
{{ end }}
9
+
</div>
10
+
{{ end }}
41
11
42
-
{{ range $kind, $count := $c }}
43
-
{{ $color := "" }}
44
-
{{ if or (eq $kind "pending") (eq $kind "running") }}
45
-
{{ $color = "#eab308" }} {{/* amber-500 */}}
46
-
{{ else if eq $kind "success" }}
47
-
{{ $color = "#10b981" }} {{/* green-500 */}}
48
-
{{ else if eq $kind "cancelled" }}
49
-
{{ $color = "#6b7280" }} {{/* gray-500 */}}
50
-
{{ else if eq $kind "timeout" }}
51
-
{{ $color = "#fb923c" }} {{/* orange-400 */}}
52
-
{{ else }}
53
-
{{ $color = "#ef4444" }} {{/* red-500 for failed or unknown */}}
54
-
{{ end }}
12
+
{{ define "symbol" }}
13
+
{{ $c := .Counts }}
14
+
{{ $statuses := .Statuses }}
15
+
{{ $total := len $statuses }}
16
+
{{ $success := index $c "success" }}
17
+
{{ $fail := index $c "failed" }}
18
+
{{ $timeout := index $c "timeout" }}
19
+
{{ $empty := eq $total 0 }}
20
+
{{ $allPass := eq $success $total }}
21
+
{{ $allFail := eq $fail $total }}
22
+
{{ $allTimeout := eq $timeout $total }}
55
23
56
-
{{ $percent := divf64 (f64 $count) (f64 $total) }}
57
-
{{ $length := mulf64 $percent $circumference }}
58
-
59
-
<circle
60
-
cx="10" cy="10" r="{{ $radius }}"
61
-
fill="none"
62
-
stroke="{{ $color }}"
63
-
stroke-width="2"
64
-
stroke-dasharray="{{ printf "%.2f %.2f" $length (subf64 $circumference $length) }}"
65
-
stroke-dashoffset="{{ printf "%.2f" (negf64 $offset) }}"
66
-
/>
67
-
{{ $offset = addf64 $offset $length }}
68
-
{{ end }}
69
-
</svg>
70
-
<span>{{ $success }}/{{ $total }}</span>
71
-
</div>
72
-
{{ end }}
73
-
</div>
24
+
{{ if $empty }}
25
+
{{ i "hourglass" "size-4 text-gray-600 dark:text-gray-400 " }}
26
+
{{ else if $allPass }}
27
+
{{ i "check" "size-4 text-green-600 dark:text-green-500" }}
28
+
{{ else if $allFail }}
29
+
{{ i "x" "size-4 text-red-600 dark:text-red-500" }}
30
+
{{ else if $allTimeout }}
31
+
{{ i "clock-alert" "size-4 text-orange-500" }}
32
+
{{ else }}
33
+
{{ $radius := f64 8 }}
34
+
{{ $circumference := mulf64 2.0 (mulf64 3.1416 $radius) }}
35
+
{{ $offset := 0.0 }}
36
+
<svg class="w-4 h-4 transform -rotate-90" viewBox="0 0 20 20">
37
+
<circle cx="10" cy="10" r="{{ $radius }}" fill="none" class="stroke-gray-200 dark:stroke-gray-700" stroke-width="2"/>
38
+
{{ range $kind, $count := $c }}
39
+
{{ $colorClass := "" }}
40
+
{{ if or (eq $kind "pending") (eq $kind "running") }}
41
+
{{ $colorClass = "stroke-yellow-600 dark:stroke-yellow-500" }}
42
+
{{ else if eq $kind "success" }}
43
+
{{ $colorClass = "stroke-green-600 dark:stroke-green-500" }}
44
+
{{ else if eq $kind "cancelled" }}
45
+
{{ $colorClass = "stroke-gray-600 dark:stroke-gray-500" }}
46
+
{{ else if eq $kind "timeout" }}
47
+
{{ $colorClass = "stroke-orange-600 dark:stroke-orange-500" }}
48
+
{{ else }}
49
+
{{ $colorClass = "stroke-red-600 dark:stroke-red-500" }}
50
+
{{ end }}
51
+
{{ $percent := divf64 (f64 $count) (f64 $total) }}
52
+
{{ $length := mulf64 $percent $circumference }}
53
+
<circle
54
+
cx="10" cy="10" r="{{ $radius }}"
55
+
fill="none"
56
+
class="{{ $colorClass }}"
57
+
stroke-width="2"
58
+
stroke-dasharray="{{ printf "%.2f %.2f" $length (subf64 $circumference $length) }}"
59
+
stroke-dashoffset="{{ printf "%.2f" (negf64 $offset) }}"
60
+
/>
61
+
{{ $offset = addf64 $offset $length }}
62
+
{{ end }}
63
+
</svg>
64
+
{{ end }}
74
65
{{ end }}
+1
-1
appview/pages/templates/repo/pipelines/fragments/pipelineSymbolLong.html
+1
-1
appview/pages/templates/repo/pipelines/fragments/pipelineSymbolLong.html
···
4
4
<div class="relative inline-block">
5
5
<details class="relative">
6
6
<summary class="cursor-pointer list-none">
7
-
{{ template "repo/pipelines/fragments/pipelineSymbol" .Pipeline }}
7
+
{{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" true) }}
8
8
</summary>
9
9
{{ template "repo/pipelines/fragments/tooltip" $ }}
10
10
</details>
+2
-3
appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html
+2
-3
appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html
···
15
15
16
16
<div class="flex-shrink-0 flex items-center gap-2">
17
17
{{ $latestRound := .LastRoundNumber }}
18
-
{{ $lastSubmission := index .Submissions $latestRound }}
19
-
{{ $commentCount := len $lastSubmission.Comments }}
18
+
{{ $commentCount := .TotalComments }}
20
19
{{ if and $pipeline $pipeline.Id }}
21
-
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
20
+
{{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" true) }}
22
21
<span class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
23
22
{{ end }}
24
23
<span>
+2
-20
appview/pages/templates/repo/pulls/interdiff.html
+2
-20
appview/pages/templates/repo/pulls/interdiff.html
···
34
34
{{ block "content" . }}{{ end }}
35
35
{{ end }}
36
36
37
-
{{ block "contentAfterLayout" . }}
38
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
39
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
40
-
{{ block "contentAfterLeft" . }} {{ end }}
41
-
</div>
42
-
<main class="col-span-1 md:col-span-10">
43
-
{{ block "contentAfter" . }}{{ end }}
44
-
</main>
45
-
</div>
46
-
{{ end }}
37
+
{{ block "contentAfter" . }}{{ end }}
47
38
</div>
48
39
{{ end }}
49
40
50
41
{{ define "contentAfter" }}
51
-
{{ template "repo/fragments/interdiff" (list .RepoInfo.FullName .Interdiff .DiffOpts) }}
52
-
{{end}}
53
-
54
-
{{ define "contentAfterLeft" }}
55
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
56
-
{{ template "repo/fragments/diffOpts" .DiffOpts }}
57
-
</div>
58
-
<div class="sticky top-0 flex-grow max-h-screen overflow-y-auto">
59
-
{{ template "repo/fragments/interdiffFiles" .Interdiff }}
60
-
</div>
42
+
{{ template "repo/fragments/interdiff" (list .Interdiff .DiffOpts) }}
61
43
{{end}}
+379
-445
appview/pages/templates/repo/pulls/pull.html
+379
-445
appview/pages/templates/repo/pulls/pull.html
···
12
12
{{ block "content" . }}{{ end }}
13
13
{{ end }}
14
14
</div>
15
+
<script>
16
+
(function() {
17
+
const details = document.getElementById('bottomSheet');
18
+
const isDesktop = () => window.matchMedia('(min-width: 768px)').matches;
19
+
20
+
// close on mobile initially
21
+
if (!isDesktop()) {
22
+
details.open = false;
23
+
}
24
+
25
+
// prevent closing on desktop
26
+
details.addEventListener('toggle', function(e) {
27
+
if (isDesktop() && !this.open) {
28
+
this.open = true;
29
+
}
30
+
});
31
+
32
+
const mediaQuery = window.matchMedia('(min-width: 768px)');
33
+
mediaQuery.addEventListener('change', function(e) {
34
+
if (e.matches) {
35
+
// switched to desktop - keep open
36
+
details.open = true;
37
+
} else {
38
+
// switched to mobile - close
39
+
details.open = false;
40
+
}
41
+
});
42
+
})();
43
+
</script>
15
44
{{ end }}
16
45
17
46
{{ define "repoContentLayout" }}
···
35
64
{{ template "repo/fragments/externalLinkPanel" $.Pull.AtUri }}
36
65
</div>
37
66
38
-
<style>
39
-
#filesToggle:checked ~ div label[for="filesToggle"] .show-text { display: none; }
40
-
#filesToggle:checked ~ div label[for="filesToggle"] .hide-text { display: inline; }
41
-
#filesToggle:not(:checked) ~ div label[for="filesToggle"] .hide-text { display: none; }
42
-
43
-
#filesToggle:checked ~ div div#files { width: 10vw; margin-right: 1rem; }
44
-
#filesToggle:not(:checked) ~ div div#files { width: 0; display: hidden; margin-right: 0; }
45
-
46
-
#subsToggle:checked ~ div div#subs { width: 25vw; margin-left: 1rem; }
47
-
#subsToggle:not(:checked) ~ div div#subs { width: 0; display: hidden; margin-left: 0; }
48
-
</style>
49
-
50
-
<!-- Checkboxes must come first as siblings -->
51
-
<input type="checkbox" id="filesToggle" class="peer/files hidden" checked/>
52
-
<input type="checkbox" id="subsToggle" class="peer/subs hidden" checked/>
53
-
54
-
<!-- Top bar with controls -->
55
-
<div class="sticky top-0 z-30 bg-slate-100 dark:bg-gray-900 flex items-center gap-2 col-span-full h-12">
56
-
<label for="filesToggle" class="inline-flex items-center justify-center rounded cursor-pointer p-2 text-normal font-normal normalcase">
57
-
<span class="show-text">{{ i "panel-left-open" "size-5" }}</span>
58
-
<span class="hide-text">{{ i "panel-left-close" "size-5" }}</span>
59
-
</label>
60
-
{{ template "repo/fragments/diffStatPill" .Diff.Stat }}
61
-
{{ .Diff.Stat.FilesChanged }} changed file{{ if ne .Diff.Stat.FilesChanged 1 }}s{{ end }}
62
-
<div class="flex-grow"></div>
63
-
{{ template "repo/fragments/diffOpts" .DiffOpts }}
64
-
<label for="subsToggle" class="inline-flex items-center justify-center rounded cursor-pointer p-2">
65
-
{{ i "message-square-more" "size-5" }}
66
-
</label>
67
-
</div>
68
-
69
-
<div class="flex col-span-full">
70
-
<!-- left panel -->
71
-
<div id="files" class="w-0 overflow-hidden sticky top-12 max-h-screen overflow-y-auto pb-12">
72
-
{{ template "repo/fragments/diffChangedFiles" .Diff }}
73
-
</div>
74
-
75
-
<!-- main content -->
76
-
<div class="flex-1 min-w-0 sticky top-12 pb-12">
77
-
{{ template "repo/fragments/diff" (list .Diff .DiffOpts) }}
78
-
</div>
79
-
80
-
<!-- right panel -->
81
-
<div id="subs" class="w-0 overflow-hidden max-h-screen flex flex-col sticky top-12 pb-12">
82
-
<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">
83
-
<h2 class="font-bold uppercase">history</h2>
84
-
</div>
85
-
<div class="flex flex-col-reverse gap-4 overflow-y-auto">
86
-
{{ template "submissions2" . }}
87
-
</div>
88
-
</div>
89
-
</div>
67
+
{{ template "repo/fragments/diff" (list .Diff .DiffOpts $) }}
90
68
</div>
91
69
{{ end }}
92
70
···
104
82
<div id="pull-reopen"></div>
105
83
{{ end }}
106
84
107
-
{{ define "submissions2" }}
108
-
{{ $lastIdx := sub (len .Pull.Submissions) 1 }}
109
-
{{ range $ridx, $item := reverse .Pull.Submissions }}
110
-
{{ $idx := sub $lastIdx $ridx }}
111
-
<div class="rounded border border-gray-200 dark:border-gray-700 w-full shadow-sm bg-gray-50 dark:bg-gray-800/50">
112
-
{{ with $item }}
113
-
{{ $patches := .AsFormatPatch }}
114
-
{{ $round := .RoundNumber }}
115
-
<div class="rounded px-6 py-4 bg-white dark:bg-gray-800 flex gap-2">
116
-
<div class="flex-shrink-0">
117
-
<img
118
-
src="{{ tinyAvatar $.Pull.OwnerDid }}"
119
-
alt=""
120
-
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
121
-
/>
122
-
</div>
123
-
<!-- right column: name and body in two rows -->
124
-
<div class="flex-1 min-w-0 flex flex-col gap-2">
125
-
<div class="flex gap-2 items-center justify-between mb-1">
126
-
<span class="inline-flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-500">
127
-
{{ resolve $.Pull.OwnerDid }} submitted v{{ $round }}
128
-
<span class="select-none before:content-['\00B7']"></span>
129
-
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ $round }}">{{ template "repo/fragments/shortTimeAgo" .Created }}</a>
130
-
</span>
131
-
{{ if ne $idx 0 }}
132
-
<a class="flex items-center gap-2 no-underline hover:no-underline text-sm"
133
-
hx-boost="true"
134
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{$round}}/interdiff">
135
-
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
136
-
<span class="hidden md:inline">interdiff</span>
137
-
</a>
138
-
{{ end }}
139
-
</div>
140
-
<div>
141
-
{{ if eq 1 (len $patches) }}
142
-
<!-- only one commit, just inline the message into the round header -->
143
-
{{ $commit := index $patches 0 }}
144
-
<span>{{ $commit.Title | description }}</span>
145
-
{{ if gt (len $commit.Body) 0 }}
146
-
<p id="body-{{$round}}-{{$commit.SHA}}" class="mt-1 pb-2">
147
-
{{ nl2br $commit.Body }}
148
-
</p>
149
-
{{ end }}
150
-
{{ else }}
151
-
<span>Commits:</span>
152
-
{{ range $patches }}
153
-
<div id="commit-{{.SHA}}" class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
154
-
<div class="flex items-center gap-2">
155
-
{{ i "git-commit-horizontal" "w-4 h-4 flex-shrink-0" }}
156
-
<div class="flex items-center">
157
-
<span>{{ .Title | description }}</span>
158
-
{{ if gt (len .Body) 0 }}
159
-
<button
160
-
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"
161
-
hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
162
-
>
163
-
{{ i "ellipsis" "w-3 h-3" }}
164
-
</button>
165
-
{{ end }}
166
-
</div>
167
-
</div>
168
-
{{ if gt (len .Body) 0 }}
169
-
<p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 text-sm pb-2">
170
-
{{ nl2br .Body }}
171
-
</p>
172
-
{{ end }}
173
-
</div>
174
-
{{ end }}
175
-
{{ end }}
176
-
</div>
177
-
<div>
178
-
{{ block "pipelineStatus" (list $ .) }} {{ end }}
179
-
</div>
180
-
</div>
181
-
</div>
182
-
<div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700">
183
-
{{ range $cidx, $c := .Comments }}
184
-
<div id="comment-{{$c.ID}}" class="flex gap-2 -ml-4 py-4 w-full mx-auto">
185
-
<!-- left column: profile picture -->
186
-
<div class="flex-shrink-0">
187
-
<img
188
-
src="{{ tinyAvatar $c.OwnerDid }}"
189
-
alt=""
190
-
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
191
-
/>
192
-
</div>
193
-
<!-- right column: name and body in two rows -->
194
-
<div class="flex-1 min-w-0">
195
-
<!-- Row 1: Author and timestamp -->
196
-
<div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
197
-
<span>{{ resolve $c.OwnerDid }}</span>
198
-
<span class="before:content-['·']"></span>
199
-
<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>
200
-
</div>
201
-
<!-- Row 2: Body text -->
202
-
<div class="prose dark:prose-invert mt-1">
203
-
{{ $c.Body | markdown }}
204
-
</div>
205
-
</div>
206
-
</div>
207
-
{{ end }}
208
-
</div>
209
-
{{ end }}
210
-
{{ if eq $lastIdx .RoundNumber }}
211
-
{{ block "mergeStatus" $ }} {{ end }}
212
-
{{ block "resubmitStatus" $ }} {{ end }}
213
-
{{ end }}
214
-
{{ if $.LoggedInUser }}
215
-
{{ template "repo/pulls/fragments/pullActions"
216
-
(dict
217
-
"LoggedInUser" $.LoggedInUser
218
-
"Pull" $.Pull
219
-
"RepoInfo" $.RepoInfo
220
-
"RoundNumber" .RoundNumber
221
-
"MergeCheck" $.MergeCheck
222
-
"ResubmitCheck" $.ResubmitCheck
223
-
"BranchDeleteStatus" $.BranchDeleteStatus
224
-
"Stack" $.Stack) }}
225
-
{{ else }}
226
-
<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">
227
-
<a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
228
-
sign up
229
-
</a>
230
-
<span class="text-gray-500 dark:text-gray-400">or</span>
231
-
<a href="/login" class="underline">login</a>
232
-
to add to the discussion
233
-
</div>
234
-
{{ end }}
85
+
{{ define "diffLayout" }}
86
+
{{ $diff := index . 0 }}
87
+
{{ $opts := index . 1 }}
88
+
{{ $root := index . 2 }}
89
+
90
+
<div class="flex col-span-full">
91
+
<!-- left panel -->
92
+
<div id="files" class="w-0 hidden md:block overflow-hidden sticky top-12 max-h-screen overflow-y-auto pb-12">
93
+
{{ template "repo/fragments/diffChangedFiles" $diff }}
235
94
</div>
236
-
{{ end }}
237
-
{{ end }}
238
95
239
-
{{ define "newComment" }}
240
-
{{ $root := index . 0 }}
241
-
{{ $submission := index . 1 }}
242
-
<form
243
-
id="comment-form"
244
-
hx-post="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $submission.RoundNumber }}/comment"
245
-
hx-on::after-request="if(event.detail.successful) this.reset()"
246
-
>
247
-
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full">
248
-
<div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
249
-
{{ template "user/fragments/picHandleLink" $root.LoggedInUser.Did }}
250
-
</div>
251
-
<textarea
252
-
id="comment-textarea"
253
-
name="body"
254
-
class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
255
-
placeholder="Add to the discussion"
256
-
rows="8"
257
-
></textarea>
258
-
<div id="pull-comment"></div>
96
+
<!-- main content -->
97
+
<div class="flex-1 min-w-0 sticky top-12 pb-12">
98
+
{{ template "diffFiles" (list $diff $opts) }}
259
99
</div>
260
-
{{ template "replyActions" . }}
261
-
</form>
100
+
101
+
<!-- right panel -->
102
+
{{ template "subsPanel" $ }}
103
+
</div>
262
104
{{ end }}
263
105
264
-
{{ define "replyActions" }}
265
-
<div class="flex flex-wrap items-stretch justify-end gap-2 text-gray-500 dark:text-gray-400 text-sm">
266
-
{{ template "cancel" . }}
267
-
{{ template "reply" . }}
106
+
{{ define "subsPanel" }}
107
+
{{ $root := index . 2 }}
108
+
{{ $pull := $root.Pull }}
109
+
{{ $commentCount := $pull.TotalComments }}
110
+
111
+
<!-- backdrop overlay - only visible on mobile when open -->
112
+
<div class="
113
+
fixed inset-0 bg-black/50 z-50 md:hidden opacity-0
114
+
pointer-events-none transition-opacity duration-300
115
+
has-[~#subs_details[open]]:opacity-100 has-[~#subs_details[open]]:pointer-events-auto">
116
+
</div>
117
+
<!-- right panel - bottom sheet on mobile, side panel on desktop -->
118
+
<div id="subs" class="fixed bottom-0 left-0 right-0 z-50 w-full md:static md:z-auto md:max-h-screen md:sticky md:top-12 overflow-hidden">
119
+
<details open id="bottomSheet" class="group rounded-t-2xl md:rounded-t-sm drop-shadow-lg md:drop-shadow-none">
120
+
<summary class="
121
+
flex gap-4 items-center justify-between
122
+
rounded-t-2xl md:rounded-t-sm cursor-pointer list-none p-4 md:h-12
123
+
text-white md:text-black md:dark:text-white
124
+
bg-green-600 dark:bg-green-600
125
+
md:bg-white md:dark:bg-gray-800
126
+
drop-shadow-sm
127
+
md:border-b md:border-x border-gray-200 dark:border-gray-700">
128
+
<h2 class="">Review Panel </h2>
129
+
<div class="flex items-center gap-2">
130
+
<span class="inline-flex items-center gap-2">
131
+
{{ $commentCount }} comment{{if ne $commentCount 1}}s{{end}}
132
+
</span>
133
+
<span class="before:content-['·'] before:select-none"></span>
134
+
<span>round <span class="font-mono">#{{ $pull.LastRoundNumber }}</span>
135
+
</span>
136
+
<span class="md:hidden inline">
137
+
<span class="inline group-open:hidden">{{ i "chevron-up" "size-4" }}</span>
138
+
<span class="hidden group-open:inline">{{ i "chevron-down" "size-4" }}</span>
139
+
</span>
140
+
</div>
141
+
</summary>
142
+
<div class="max-h-[60vh] md:max-h-[calc(100vh-3rem-3rem)] w-full flex flex-col-reverse gap-4 overflow-y-auto bg-slate-100 dark:bg-gray-900 md:bg-transparent">
143
+
{{ template "submissions" $root }}
144
+
</div>
145
+
</details>
268
146
</div>
269
147
{{ end }}
270
148
271
-
{{ define "cancel" }}
272
-
<button
273
-
class="btn text-red-500 dark:text-red-400 flex gap-2 items-center group"
274
-
hx-get="TODO"
275
-
hx-target="TODO"
276
-
hx-swap="outerHTML">
277
-
{{ i "x" "size-4" }}
278
-
cancel
279
-
</button>
149
+
{{ define "subsCheckbox" }}
150
+
<input type="checkbox" id="subsToggle" class="peer/subs hidden" checked/>
280
151
{{ end }}
281
152
282
-
{{ define "reply" }}
283
-
<button
284
-
id="TODO"
285
-
type="submit"
286
-
class="btn-create flex items-center gap-2 no-underline hover:no-underline">
287
-
{{ i "reply" "w-4 h-4 inline group-[.htmx-request]:hidden" }}
288
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
289
-
reply
290
-
</button>
153
+
{{ define "subsToggle" }}
154
+
<style>
155
+
/* Mobile: full width */
156
+
#subsToggle:checked ~ div div#subs {
157
+
width: 100%;
158
+
margin-left: 0;
159
+
}
160
+
161
+
/* Desktop: 25vw with left margin */
162
+
@media (min-width: 768px) {
163
+
#subsToggle:checked ~ div div#subs {
164
+
width: 25vw;
165
+
margin-left: 1rem;
166
+
}
167
+
/* Unchecked state */
168
+
#subsToggle:not(:checked) ~ div div#subs {
169
+
width: 0;
170
+
display: none;
171
+
margin-left: 0;
172
+
}
173
+
}
174
+
</style>
175
+
<label title="Toggle review panel" for="subsToggle" class="hidden md:inline-flex items-center justify-center rounded cursor-pointer p-2">
176
+
{{ i "message-square-more" "size-4" }}
177
+
</label>
291
178
{{ end }}
292
179
180
+
293
181
{{ define "submissions" }}
294
182
{{ $lastIdx := sub (len .Pull.Submissions) 1 }}
295
-
{{ $targetBranch := .Pull.TargetBranch }}
296
-
{{ $repoName := .RepoInfo.FullName }}
297
-
{{ range $idx, $item := .Pull.Submissions }}
298
-
{{ with $item }}
299
-
<details {{ if eq $idx $lastIdx }}open{{ end }}>
300
-
<summary id="round-#{{ .RoundNumber }}" class="list-none cursor-pointer">
301
-
<div class="flex flex-wrap gap-2 items-stretch">
302
-
<!-- round number -->
303
-
<div class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-3 py-2 dark:text-white">
304
-
<span class="flex items-center">{{ i "hash" "w-4 h-4" }}{{ .RoundNumber }}</span>
305
-
</div>
306
-
<!-- round summary -->
307
-
<div class="flex-1 rounded drop-shadow-sm bg-white dark:bg-gray-800 p-2 text-gray-500 dark:text-gray-400">
308
-
<span class="gap-1 flex items-center">
309
-
{{ $owner := resolve $.Pull.OwnerDid }}
310
-
{{ $re := "re" }}
311
-
{{ if eq .RoundNumber 0 }}
312
-
{{ $re = "" }}
313
-
{{ end }}
314
-
<span class="hidden md:inline">{{$re}}submitted</span>
315
-
by {{ template "user/fragments/picHandleLink" $.Pull.OwnerDid }}
316
-
<span class="select-none before:content-['\00B7']"></span>
317
-
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ .RoundNumber }}">{{ template "repo/fragments/shortTime" .Created }}</a>
318
-
<span class="select-none before:content-['·']"></span>
319
-
{{ $s := "s" }}
320
-
{{ if eq (len .Comments) 1 }}
321
-
{{ $s = "" }}
322
-
{{ end }}
323
-
{{ len .Comments }} comment{{$s}}
324
-
</span>
325
-
</div>
183
+
{{ range $ridx, $item := reverse .Pull.Submissions }}
184
+
{{ $idx := sub $lastIdx $ridx }}
185
+
{{ template "submission" (list $item $idx $lastIdx $) }}
186
+
{{ end }}
187
+
{{ end }}
326
188
327
-
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
328
-
hx-boost="true"
329
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}">
330
-
{{ i "file-diff" "w-4 h-4" }}
331
-
<span class="hidden md:inline">diff</span>
332
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
333
-
</a>
334
-
{{ if ne $idx 0 }}
335
-
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
336
-
hx-boost="true"
337
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}/interdiff">
338
-
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
339
-
<span class="hidden md:inline">interdiff</span>
340
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
341
-
</a>
342
-
{{ end }}
343
-
<span id="interdiff-error-{{.RoundNumber}}"></span>
344
-
</div>
345
-
</summary>
189
+
{{ define "submission" }}
190
+
{{ $item := index . 0 }}
191
+
{{ $idx := index . 1 }}
192
+
{{ $lastIdx := index . 2 }}
193
+
{{ $root := index . 3 }}
194
+
<div class="rounded border border-gray-200 dark:border-gray-700 w-full shadow-sm bg-gray-50 dark:bg-gray-800/50">
195
+
{{ template "submissionHeader" $ }}
196
+
{{ template "submissionComments" $ }}
346
197
347
-
{{ if .IsFormatPatch }}
348
-
{{ $patches := .AsFormatPatch }}
349
-
{{ $round := .RoundNumber }}
350
-
<details class="group py-2 md:ml-[3.5rem] text-gray-500 dark:text-gray-400 flex flex-col gap-2 relative text-sm">
351
-
<summary class="py-1 list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
352
-
{{ $s := "s" }}
353
-
{{ if eq (len $patches) 1 }}
354
-
{{ $s = "" }}
355
-
{{ end }}
356
-
<div class="group-open:hidden flex items-center gap-2 ml-2">
357
-
{{ i "chevrons-up-down" "w-4 h-4" }} expand {{ len $patches }} commit{{$s}}
358
-
</div>
359
-
<div class="hidden group-open:flex items-center gap-2 ml-2">
360
-
{{ i "chevrons-down-up" "w-4 h-4" }} hide {{ len $patches }} commit{{$s}}
361
-
</div>
362
-
</summary>
363
-
{{ range $patches }}
364
-
<div id="commit-{{.SHA}}" class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
365
-
<div class="flex items-center gap-2">
366
-
{{ i "git-commit-horizontal" "w-4 h-4" }}
367
-
<div class="text-sm text-gray-500 dark:text-gray-400">
368
-
<!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
369
-
{{ $fullRepo := "" }}
370
-
{{ if and $.Pull.IsForkBased $.Pull.PullSource.Repo }}
371
-
{{ $fullRepo = printf "%s/%s" $owner $.Pull.PullSource.Repo.Name }}
372
-
{{ else if $.Pull.IsBranchBased }}
373
-
{{ $fullRepo = $.RepoInfo.FullName }}
374
-
{{ end }}
198
+
{{ if eq $lastIdx $item.RoundNumber }}
199
+
{{ block "mergeStatus" $root }} {{ end }}
200
+
{{ block "resubmitStatus" $root }} {{ end }}
201
+
{{ end }}
375
202
376
-
<!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
377
-
{{ if $fullRepo }}
378
-
<a href="/{{ $fullRepo }}/commit/{{ .SHA }}" class="font-mono text-gray-500 dark:text-gray-400">{{ slice .SHA 0 8 }}</a>
379
-
{{ else }}
380
-
<span class="font-mono">{{ slice .SHA 0 8 }}</span>
381
-
{{ end }}
382
-
</div>
383
-
<div class="flex items-center">
384
-
<span>{{ .Title | description }}</span>
385
-
{{ if gt (len .Body) 0 }}
386
-
<button
387
-
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"
388
-
hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
389
-
>
390
-
{{ i "ellipsis" "w-3 h-3" }}
391
-
</button>
392
-
{{ end }}
393
-
</div>
394
-
</div>
395
-
{{ if gt (len .Body) 0 }}
396
-
<p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 text-sm pb-2">
397
-
{{ nl2br .Body }}
398
-
</p>
399
-
{{ end }}
400
-
</div>
401
-
{{ end }}
402
-
</details>
403
-
{{ end }}
203
+
{{ if $root.LoggedInUser }}
204
+
{{ template "repo/pulls/fragments/pullActions"
205
+
(dict
206
+
"LoggedInUser" $root.LoggedInUser
207
+
"Pull" $root.Pull
208
+
"RepoInfo" $root.RepoInfo
209
+
"RoundNumber" $item.RoundNumber
210
+
"MergeCheck" $root.MergeCheck
211
+
"ResubmitCheck" $root.ResubmitCheck
212
+
"BranchDeleteStatus" $root.BranchDeleteStatus
213
+
"Stack" $root.Stack) }}
214
+
{{ else }}
215
+
{{ template "loginPrompt" $ }}
216
+
{{ end }}
217
+
</div>
218
+
{{ end }}
404
219
220
+
{{ define "submissionHeader" }}
221
+
{{ $item := index . 0 }}
222
+
{{ $lastIdx := index . 2 }}
223
+
{{ $root := index . 3 }}
224
+
{{ $round := $item.RoundNumber }}
225
+
<div class="rounded px-6 pr-4 py-4 bg-white dark:bg-gray-800 flex gap-2 sticky top-0 z-20 border-b border-gray-200 dark:border-gray-700">
226
+
<!-- left column: just profile picture -->
227
+
<div class="flex-shrink-0">
228
+
<img
229
+
src="{{ tinyAvatar $root.Pull.OwnerDid }}"
230
+
alt=""
231
+
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
232
+
/>
233
+
</div>
234
+
<!-- right column -->
235
+
<div class="flex-1 min-w-0 flex flex-col gap-1">
236
+
{{ template "submissionInfo" $ }}
237
+
{{ template "submissionCommits" $ }}
238
+
{{ template "submissionPipeline" $ }}
239
+
{{ if eq $lastIdx $round }}
240
+
{{ block "mergeCheck" $root }} {{ end }}
241
+
{{ end }}
242
+
</div>
243
+
</div>
244
+
{{ end }}
405
245
406
-
<div class="md:pl-[3.5rem] flex flex-col gap-2 mt-2 relative">
407
-
{{ range $cidx, $c := .Comments }}
408
-
<div id="comment-{{$c.ID}}" class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-2 px-4 relative w-full">
409
-
{{ if gt $cidx 0 }}
410
-
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
411
-
{{ end }}
412
-
<div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
413
-
{{ template "user/fragments/picHandleLink" $c.OwnerDid }}
414
-
<span class="before:content-['·']"></span>
415
-
<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>
416
-
</div>
417
-
<div class="prose dark:prose-invert">
418
-
{{ $c.Body | markdown }}
419
-
</div>
420
-
</div>
421
-
{{ end }}
246
+
{{ define "submissionInfo" }}
247
+
{{ $item := index . 0 }}
248
+
{{ $idx := index . 1 }}
249
+
{{ $root := index . 3 }}
250
+
{{ $round := $item.RoundNumber }}
251
+
<div class="flex gap-2 items-center justify-between mb-1">
252
+
<span class="inline-flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
253
+
{{ resolve $root.Pull.OwnerDid }} submitted v{{ $round }}
254
+
<span class="select-none before:content-['\00B7']"></span>
255
+
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ $round }}">
256
+
{{ template "repo/fragments/shortTimeAgo" $item.Created }}
257
+
</a>
258
+
</span>
259
+
{{ if ne $idx 0 }}
260
+
<a class="btn-flat flex items-center gap-2 no-underline hover:no-underline text-sm"
261
+
hx-boost="true"
262
+
href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $round }}/interdiff">
263
+
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
264
+
interdiff
265
+
</a>
266
+
{{ end }}
267
+
</div>
268
+
{{ end }}
422
269
423
-
{{ block "pipelineStatus" (list $ .) }} {{ end }}
270
+
{{ define "submissionCommits" }}
271
+
{{ $item := index . 0 }}
272
+
{{ $root := index . 3 }}
273
+
{{ $round := $item.RoundNumber }}
274
+
{{ $patches := $item.AsFormatPatch }}
275
+
{{ if $patches }}
276
+
<details class="group/commit">
277
+
<summary class="list-none cursor-pointer flex items-center gap-2">
278
+
<span>{{ i "git-commit-horizontal" "w-4 h-4" }}</span>
279
+
{{ len $patches }} commit{{ if ne (len $patches) 1 }}s{{ end }}
280
+
<div class="text-sm text-gray-500 dark:text-gray-400">
281
+
<span class="group-open/commit:hidden inline">expand</span>
282
+
<span class="hidden group-open/commit:inline">collapse</span>
283
+
</div>
284
+
</summary>
285
+
{{ range $patches }}
286
+
{{ template "submissionCommit" (list . $item $root) }}
287
+
{{ end }}
288
+
</details>
289
+
{{ end }}
290
+
{{ end }}
424
291
425
-
{{ if eq $lastIdx .RoundNumber }}
426
-
{{ block "mergeStatus" $ }} {{ end }}
427
-
{{ block "resubmitStatus" $ }} {{ end }}
292
+
{{ define "submissionCommit" }}
293
+
{{ $patch := index . 0 }}
294
+
{{ $item := index . 1 }}
295
+
{{ $root := index . 2 }}
296
+
{{ $round := $item.RoundNumber }}
297
+
{{ with $patch }}
298
+
<div id="commit-{{.SHA}}" class="py-1 relative w-full md:max-w-3/5 md:w-fit flex flex-col text-gray-600 dark:text-gray-300">
299
+
<div class="flex items-baseline gap-2">
300
+
<div class="text-xs">
301
+
<!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
302
+
{{ $fullRepo := "" }}
303
+
{{ if and $root.Pull.IsForkBased $root.Pull.PullSource.Repo }}
304
+
{{ $fullRepo = printf "%s/%s" $root.Pull.OwnerDid $root.Pull.PullSource.Repo.Name }}
305
+
{{ else if $root.Pull.IsBranchBased }}
306
+
{{ $fullRepo = $root.RepoInfo.FullName }}
428
307
{{ end }}
429
308
430
-
{{ if $.LoggedInUser }}
431
-
{{ template "repo/pulls/fragments/pullActions"
432
-
(dict
433
-
"LoggedInUser" $.LoggedInUser
434
-
"Pull" $.Pull
435
-
"RepoInfo" $.RepoInfo
436
-
"RoundNumber" .RoundNumber
437
-
"MergeCheck" $.MergeCheck
438
-
"ResubmitCheck" $.ResubmitCheck
439
-
"BranchDeleteStatus" $.BranchDeleteStatus
440
-
"Stack" $.Stack) }}
309
+
<!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
310
+
{{ if $fullRepo }}
311
+
<a href="/{{ $fullRepo }}/commit/{{ .SHA }}" class="font-mono text-gray-600 dark:text-gray-300">{{ slice .SHA 0 8 }}</a>
441
312
{{ else }}
442
-
<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 w-fit">
443
-
<a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
444
-
sign up
445
-
</a>
446
-
<span class="text-gray-500 dark:text-gray-400">or</span>
447
-
<a href="/login" class="underline">login</a>
448
-
to add to the discussion
449
-
</div>
313
+
<span class="font-mono">{{ slice .SHA 0 8 }}</span>
450
314
{{ end }}
451
315
</div>
316
+
317
+
<div>
318
+
<span>{{ .Title | description }}</span>
319
+
{{ if gt (len .Body) 0 }}
320
+
<button
321
+
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"
322
+
hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
323
+
>
324
+
{{ i "ellipsis" "w-3 h-3" }}
325
+
</button>
326
+
{{ end }}
327
+
{{ if gt (len .Body) 0 }}
328
+
<p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 pb-2">{{ nl2br .Body }}</p>
329
+
{{ end }}
330
+
</div>
331
+
</div>
332
+
</div>
333
+
{{ end }}
334
+
{{ end }}
335
+
336
+
{{ define "mergeCheck" }}
337
+
{{ $isOpen := .Pull.State.IsOpen }}
338
+
{{ if and $isOpen .MergeCheck .MergeCheck.Error }}
339
+
<div class="flex items-center gap-2">
340
+
{{ i "triangle-alert" "w-4 h-4 text-red-600 dark:text-red-500" }}
341
+
{{ .MergeCheck.Error }}
342
+
</div>
343
+
{{ else if and $isOpen .MergeCheck .MergeCheck.IsConflicted }}
344
+
<details class="group/conflict">
345
+
<summary class="flex items-center justify-between cursor-pointer list-none">
346
+
<div class="flex items-center gap-2 ">
347
+
{{ i "triangle-alert" "text-red-600 dark:text-red-500 w-4 h-4" }}
348
+
<span class="font-medium">merge conflicts detected</span>
349
+
<div class="text-sm text-gray-500 dark:text-gray-400">
350
+
<span class="group-open/conflict:hidden inline">expand</span>
351
+
<span class="hidden group-open/conflict:inline">collapse</span>
352
+
</div>
353
+
</div>
354
+
</summary>
355
+
{{ if gt (len .MergeCheck.Conflicts) 0 }}
356
+
<ul class="space-y-1 mt-2 overflow-x-auto">
357
+
{{ range .MergeCheck.Conflicts }}
358
+
{{ if .Filename }}
359
+
<li class="flex items-center whitespace-nowrap">
360
+
{{ i "file-warning" "inline-flex w-4 h-4 mr-1.5 text-red-600 dark:text-red-500 flex-shrink-0" }}
361
+
<span class="font-mono">{{ .Filename }}</span>
362
+
</li>
363
+
{{ else if .Reason }}
364
+
<li class="flex items-center whitespace-nowrap">
365
+
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
366
+
<span>{{.Reason}}</span>
367
+
</li>
368
+
{{ end }}
369
+
{{ end }}
370
+
</ul>
371
+
{{ end }}
452
372
</details>
453
-
{{ end }}
373
+
{{ else if and $isOpen .MergeCheck }}
374
+
<div class="flex items-center gap-2">
375
+
{{ i "check" "w-4 h-4 text-green-600 dark:text-green-500" }}
376
+
<span>no conflicts, ready to merge</span>
377
+
</div>
454
378
{{ end }}
455
379
{{ end }}
456
380
···
478
402
<span class="font-medium">This pull has been deleted (possibly by jj abandon or jj squash)</span>
479
403
</div>
480
404
</div>
481
-
{{ else if and .MergeCheck .MergeCheck.Error }}
482
-
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative">
483
-
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
484
-
{{ i "triangle-alert" "w-4 h-4" }}
485
-
<span class="font-medium">{{ .MergeCheck.Error }}</span>
486
-
</div>
487
-
</div>
488
-
{{ else if and .MergeCheck .MergeCheck.IsConflicted }}
489
-
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative">
490
-
<details class="text-red-500 dark:text-red-300 group">
491
-
<summary class="flex items-center justify-between cursor-pointer list-none">
492
-
<div class="flex items-center gap-2 ">
493
-
{{ i "triangle-alert" "w-4 h-4" }}
494
-
<span class="font-medium">merge conflicts detected</span>
495
-
</div>
496
-
<div>
497
-
<span class="group-open:hidden inline">{{ i "chevrons-up-down" "w-4 h-4" }}</span>
498
-
<span class="hidden group-open:inline">{{ i "chevrons-down-up" "w-4 h-4" }}</span>
499
-
</div>
500
-
</summary>
501
-
{{ if gt (len .MergeCheck.Conflicts) 0 }}
502
-
<ul class="space-y-1 mt-2">
503
-
{{ range .MergeCheck.Conflicts }}
504
-
{{ if .Filename }}
505
-
<li class="flex items-center">
506
-
{{ i "file-warning" "inline-flex w-4 h-4 mr-1.5 text-red-500 dark:text-red-300 flex-shrink-0" }}
507
-
<span class="font-mono" style="word-break: keep-all; overflow-wrap: break-word;">{{ .Filename }}</span>
508
-
</li>
509
-
{{ else if .Reason }}
510
-
<li class="flex items-center">
511
-
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
512
-
<span>{{.Reason}}</span>
513
-
</li>
514
-
{{ end }}
515
-
{{ end }}
516
-
</ul>
517
-
{{ end }}
518
-
</details>
519
-
</div>
520
-
{{ else if .MergeCheck }}
521
-
<div class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative">
522
-
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
523
-
{{ i "circle-check-big" "w-4 h-4" }}
524
-
<span class="font-medium">no conflicts, ready to merge</span>
525
-
</div>
526
-
</div>
527
405
{{ end }}
528
406
{{ end }}
529
407
···
538
416
{{ end }}
539
417
{{ end }}
540
418
541
-
{{ define "pipelineStatus" }}
542
-
{{ $root := index . 0 }}
543
-
{{ $submission := index . 1 }}
544
-
{{ $pipeline := index $root.Pipelines $submission.SourceRev }}
419
+
{{ define "submissionPipeline" }}
420
+
{{ $item := index . 0 }}
421
+
{{ $root := index . 3 }}
422
+
{{ $pipeline := index $root.Pipelines $item.SourceRev }}
545
423
{{ with $pipeline }}
546
424
{{ $id := .Id }}
547
425
{{ if .Statuses }}
548
-
<span>Workflows:</span>
549
-
<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">
550
-
{{ range $name, $all := .Statuses }}
551
-
<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">
552
-
<div
553
-
class="flex gap-2 items-center justify-between p-2">
554
-
{{ $lastStatus := $all.Latest }}
555
-
{{ $kind := $lastStatus.Status.String }}
426
+
<details class="group/pipeline">
427
+
<summary class="cursor-pointer list-none flex items-center gap-2">
428
+
{{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" false) }}
429
+
<div class="text-sm text-gray-500 dark:text-gray-400">
430
+
<span class="group-open/pipeline:hidden inline">expand</span>
431
+
<span class="hidden group-open/pipeline:inline">collapse</span>
432
+
</div>
433
+
</summary>
434
+
<div class="my-2 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">
435
+
{{ range $name, $all := .Statuses }}
436
+
<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">
437
+
<div
438
+
class="flex gap-2 items-center justify-between p-2">
439
+
{{ $lastStatus := $all.Latest }}
440
+
{{ $kind := $lastStatus.Status.String }}
556
441
557
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
558
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
559
-
{{ $name }}
560
-
</div>
561
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
562
-
<span class="font-bold">{{ $kind }}</span>
563
-
{{ if .TimeTaken }}
564
-
{{ template "repo/fragments/duration" .TimeTaken }}
565
-
{{ else }}
566
-
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
567
-
{{ end }}
568
-
</div>
442
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
443
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
444
+
{{ $name }}
445
+
</div>
446
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
447
+
<span class="font-bold">{{ $kind }}</span>
448
+
{{ if .TimeTaken }}
449
+
{{ template "repo/fragments/duration" .TimeTaken }}
450
+
{{ else }}
451
+
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
452
+
{{ end }}
453
+
</div>
454
+
</div>
455
+
</a>
456
+
{{ end }}
569
457
</div>
458
+
</details>
459
+
{{ end }}
460
+
{{ end }}
461
+
{{ end }}
462
+
463
+
{{ define "submissionComments" }}
464
+
{{ $item := index . 0 }}
465
+
<div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700">
466
+
{{ range $item.Comments }}
467
+
{{ template "submissionComment" . }}
468
+
{{ end }}
469
+
</div>
470
+
{{ end }}
471
+
472
+
{{ define "submissionComment" }}
473
+
<div id="comment-{{.ID}}" class="flex gap-2 -ml-4 py-4 w-full mx-auto">
474
+
<!-- left column: profile picture -->
475
+
<div class="flex-shrink-0">
476
+
<img
477
+
src="{{ tinyAvatar .OwnerDid }}"
478
+
alt=""
479
+
class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
480
+
/>
481
+
</div>
482
+
<!-- right column: name and body in two rows -->
483
+
<div class="flex-1 min-w-0">
484
+
<!-- Row 1: Author and timestamp -->
485
+
<div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
486
+
<span>{{ resolve .OwnerDid }}</span>
487
+
<span class="before:content-['·']"></span>
488
+
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="#comment-{{.ID}}">
489
+
{{ template "repo/fragments/time" .Created }}
570
490
</a>
571
-
{{ end }}
491
+
</div>
492
+
<!-- Row 2: Body text -->
493
+
<div class="prose dark:prose-invert mt-1">
494
+
{{ .Body | markdown }}
572
495
</div>
573
-
{{ end }}
574
-
{{ end }}
496
+
</div>
497
+
</div>
498
+
{{ end }}
499
+
500
+
{{ define "loginPrompt" }}
501
+
<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">
502
+
<a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
503
+
sign up
504
+
</a>
505
+
<span class="text-gray-500 dark:text-gray-400">or</span>
506
+
<a href="/login" class="underline">login</a>
507
+
to add to the discussion
508
+
</div>
575
509
{{ end }}
+3
-12
appview/pages/templates/repo/pulls/pulls.html
+3
-12
appview/pages/templates/repo/pulls/pulls.html
···
112
112
{{ template "repo/fragments/time" .Created }}
113
113
</span>
114
114
115
-
116
-
{{ $latestRound := .LastRoundNumber }}
117
-
{{ $lastSubmission := index .Submissions $latestRound }}
118
-
119
115
<span class="before:content-['·']">
120
-
{{ $commentCount := len $lastSubmission.Comments }}
121
-
{{ $s := "s" }}
122
-
{{ if eq $commentCount 1 }}
123
-
{{ $s = "" }}
124
-
{{ end }}
125
-
126
-
{{ len $lastSubmission.Comments}} comment{{$s}}
116
+
{{ $commentCount := .TotalComments }}
117
+
{{ $commentCount }} comment{{ if ne $commentCount 1 }}s{{ end }}
127
118
</span>
128
119
129
120
<span class="before:content-['·']">
···
136
127
{{ $pipeline := index $.Pipelines .LatestSha }}
137
128
{{ if and $pipeline $pipeline.Id }}
138
129
<span class="before:content-['·']"></span>
139
-
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
130
+
{{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" true) }}
140
131
{{ end }}
141
132
142
133
{{ $state := .Labels }}
+2
-2
appview/pulls/pulls.go
+2
-2
appview/pulls/pulls.go
···
528
528
529
529
interdiff := patchutil.Interdiff(previousPatch, currentPatch)
530
530
531
-
s.pages.RepoPullInterdiffPage(w, pages.RepoPullInterdiffParams{
531
+
fmt.Println(s.pages.RepoPullInterdiffPage(w, pages.RepoPullInterdiffParams{
532
532
LoggedInUser: s.oauth.GetUser(r),
533
533
RepoInfo: s.repoResolver.GetRepoInfo(r, user),
534
534
Pull: pull,
535
535
Round: roundIdInt,
536
536
Interdiff: interdiff,
537
537
DiffOpts: diffOpts,
538
-
})
538
+
}))
539
539
}
540
540
541
541
func (s *Pulls) RepoPullPatchRaw(w http.ResponseWriter, r *http.Request) {
+2
-2
spindle/models/models.go
+2
-2
spindle/models/models.go
+3
-3
types/diff.go
+3
-3
types/diff.go
···
32
32
FilesChanged int
33
33
}
34
34
35
-
func (d *Diff) Stats() DiffStat {
35
+
func (d Diff) Stats() DiffStat {
36
36
var stats DiffStat
37
37
for _, f := range d.TextFragments {
38
38
stats.Insertions += f.LinesAdded
···
75
75
}
76
76
77
77
// used by html elements as a unique ID for hrefs
78
-
func (d *Diff) Id() string {
78
+
func (d Diff) Id() string {
79
79
if d.IsDelete {
80
80
return d.Name.Old
81
81
}
82
82
return d.Name.New
83
83
}
84
84
85
-
func (d *Diff) Split() *SplitDiff {
85
+
func (d Diff) Split() *SplitDiff {
86
86
fragments := make([]SplitFragment, len(d.TextFragments))
87
87
for i, fragment := range d.TextFragments {
88
88
leftLines, rightLines := SeparateLines(&fragment)