impl breadcrumbs and file nav
MODIFIED
appview/pages/pages.go
MODIFIED
appview/pages/pages.go
@@ -8,9 +8,7 @@ "io""io/fs""log""net/http"- "os""path"- "path/filepath""strings""github.com/dustin/go-humanize"@@ -34,6 +32,20 @@ },"add": func(a, b int) int {return a + b},+ "sub": func(a, b int) int {+ return a - b+ },+ "cond": func(cond interface{}, a, b string) string {+ if cond == nil {+ return b+ }++ if boolean, ok := cond.(bool); boolean && ok {+ return a+ }++ return b+ },"didOrHandle": func(did, handle string) string {if handle != "" {return fmt.Sprintf("@%s", handle)@@ -50,6 +62,12 @@ for i := 0; i < len(values); i += 2 {pairs = append(pairs, []string{values[i], values[i+1]})}return pairs, nil+ },+ "append": func(s []string, values ...string) []string {+ for _, v := range values {+ s = append(s, v)+ }+ return s},"timeFmt": humanize.Time,"length": func(v []string) int {@@ -195,6 +213,20 @@ func (r RepoInfo) FullName() string {return path.Join(r.OwnerWithAt(), r.Name)}+func (r RepoInfo) GetTabs() [][]string {+ tabs := [][]string{+ {"overview", "/"},+ {"issues", "/issues"},+ {"pulls", "/pulls"},+ }++ if r.SettingsAllowed {+ tabs = append(tabs, []string{"settings", "/settings"})+ }++ return tabs+}+type RepoIndexParams struct {LoggedInUser *auth.UserRepoInfo RepoInfo@@ -230,10 +262,15 @@type RepoTreeParams struct {LoggedInUser *auth.UserRepoInfo RepoInfo+ Active string+ BreadCrumbs [][]string+ BaseTreeLink string+ BaseBlobLink stringtypes.RepoTreeResponse}func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {+ params.Active = "overview"return p.execute("repo/tree", w, params)}@@ -261,18 +298,11 @@ type RepoBlobParams struct {LoggedInUser *auth.UserRepoInfo RepoInfoActive string- File string- PathElems []string+ BreadCrumbs [][]stringtypes.RepoBlobResponse}func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error {- path := filepath.Dir(params.Path)- file := filepath.Base(params.Path)-- params.PathElems = strings.Split(path, string(os.PathSeparator))- params.Path = path- params.File = fileparams.Active = "overview"return p.executeRepo("repo/blob", w, params)}
@@ -16,7 +16,7 @@ <section id="repo-links" class="min-h-screen flex flex-col"><nav class="w-full mx-auto"><div class="flex z-60 border-black border-b">{{ $activeTabStyles := "border-black border-l border-r border-t border-b-0 -mb-px bg-white" }}- {{ $tabs := assoc "overview" "/" "issues" "/issues" "pulls" "/pulls" "settings" "/settings" }}+ {{ $tabs := .RepoInfo.GetTabs }}{{ range $item := $tabs }}{{ $key := index $item 0 }}{{ $value := index $item 1 }}
@@ -1,6 +1,6 @@{{ define "layouts/topbar" }}{{ with .LoggedInUser }}- <nav class="flex items-center justify-center space-x-4 text-sm mb-4">+ <nav class="flex items-center justify-center space-x-4 text-sm mb-4 border-b border-l border-r border-black"><ahref="/"hx-boost="true"
@@ -3,10 +3,15 @@ {{ $lines := split .Contents }}{{ $tot_lines := len $lines }}{{ $tot_chars := len (printf "%d" $tot_lines) }}{{ $code_number_style := "text-gray-400 left-0 bg-white text-right mr-2 select-none" }}-<div class="pb-2 text-lg">-{{ range .PathElems }}- <a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ . }}" class="text-bold text-gray-500">{{ . }}</a> /-{{ end }}<span class="">{{ .File }}</span>+{{ $linkstyle := "no-underline hover:underline" }}+<div class="pb-2 text-base">+ {{ range $idx, $value := .BreadCrumbs }}+ {{ if ne $idx (sub (len $.BreadCrumbs) 1) }}+ <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> /+ {{ else }}+ <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a>+ {{ end }}+ {{ end }}</div>
@@ -1,48 +1,38 @@-{{define "title"}} {{ .RepoInfo.FullName }} {{end}}--{{define "content"}}+{{define "repoContent"}}+<main>+ <div class="tree">+ {{ $containerstyle := "py-1" }}+ {{ $linkstyle := "no-underline hover:underline" }}-<h1>-{{ .RepoInfo.FullName }}-</h1>- <main>- <div class="tree">-- {{ if .Parent }}- <div></div>- <div></div>- <div><a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}/{{ .DotDot }}">..</a></div>- {{ end }}+ <div class="pb-2 text-base">+ {{ range .BreadCrumbs }}+ <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> /+ {{ end }}+ </div>- {{ range .Files }}- {{ if not .IsFile }}- <div class="mode">{{ .Mode }}</div>- <div class="size">{{ .Size }}</div>- <div>- {{ if $.Parent }}- <a href="/{{ .RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ $.Parent }}/{{ .Name }}">{{ .Name }}/</a>- {{ else }}- <a href="/{{ .RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ .Name }}">{{ .Name }}/</a>- {{ end }}+ {{ range .Files }}+ {{ if not .IsFile }}+ <div class="{{ $containerstyle }}">+ <a href="/{{ $.BaseTreeLink }}/{{ .Name }}" class="{{ $linkstyle }}">+ <div class="flex items-center gap-2">+ <i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }}/</div>- <hr />- {{ end }}- {{ end }}+ </a>+ </div>+ {{ end }}+ {{ end }}- {{ range .Files }}- {{ if .IsFile }}- <div class="mode">{{ .Mode }}</div>- <div class="size">{{ .Size }}</div>- <div>- {{ if $.Parent }}- <a href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref }}/{{ $.Parent }}/{{ .Name }}">{{ .Name }}</a>- {{ else }}- <a href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref }}/{{ .Name }}">{{ .Name }}</a>- {{ end }}+ {{ range .Files }}+ {{ if .IsFile }}+ <div class="{{ $containerstyle }}">+ <a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}">+ <div class="flex items-center gap-2">+ <i class="w-3 h-3" data-lucide="file"></i>{{ .Name }}+ </div>+ </a></div>- <hr />- {{ end }}- {{ end }}- </div>- </main>- {{end}}+ {{ end }}+ {{ end }}+ </div>+</main>+{{end}}
MODIFIED
appview/state/repo.go
MODIFIED
appview/state/repo.go
@@ -6,6 +6,8 @@ "fmt""io""log""net/http"+ "path"+ "strings""github.com/bluesky-social/indigo/atproto/identity"securejoin "github.com/cyphar/filepath-securejoin"@@ -170,11 +172,24 @@ log.Println("failed to parse response:", err)return}- log.Println(result)+ user := s.auth.GetUser(r)++ var breadcrumbs [][]string+ breadcrumbs = append(breadcrumbs, []string{f.RepoName, fmt.Sprintf("/%s/%s/tree/%s", f.OwnerDid(), f.RepoName, ref)})+ if treePath != "" {+ for idx, elem := range strings.Split(treePath, "/") {+ breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], elem)})+ }+ }- user := s.auth.GetUser(r)+ baseTreeLink := path.Join(f.OwnerDid(), f.RepoName, "tree", ref, treePath)+ baseBlobLink := path.Join(f.OwnerDid(), f.RepoName, "blob", ref, treePath)+s.pages.RepoTree(w, pages.RepoTreeParams{LoggedInUser: user,+ BreadCrumbs: breadcrumbs,+ BaseTreeLink: baseTreeLink,+ BaseBlobLink: baseBlobLink,RepoInfo: pages.RepoInfo{OwnerDid: f.OwnerDid(),OwnerHandle: f.OwnerHandle(),@@ -296,6 +311,14 @@ log.Println("failed to parse response:", err)return}+ var breadcrumbs [][]string+ breadcrumbs = append(breadcrumbs, []string{f.RepoName, fmt.Sprintf("/%s/%s/tree/%s", f.OwnerDid(), f.RepoName, ref)})+ if filePath != "" {+ for idx, elem := range strings.Split(filePath, "/") {+ breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], elem)})+ }+ }+user := s.auth.GetUser(r)s.pages.RepoBlob(w, pages.RepoBlobParams{LoggedInUser: user,@@ -306,6 +329,7 @@ Name: f.RepoName,SettingsAllowed: settingsAllowed(s, user, f),},RepoBlobResponse: result,+ BreadCrumbs: breadcrumbs,})return}@@ -449,6 +473,8 @@ if u != nil {ok, err := s.enforcer.IsSettingsAllowed(u.Did, f.Knot, f.OwnerSlashRepo())if err == nil && ok {settingsAllowed = true+ } else {+ log.Println(err, ok)}}
MODIFIED
appview/state/state.go
MODIFIED
appview/state/state.go
@@ -535,9 +535,10 @@ return}// acls- p, _ := securejoin.SecureJoin(domain, repoName)+ p, _ := securejoin.SecureJoin(user.Did, repoName)err = s.enforcer.AddRepo(user.Did, domain, p)if err != nil {+ log.Println(err)s.pages.Notice(w, "repo", "Failed to set up repository permissions.")return}