forked from tangled.org/core
Monorepo for Tangled

appview/pages: improve grid layout in directory listings

unifies layouts in repo-index and repo-tree.

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 87d9107d 23e971e6

verified
Changed files
+101 -115
appview
+1 -1
appview/pages/funcmap.go
··· 191 191 if v.Len() == 0 { 192 192 return nil 193 193 } 194 - return v.Slice(0, min(n, v.Len()-1)).Interface() 194 + return v.Slice(0, min(n, v.Len())).Interface() 195 195 }, 196 196 197 197 "markdown": func(text string) template.HTML {
+1 -2
appview/pages/pages.go
··· 555 555 RepoInfo repoinfo.RepoInfo 556 556 Active string 557 557 BreadCrumbs [][]string 558 - BaseTreeLink string 559 - BaseBlobLink string 558 + TreePath string 560 559 types.RepoTreeResponse 561 560 } 562 561
+27 -47
appview/pages/templates/repo/index.html
··· 127 127 {{ end }} 128 128 129 129 {{ define "fileTree" }} 130 - <div 131 - id="file-tree" 132 - class="col-span-1 pr-2 md:border-r md:border-gray-200 dark:md:border-gray-700" 133 - > 134 - {{ $containerstyle := "py-1" }} 135 - {{ $linkstyle := "no-underline hover:underline dark:text-white" }} 130 + <div id="file-tree" class="col-span-1 pr-2 md:border-r md:border-gray-200 dark:md:border-gray-700" > 131 + {{ $linkstyle := "no-underline hover:underline dark:text-white" }} 136 132 137 - {{ range .Files }} 138 - {{ if not .IsFile }} 139 - <div class="{{ $containerstyle }}"> 140 - <div class="flex justify-between items-center"> 141 - <a 142 - href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref | urlquery }}/{{ .Name }}" 143 - class="{{ $linkstyle }}" 144 - > 145 - <div class="flex items-center gap-2"> 146 - {{ i "folder" "size-4 fill-current" }} 147 - {{ .Name }} 148 - </div> 149 - </a> 133 + {{ range .Files }} 134 + <div class="grid grid-cols-2 gap-4 items-center py-1"> 135 + <div class="col-span-1"> 136 + {{ $link := printf "/%s/%s/%s/%s" $.RepoInfo.FullName "tree" (urlquery $.Ref) .Name }} 137 + {{ $icon := "folder" }} 138 + {{ $iconStyle := "size-4 fill-current" }} 150 139 151 - {{ if .LastCommit }} 152 - <span class="text-xs text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .LastCommit.When }}</span> 153 - {{ end }} 154 - </div> 155 - </div> 156 - {{ end }} 157 - {{ end }} 158 - 159 - {{ range .Files }} 160 - {{ if .IsFile }} 161 - <div class="{{ $containerstyle }}"> 162 - <div class="flex justify-between items-center"> 163 - <a 164 - href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref | urlquery }}/{{ .Name }}" 165 - class="{{ $linkstyle }}" 166 - > 167 - <div class="flex items-center gap-2"> 168 - {{ i "file" "size-4" }}{{ .Name }} 169 - </div> 170 - </a> 140 + {{ if .IsFile }} 141 + {{ $link = printf "/%s/%s/%s/%s" $.RepoInfo.FullName "blob" (urlquery $.Ref) .Name }} 142 + {{ $icon = "file" }} 143 + {{ $iconStyle = "size-4" }} 144 + {{ end }} 145 + <a href="{{ $link }}" class="{{ $linkstyle }}"> 146 + <div class="flex items-center gap-2"> 147 + {{ i $icon $iconStyle }}{{ .Name }} 148 + </div> 149 + </a> 150 + </div> 171 151 172 - {{ if .LastCommit }} 173 - <span class="text-xs text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .LastCommit.When }}</span> 174 - {{ end }} 175 - </div> 176 - </div> 177 - {{ end }} 178 - {{ end }} 179 - </div> 152 + <div class="text-xs col-span-1 text-right"> 153 + {{ with .LastCommit }} 154 + <a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .When }}</a> 155 + {{ end }} 156 + </div> 157 + </div> 158 + {{ end }} 159 + </div> 180 160 {{ end }} 181 161 182 162 {{ define "rightInfo" }}
+26 -34
appview/pages/templates/repo/tree.html
··· 19 19 {{define "repoContent"}} 20 20 <main> 21 21 <div class="tree"> 22 - {{ $containerstyle := "py-1" }} 23 22 {{ $linkstyle := "no-underline hover:underline" }} 24 23 25 24 <div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700"> ··· 54 53 </div> 55 54 56 55 {{ range .Files }} 57 - {{ if not .IsFile }} 58 - <div class="{{ $containerstyle }}"> 59 - <div class="flex justify-between items-center"> 60 - <a href="/{{ $.BaseTreeLink }}/{{ .Name }}" class="{{ $linkstyle }}"> 61 - <div class="flex items-center gap-2"> 62 - {{ i "folder" "size-4 fill-current" }}{{ .Name }} 63 - </div> 64 - </a> 65 - {{ if .LastCommit}} 66 - <div class="flex items-end gap-2"> 67 - <span class="text text-gray-500 dark:text-gray-400 mr-6">{{ .LastCommit.Message }}</span> 68 - <span class="text-xs text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .LastCommit.When }}</span> 56 + <div class="grid grid-cols-12 gap-4 items-center py-1"> 57 + <div class="col-span-6 md:col-span-3"> 58 + {{ $link := printf "/%s/%s/%s/%s/%s" $.RepoInfo.FullName "tree" (urlquery $.Ref) $.TreePath .Name }} 59 + {{ $icon := "folder" }} 60 + {{ $iconStyle := "size-4 fill-current" }} 61 + 62 + {{ if .IsFile }} 63 + {{ $icon = "file" }} 64 + {{ $iconStyle = "size-4" }} 65 + {{ end }} 66 + <a href="{{ $link }}" class="{{ $linkstyle }}"> 67 + <div class="flex items-center gap-2"> 68 + {{ i $icon $iconStyle }}{{ .Name }} 69 69 </div> 70 - {{ end }} 70 + </a> 71 71 </div> 72 - </div> 73 - {{ end }} 74 - {{ end }} 75 72 76 - {{ range .Files }} 77 - {{ if .IsFile }} 78 - <div class="{{ $containerstyle }}"> 79 - <div class="flex justify-between items-center"> 80 - <a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}"> 81 - <div class="flex items-center gap-2"> 82 - {{ i "file" "size-4" }}{{ .Name }} 83 - </div> 84 - </a> 85 - {{ if .LastCommit}} 86 - <div class="flex items-end gap-2"> 87 - <span class="text text-gray-500 dark:text-gray-400 mr-6">{{ .LastCommit.Message }}</span> 88 - <span class="text-xs text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .LastCommit.When }}</span> 89 - </div> 90 - {{ end }} 73 + <div class="col-span-0 md:col-span-7 hidden md:block overflow-hidden"> 74 + {{ with .LastCommit }} 75 + <a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400 block truncate">{{ .Message }}</a> 76 + {{ end }} 77 + </div> 78 + 79 + <div class="col-span-6 md:col-span-2 text-right"> 80 + {{ with .LastCommit }} 81 + <a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .When }}</a> 82 + {{ end }} 91 83 </div> 92 - </div> 84 + </div> 93 85 {{ end }} 94 - {{ end }} 86 + 95 87 </div> 96 88 </main> 97 89 {{end}}
+3 -3
appview/pages/templates/user/repos.html
··· 8 8 {{ end }} 9 9 10 10 {{ define "content" }} 11 - <div class="grid grid-cols-1 md:grid-cols-8 gap-4"> 12 - <div class="md:col-span-2 order-1 md:order-1"> 11 + <div class="grid grid-cols-1 md:grid-cols-11 gap-4"> 12 + <div class="md:col-span-3 order-1 md:order-1"> 13 13 {{ template "user/fragments/profileCard" .Card }} 14 14 </div> 15 - <div id="all-repos" class="md:col-span-6 order-2 md:order-2"> 15 + <div id="all-repos" class="md:col-span-8 order-2 md:order-2"> 16 16 {{ block "ownRepos" . }}{{ end }} 17 17 </div> 18 18 </div>
+2
appview/repo/index.go
··· 58 58 tagMap[hash] = append(tagMap[hash], branch.Name) 59 59 } 60 60 61 + sortFiles(result.Files) 62 + 61 63 slices.SortFunc(result.Branches, func(a, b types.Branch) int { 62 64 if a.Name == result.Ref { 63 65 return -1
+7 -28
appview/repo/repo.go
··· 10 10 "log" 11 11 "net/http" 12 12 "net/url" 13 - "path" 14 13 "slices" 15 - "sort" 16 14 "strconv" 17 15 "strings" 18 16 "time" ··· 374 372 375 373 // redirects tree paths trying to access a blob; in this case the result.Files is unpopulated, 376 374 // so we can safely redirect to the "parent" (which is the same file). 377 - if len(result.Files) == 0 && result.Parent == treePath { 375 + unescapedTreePath, _ := url.PathUnescape(treePath) 376 + if len(result.Files) == 0 && result.Parent == unescapedTreePath { 378 377 http.Redirect(w, r, fmt.Sprintf("/%s/blob/%s/%s", f.OwnerSlashRepo(), ref, result.Parent), http.StatusFound) 379 378 return 380 379 } ··· 389 388 } 390 389 } 391 390 392 - baseTreeLink := path.Join(f.OwnerSlashRepo(), "tree", ref, treePath) 393 - baseBlobLink := path.Join(f.OwnerSlashRepo(), "blob", ref, treePath) 391 + sortFiles(result.Files) 394 392 395 393 rp.pages.RepoTree(w, pages.RepoTreeParams{ 396 394 LoggedInUser: user, 397 395 BreadCrumbs: breadcrumbs, 398 - BaseTreeLink: baseTreeLink, 399 - BaseBlobLink: baseBlobLink, 396 + TreePath: treePath, 400 397 RepoInfo: f.RepoInfo(user), 401 398 RepoTreeResponse: result, 402 399 }) 403 - return 404 400 } 405 401 406 402 func (rp *Repo) RepoTags(w http.ResponseWriter, r *http.Request) { ··· 480 476 return 481 477 } 482 478 483 - slices.SortFunc(result.Branches, func(a, b types.Branch) int { 484 - if a.IsDefault { 485 - return -1 486 - } 487 - if b.IsDefault { 488 - return 1 489 - } 490 - if a.Commit != nil && b.Commit != nil { 491 - if a.Commit.Committer.When.Before(b.Commit.Committer.When) { 492 - return 1 493 - } else { 494 - return -1 495 - } 496 - } 497 - return strings.Compare(a.Name, b.Name) * -1 498 - }) 479 + sortBranches(result.Branches) 499 480 500 481 user := rp.oauth.GetUser(r) 501 482 rp.pages.RepoBranches(w, pages.RepoBranchesParams{ ··· 503 484 RepoInfo: f.RepoInfo(user), 504 485 RepoBranchesResponse: *result, 505 486 }) 506 - return 507 487 } 508 488 509 489 func (rp *Repo) RepoBlob(w http.ResponseWriter, r *http.Request) { ··· 1233 1213 return 1234 1214 } 1235 1215 branches := result.Branches 1236 - sort.Slice(branches, func(i int, j int) bool { 1237 - return branches[i].Commit.Committer.When.After(branches[j].Commit.Committer.When) 1238 - }) 1216 + 1217 + sortBranches(branches) 1239 1218 1240 1219 var defaultBranch string 1241 1220 for _, b := range branches {
+34
appview/repo/repo_util.go
··· 5 5 "crypto/rand" 6 6 "fmt" 7 7 "math/big" 8 + "slices" 9 + "sort" 10 + "strings" 8 11 9 12 "tangled.sh/tangled.sh/core/appview/db" 10 13 "tangled.sh/tangled.sh/core/appview/pages/repoinfo" 14 + "tangled.sh/tangled.sh/core/types" 11 15 12 16 "github.com/go-git/go-git/v5/plumbing/object" 13 17 ) 18 + 19 + func sortFiles(files []types.NiceTree) { 20 + sort.Slice(files, func(i, j int) bool { 21 + iIsFile := files[i].IsFile 22 + jIsFile := files[j].IsFile 23 + if iIsFile != jIsFile { 24 + return !iIsFile 25 + } 26 + return files[i].Name < files[j].Name 27 + }) 28 + } 29 + 30 + func sortBranches(branches []types.Branch) { 31 + slices.SortFunc(branches, func(a, b types.Branch) int { 32 + if a.IsDefault { 33 + return -1 34 + } 35 + if b.IsDefault { 36 + return 1 37 + } 38 + if a.Commit != nil && b.Commit != nil { 39 + if a.Commit.Committer.When.Before(b.Commit.Committer.When) { 40 + return 1 41 + } else { 42 + return -1 43 + } 44 + } 45 + return strings.Compare(a.Name, b.Name) 46 + }) 47 + } 14 48 15 49 func uniqueEmails(commits []*object.Commit) []string { 16 50 emails := make(map[string]struct{})