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

impl breadcrumbs and file nav

Changed files
+114 -62
appview
+40 -10
appview/pages/pages.go
···
"io/fs"
"log"
"net/http"
-
"os"
"path"
-
"path/filepath"
"strings"
"github.com/dustin/go-humanize"
···
"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)
···
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 {
···
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.User
RepoInfo RepoInfo
···
type RepoTreeParams struct {
LoggedInUser *auth.User
RepoInfo RepoInfo
+
Active string
+
BreadCrumbs [][]string
+
BaseTreeLink string
+
BaseBlobLink string
types.RepoTreeResponse
}
func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
+
params.Active = "overview"
return p.execute("repo/tree", w, params)
}
···
LoggedInUser *auth.User
RepoInfo RepoInfo
Active string
-
File string
-
PathElems []string
+
BreadCrumbs [][]string
types.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 = file
params.Active = "overview"
return p.executeRepo("repo/blob", w, params)
}
+1 -1
appview/pages/templates/layouts/repobase.html
···
<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 -1
appview/pages/templates/layouts/topbar.html
···
{{ 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">
<a
href="/"
hx-boost="true"
+9 -4
appview/pages/templates/repo/blob.html
···
{{ $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>
+33 -43
appview/pages/templates/repo/tree.html
···
-
{{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}}
+28 -2
appview/state/repo.go
···
"io"
"log"
"net/http"
+
"path"
+
"strings"
"github.com/bluesky-social/indigo/atproto/identity"
securejoin "github.com/cyphar/filepath-securejoin"
···
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(),
···
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,
···
SettingsAllowed: settingsAllowed(s, user, f),
},
RepoBlobResponse: result,
+
BreadCrumbs: breadcrumbs,
})
return
}
···
ok, err := s.enforcer.IsSettingsAllowed(u.Did, f.Knot, f.OwnerSlashRepo())
if err == nil && ok {
settingsAllowed = true
+
} else {
+
log.Println(err, ok)
}
}
+2 -1
appview/state/state.go
···
}
// 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
}