forked from tangled.org/core
this repo has no description

appview: add stats and line-nr links to diffs

drive-by fix: style the separator between pull submissions

authored by oppi.li and committed by Tangled 48cbc686 438f94f1

Changed files
+83 -57
appview
types
+59 -16
appview/pages/templates/fragments/diff.html
··· 8 {{ $this := $commit.This }} 9 {{ $parent := $commit.Parent }} 10 11 {{ $last := sub (len $diff) 1 }} 12 {{ range $idx, $hunk := $diff }} 13 {{ with $hunk }} ··· 32 {{ else }} 33 <span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">MODIFIED</span> 34 {{ end }} 35 36 {{ if .IsDelete }} 37 <a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}> ··· 72 73 <div class="transition-all duration-700 ease-in-out"> 74 {{ if .IsDelete }} 75 - <p class="text-center text-gray-400 dark:text-gray-500 p-4"> 76 - This file has been deleted in this commit. 77 - </p> 78 {{ else }} 79 - {{ if .IsBinary }} 80 - <p class="text-center text-gray-400 dark:text-gray-500 p-4"> 81 - This is a binary file and will not be displayed. 82 - </p> 83 - {{ else }} 84 <pre class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 85 {{- $oldStart := .OldPosition -}} 86 {{- $newStart := .NewPosition -}} 87 - {{- $lineNrStyle := "min-w-[3rem] flex-shrink-0 select-none text-right" -}} 88 - {{- $lineNrSepStyle1 := "text-gray-400 dark:text-gray-500 bg-white dark:bg-gray-800" -}} 89 - {{- $lineNrSepStyle2 := "text-gray-400 dark:text-gray-500 bg-white dark:bg-gray-800 pr-2" -}} 90 {{- range .Lines -}} 91 {{- if eq .Op.String "+" -}} 92 <div class="bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 flex min-w-full items-center"> 93 <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div> 94 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}">{{ $newStart }}</div> 95 <div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div> 96 <div class="px-2">{{ .Line }}</div> 97 </div> ··· 99 {{- end -}} 100 {{- if eq .Op.String "-" -}} 101 <div class="bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 flex min-w-full items-center"> 102 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}">{{ $oldStart }}</div> 103 <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div> 104 <div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div> 105 <div class="px-2">{{ .Line }}</div> ··· 108 {{- end -}} 109 {{- if eq .Op.String " " -}} 110 <div class="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 flex min-w-full items-center"> 111 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}">{{ $oldStart }}</div> 112 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}">{{ $newStart }}</div> 113 <div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div> 114 <div class="px-2">{{ .Line }}</div> 115 </div> ··· 119 {{- end -}} 120 {{- end -}}</div></div></pre> 121 {{- end -}} 122 - {{ end }} 123 </div> 124 125 </details> ··· 130 {{ end }} 131 {{ end }} 132 {{ end }}
··· 8 {{ $this := $commit.This }} 9 {{ $parent := $commit.Parent }} 10 11 + <section class="mt-6 p-6 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm"> 12 + <div class="diff-stat"> 13 + <div class="flex gap-2 items-center"> 14 + <strong class="text-sm uppercase dark:text-gray-200">Changed files</strong> 15 + {{ block "statPill" $stat }} {{ end }} 16 + </div> 17 + <div class="overflow-x-auto"> 18 + {{ range $diff }} 19 + <ul class="dark:text-gray-200"> 20 + {{ if .IsDelete }} 21 + <li><a href="#file-{{ .Name.Old }}" class="dark:hover:text-gray-300">{{ .Name.Old }}</a></li> 22 + {{ else }} 23 + <li><a href="#file-{{ .Name.New }}" class="dark:hover:text-gray-300">{{ .Name.New }}</a></li> 24 + {{ end }} 25 + </ul> 26 + {{ end }} 27 + </div> 28 + </div> 29 + </section> 30 + 31 {{ $last := sub (len $diff) 1 }} 32 {{ range $idx, $hunk := $diff }} 33 {{ with $hunk }} ··· 52 {{ else }} 53 <span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">MODIFIED</span> 54 {{ end }} 55 + 56 + {{ block "statPill" .Stats }} {{ end }} 57 58 {{ if .IsDelete }} 59 <a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}> ··· 94 95 <div class="transition-all duration-700 ease-in-out"> 96 {{ if .IsDelete }} 97 + <p class="text-center text-gray-400 dark:text-gray-500 p-4"> 98 + This file has been deleted. 99 + </p> 100 + {{ else if .IsCopy }} 101 + <p class="text-center text-gray-400 dark:text-gray-500 p-4"> 102 + This file has been copied. 103 + </p> 104 + {{ else if .IsRename }} 105 + <p class="text-center text-gray-400 dark:text-gray-500 p-4"> 106 + This file has been renamed. 107 + </p> 108 + {{ else if .IsBinary }} 109 + <p class="text-center text-gray-400 dark:text-gray-500 p-4"> 110 + This is a binary file and will not be displayed. 111 + </p> 112 {{ else }} 113 + {{ $name := .Name.New }} 114 <pre class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 115 {{- $oldStart := .OldPosition -}} 116 {{- $newStart := .NewPosition -}} 117 + {{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 scroll-mt-10 target:border target:border-amber-500 target:rounded " -}} 118 + {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} 119 + {{- $lineNrSepStyle1 := "" -}} 120 + {{- $lineNrSepStyle2 := "pr-2" -}} 121 {{- range .Lines -}} 122 {{- if eq .Op.String "+" -}} 123 <div class="bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 flex min-w-full items-center"> 124 <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div> 125 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}" id="{{$name}}-N{{$newStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div> 126 <div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div> 127 <div class="px-2">{{ .Line }}</div> 128 </div> ··· 130 {{- end -}} 131 {{- if eq .Op.String "-" -}} 132 <div class="bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 flex min-w-full items-center"> 133 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}" id="{{$name}}-O{{$oldStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div> 134 <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div> 135 <div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div> 136 <div class="px-2">{{ .Line }}</div> ··· 139 {{- end -}} 140 {{- if eq .Op.String " " -}} 141 <div class="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 flex min-w-full items-center"> 142 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}" id="{{$name}}-O{{$oldStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div> 143 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}" id="{{$name}}-N{{$newStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div> 144 <div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div> 145 <div class="px-2">{{ .Line }}</div> 146 </div> ··· 150 {{- end -}} 151 {{- end -}}</div></div></pre> 152 {{- end -}} 153 </div> 154 155 </details> ··· 160 {{ end }} 161 {{ end }} 162 {{ end }} 163 + 164 + {{ define "statPill" }} 165 + <div class="flex items-center font-mono text-sm"> 166 + {{ if and .Insertions .Deletions }} 167 + <span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 168 + <span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 169 + {{ else if .Insertions }} 170 + <span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 171 + {{ else if .Deletions }} 172 + <span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 173 + {{ end }} 174 + </div> 175 + {{ end }}
+1 -20
appview/pages/templates/repo/commit.html
··· 4 5 {{ $repo := .RepoInfo.FullName }} 6 {{ $commit := .Diff.Commit }} 7 - {{ $stat := .Diff.Stat }} 8 - {{ $diff := .Diff.Diff }} 9 10 <section class="commit dark:text-white"> 11 <div id="commit-message"> ··· 13 <div> 14 <p class="pb-2">{{ index $messageParts 0 }}</p> 15 {{ if gt (len $messageParts) 1 }} 16 - <p class="mt-1 cursor-text pb-2 text-sm">{{ nl2br (unwrapText (index $messageParts 1)) }}</p> 17 {{ end }} 18 </div> 19 </div> ··· 29 {{ end }} 30 <span class="px-1 select-none before:content-['\00B7']"></span> 31 {{ timeFmt $commit.Author.When }} 32 - <span class="px-1 select-none before:content-['\00B7']"></span> 33 - <span>{{ $stat.FilesChanged }}</span> files <span class="font-mono">(+{{ $stat.Insertions }}, -{{ $stat.Deletions }})</span> 34 <span class="px-1 select-none before:content-['\00B7']"></span> 35 </p> 36 ··· 43 </p> 44 </div> 45 46 - <div class="diff-stat"> 47 - <br> 48 - <strong class="text-sm uppercase mb-4 dark:text-gray-200">Changed files</strong> 49 - <div class="overflow-x-auto"> 50 - {{ range $diff }} 51 - <ul class="dark:text-gray-200"> 52 - {{ if .IsDelete }} 53 - <li><a href="#file-{{ .Name.Old }}" class="dark:hover:text-gray-300">{{ .Name.Old }}</a></li> 54 - {{ else }} 55 - <li><a href="#file-{{ .Name.New }}" class="dark:hover:text-gray-300">{{ .Name.New }}</a></li> 56 - {{ end }} 57 - </ul> 58 - {{ end }} 59 - </div> 60 - </div> 61 </section> 62 63 {{end}}
··· 4 5 {{ $repo := .RepoInfo.FullName }} 6 {{ $commit := .Diff.Commit }} 7 8 <section class="commit dark:text-white"> 9 <div id="commit-message"> ··· 11 <div> 12 <p class="pb-2">{{ index $messageParts 0 }}</p> 13 {{ if gt (len $messageParts) 1 }} 14 + <p class="mt-1 cursor-text pb-2 text-sm">{{ nl2br (index $messageParts 1) }}</p> 15 {{ end }} 16 </div> 17 </div> ··· 27 {{ end }} 28 <span class="px-1 select-none before:content-['\00B7']"></span> 29 {{ timeFmt $commit.Author.When }} 30 <span class="px-1 select-none before:content-['\00B7']"></span> 31 </p> 32 ··· 39 </p> 40 </div> 41 42 </section> 43 44 {{end}}
+1 -1
appview/pages/templates/repo/index.html
··· 146 <p 147 class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300" 148 > 149 - {{ nl2br (unwrapText (index $messageParts 1)) }} 150 </p> 151 {{ end }} 152 </div>
··· 146 <p 147 class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300" 148 > 149 + {{ nl2br (index $messageParts 1) }} 150 </p> 151 {{ end }} 152 </div>
+1 -1
appview/pages/templates/repo/issues/issues.html
··· 4 <div class="flex justify-between items-center"> 5 <p> 6 filtering 7 - <select class="border px-1 bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value"> 8 <option value="open" {{ if .FilteringByOpen }}selected{{ end }}>open ({{ .RepoInfo.Stats.IssueCount.Open }})</option> 9 <option value="closed" {{ if not .FilteringByOpen }}selected{{ end }}>closed ({{ .RepoInfo.Stats.IssueCount.Closed }})</option> 10 </select>
··· 4 <div class="flex justify-between items-center"> 5 <p> 6 filtering 7 + <select class="border p-1 bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value"> 8 <option value="open" {{ if .FilteringByOpen }}selected{{ end }}>open ({{ .RepoInfo.Stats.IssueCount.Open }})</option> 9 <option value="closed" {{ if not .FilteringByOpen }}selected{{ end }}>closed ({{ .RepoInfo.Stats.IssueCount.Closed }})</option> 10 </select>
+1 -1
appview/pages/templates/repo/log.html
··· 83 <p 84 class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300" 85 > 86 - {{ nl2br (unwrapText (index $messageParts 1)) }} 87 </p> 88 {{ end }} 89 </div>
··· 83 <p 84 class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300" 85 > 86 + {{ nl2br (index $messageParts 1) }} 87 </p> 88 {{ end }} 89 </div>
-13
appview/pages/templates/repo/pulls/patch.html
··· 69 {{ end }} 70 </section> 71 72 - <div id="diff-stat"> 73 - <br> 74 - <strong class="text-sm uppercase mb-4">Changed files</strong> 75 - {{ range .Diff.Diff }} 76 - <ul> 77 - {{ if .IsDelete }} 78 - <li><a href="#file-{{ .Name.Old }}">{{ .Name.Old }}</a></li> 79 - {{ else }} 80 - <li><a href="#file-{{ .Name.New }}">{{ .Name.New }}</a></li> 81 - {{ end }} 82 - </ul> 83 - {{ end }} 84 - </div> 85 </div> 86 87 <section>
··· 69 {{ end }} 70 </section> 71 72 </div> 73 74 <section>
+1 -1
appview/pages/templates/repo/pulls/pull.html
··· 156 {{ end }} 157 </div> 158 </details> 159 - <hr class="md:hidden"/> 160 {{ end }} 161 {{ end }} 162 {{ end }}
··· 156 {{ end }} 157 </div> 158 </details> 159 + <hr class="md:hidden border-t border-gray-300 dark:border-gray-600"/> 160 {{ end }} 161 {{ end }} 162 {{ end }}
+1 -1
appview/pages/templates/repo/pulls/pulls.html
··· 5 <p class="dark:text-white"> 6 filtering 7 <select 8 - class="border px-1 bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-600 dark:text-white" 9 onchange="window.location.href = '/{{ .RepoInfo.FullName }}/pulls?state=' + this.value" 10 > 11 <option value="open" {{ if .FilteringBy.IsOpen }}selected{{ end }}>
··· 5 <p class="dark:text-white"> 6 filtering 7 <select 8 + class="border p-1 bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-600 dark:text-white" 9 onchange="window.location.href = '/{{ .RepoInfo.FullName }}/pulls?state=' + this.value" 10 > 11 <option value="open" {{ if .FilteringBy.IsOpen }}selected{{ end }}>
+4 -3
appview/pages/templates/repo/tree.html
··· 28 {{ $stats := .TreeStats }} 29 30 <span>at <a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">{{ $.Ref }}</a></span> 31 - <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 32 {{ if eq $stats.NumFolders 1 }} 33 - <span>{{ $stats.NumFolders }} folder</span> 34 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 35 {{ else if gt $stats.NumFolders 1 }} 36 <span>{{ $stats.NumFolders }} folders</span> 37 - <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 38 {{ end }} 39 40 {{ if eq $stats.NumFiles 1 }} 41 <span>{{ $stats.NumFiles }} file</span> 42 {{ else if gt $stats.NumFiles 1 }} 43 <span>{{ $stats.NumFiles }} files</span> 44 {{ end }} 45
··· 28 {{ $stats := .TreeStats }} 29 30 <span>at <a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">{{ $.Ref }}</a></span> 31 {{ if eq $stats.NumFolders 1 }} 32 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 33 + <span>{{ $stats.NumFolders }} folder</span> 34 {{ else if gt $stats.NumFolders 1 }} 35 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 36 <span>{{ $stats.NumFolders }} folders</span> 37 {{ end }} 38 39 {{ if eq $stats.NumFiles 1 }} 40 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 41 <span>{{ $stats.NumFiles }} file</span> 42 {{ else if gt $stats.NumFiles 1 }} 43 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 44 <span>{{ $stats.NumFiles }} files</span> 45 {{ end }} 46
+14
types/diff.go
··· 23 IsRename bool `json:"is_rename"` 24 } 25 26 // A nicer git diff representation. 27 type NiceDiff struct { 28 Commit struct {
··· 23 IsRename bool `json:"is_rename"` 24 } 25 26 + type DiffStat struct { 27 + Insertions int64 28 + Deletions int64 29 + } 30 + 31 + func (d *Diff) Stats() DiffStat { 32 + var stats DiffStat 33 + for _, f := range d.TextFragments { 34 + stats.Insertions += f.LinesAdded 35 + stats.Deletions += f.LinesDeleted 36 + } 37 + return stats 38 + } 39 + 40 // A nicer git diff representation. 41 type NiceDiff struct { 42 Commit struct {