forked from
tangled.org/core
Monorepo for Tangled
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: fit-content; max-width: 15vw; margin-right: 1rem; }
7 #filesToggle:not(:checked) ~ div div#files { width: 0; display: none; 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 {{ $root := "" }}
18 {{ if gt (len .) 2 }}
19 {{ $root = index . 2 }}
20 {{ end }}
21
22 {{ block "filesCheckbox" $ }} {{ end }}
23 {{ block "subsCheckbox" $ }} {{ end }}
24
25 <!-- top bar -->
26 <div class="sticky top-0 z-30 flex items-center gap-2 col-span-full h-12 p-2 {{ if $root }}mt-4{{ end }}">
27 <!-- left panel toggle -->
28 {{ template "filesToggle" . }}
29
30 <!-- stats -->
31 {{ $stat := $diff.Stats }}
32 {{ $count := len $diff.ChangedFiles }}
33 {{ template "repo/fragments/diffStatPill" $stat }}
34 <span class="text-xs text-gray-600 dark:text-gray-400">{{ $count }} changed file{{ if ne $count 1 }}s{{ end }}</span>
35
36 {{ if $root }}
37 {{ if $root.IsInterdiff }}
38 <!-- interdiff indicator -->
39 <div class="flex items-center gap-2 before:content-['|'] before:text-gray-300 dark:before:text-gray-600 before:mr-2">
40 <span class="text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide">Interdiff</span>
41 <a
42 href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ sub $root.ActiveRound 1 }}"
43 class="px-2 py-0.5 bg-white dark:bg-gray-700 rounded font-mono text-xs hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-300 dark:border-gray-600"
44 >
45 #{{ sub $root.ActiveRound 1 }}
46 </a>
47 <span class="text-gray-400 text-xs">→</span>
48 <a
49 href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $root.ActiveRound }}"
50 class="px-2 py-0.5 bg-white dark:bg-gray-700 rounded font-mono text-xs hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-300 dark:border-gray-600"
51 >
52 #{{ $root.ActiveRound }}
53 </a>
54 </div>
55 {{ else if ne $root.ActiveRound nil }}
56 <!-- diff round indicator -->
57 <div class="flex items-center gap-2 before:content-['|'] before:text-gray-300 dark:before:text-gray-600 before:mr-2">
58 <span class="text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide">Diff</span>
59 <span class="px-2 py-0.5 bg-white dark:bg-gray-700 rounded font-mono text-xs border border-gray-300 dark:border-gray-600">
60 <span class="hidden md:inline">round </span>#{{ $root.ActiveRound }}
61 </span>
62 </div>
63 {{ end }}
64 {{ end }}
65
66 <!-- spacer -->
67 <div class="flex-grow"></div>
68
69 <!-- collapse diffs -->
70 {{ template "collapseToggle" }}
71
72 <!-- diff options -->
73 <div class="hidden md:block">
74 {{ template "repo/fragments/diffOpts" $opts }}
75 </div>
76
77 <!-- right panel toggle -->
78 {{ block "subsToggle" $ }} {{ end }}
79 </div>
80
81{{ end }}
82
83{{ define "diffLayout" }}
84 {{ $diff := index . 0 }}
85 {{ $opts := index . 1 }}
86
87 <div class="flex col-span-full flex-grow">
88 <!-- left panel -->
89 <div id="files" class="w-0 hidden md:block overflow-hidden sticky top-12 max-h-screen overflow-y-auto pb-12">
90 <section class="overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto min-h-full rounded bg-white dark:bg-gray-800 drop-shadow-sm">
91 {{ template "repo/fragments/fileTree" $diff.FileTree }}
92 </section>
93 </div>
94
95 <!-- main content -->
96 <div class="flex-1 min-w-0 sticky top-12 pb-12">
97 {{ template "diffFiles" (list $diff $opts) }}
98 </div>
99
100 </div>
101{{ end }}
102
103{{ define "diffFiles" }}
104 {{ $diff := index . 0 }}
105 {{ $opts := index . 1 }}
106 {{ $files := $diff.ChangedFiles }}
107 {{ $isSplit := $opts.Split }}
108 <div class="flex flex-col gap-4">
109 {{ if eq (len $files) 0 }}
110 <div class="text-center text-gray-500 dark:text-gray-400 py-8">
111 <p>No differences found between the selected revisions.</p>
112 </div>
113 {{ else }}
114 {{ range $idx, $file := $files }}
115 {{ template "diffFile" (list $idx $file $isSplit) }}
116 {{ end }}
117 {{ end }}
118 </div>
119{{ end }}
120
121{{ define "diffFile" }}
122 {{ $idx := index . 0 }}
123 {{ $file := index . 1 }}
124 {{ $isSplit := index . 2 }}
125 {{ with $file }}
126 <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 }}">
127 <summary class="list-none cursor-pointer sticky top-12 group-open:border-b border-gray-200 dark:border-gray-700">
128 <div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
129 <div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
130 <span class="group-open:hidden inline">{{ i "chevron-right" "w-4 h-4" }}</span>
131 <span class="hidden group-open:inline">{{ i "chevron-down" "w-4 h-4" }}</span>
132 {{ template "repo/fragments/diffStatPill" .Stats }}
133
134 <div class="flex gap-2 items-center overflow-x-auto">
135 {{ $n := .Names }}
136 {{ if and $n.New $n.Old (ne $n.New $n.Old)}}
137 {{ $n.Old }} {{ i "arrow-right" "w-4 h-4" }} {{ $n.New }}
138 {{ else if $n.New }}
139 {{ $n.New }}
140 {{ else }}
141 {{ $n.Old }}
142 {{ end }}
143 </div>
144 </div>
145 </div>
146 </summary>
147
148 <div class="transition-all duration-700 ease-in-out">
149 {{ $reason := .CanRender }}
150 {{ if $reason }}
151 <p class="text-center text-gray-400 dark:text-gray-500 p-4">{{ $reason }}</p>
152 {{ else }}
153 {{ if $isSplit }}
154 {{- template "repo/fragments/splitDiff" .Split -}}
155 {{ else }}
156 {{- template "repo/fragments/unifiedDiff" . -}}
157 {{ end }}
158 {{- end -}}
159 </div>
160 </details>
161 {{ end }}
162{{ end }}
163
164{{ define "filesCheckbox" }}
165 <input type="checkbox" id="filesToggle" class="peer/files hidden" checked/>
166{{ end }}
167
168{{ define "filesToggle" }}
169 <label title="Toggle filetree panel" for="filesToggle" class="hidden md:inline-flex items-center justify-center rounded cursor-pointer text-normal font-normal normalcase">
170 <span class="show-text">{{ i "panel-left-open" "size-4" }}</span>
171 <span class="hide-text">{{ i "panel-left-close" "size-4" }}</span>
172 </label>
173{{ end }}
174
175{{ define "collapseToggle" }}
176 <label
177 title="Expand/Collapse diffs"
178 for="collapseToggle"
179 class="btn font-normal normal-case p-2"
180 >
181 <input type="checkbox" id="collapseToggle" class="peer/collapse hidden" checked/>
182 <span class="peer-checked/collapse:hidden inline-flex items-center gap-2">
183 {{ i "fold-vertical" "w-4 h-4" }}
184 <span class="hidden md:inline">expand all</span>
185 </span>
186 <span class="peer-checked/collapse:inline-flex hidden flex items-center gap-2">
187 {{ i "unfold-vertical" "w-4 h-4" }}
188 <span class="hidden md:inline">collapse all</span>
189 </span>
190 </label>
191 <script>
192 document.addEventListener('DOMContentLoaded', function() {
193 const checkbox = document.getElementById('collapseToggle');
194 const details = document.querySelectorAll('details[id^="file-"]');
195
196 checkbox.addEventListener('change', function() {
197 details.forEach(detail => {
198 detail.open = checkbox.checked;
199 });
200 });
201
202 details.forEach(detail => {
203 detail.addEventListener('toggle', function() {
204 const allOpen = Array.from(details).every(d => d.open);
205 const allClosed = Array.from(details).every(d => !d.open);
206
207 if (allOpen) {
208 checkbox.checked = true;
209 } else if (allClosed) {
210 checkbox.checked = false;
211 }
212 });
213 });
214 });
215 </script>
216{{ end }}