+40
-10
appview/pages/pages.go
+40
-10
appview/pages/pages.go
···
8
8
"io/fs"
9
9
"log"
10
10
"net/http"
11
-
"os"
12
11
"path"
13
-
"path/filepath"
14
12
"strings"
15
13
16
14
"github.com/dustin/go-humanize"
···
34
32
"add": func(a, b int) int {
35
33
return a + b
36
34
},
35
+
"sub": func(a, b int) int {
36
+
return a - b
37
+
},
38
+
"cond": func(cond interface{}, a, b string) string {
39
+
if cond == nil {
40
+
return b
41
+
}
42
+
43
+
if boolean, ok := cond.(bool); boolean && ok {
44
+
return a
45
+
}
46
+
47
+
return b
48
+
},
37
49
"didOrHandle": func(did, handle string) string {
38
50
if handle != "" {
39
51
return fmt.Sprintf("@%s", handle)
···
50
62
pairs = append(pairs, []string{values[i], values[i+1]})
51
63
}
52
64
return pairs, nil
65
+
},
66
+
"append": func(s []string, values ...string) []string {
67
+
for _, v := range values {
68
+
s = append(s, v)
69
+
}
70
+
return s
53
71
},
54
72
"timeFmt": humanize.Time,
55
73
"length": func(v []string) int {
···
195
213
return path.Join(r.OwnerWithAt(), r.Name)
196
214
}
197
215
216
+
func (r RepoInfo) GetTabs() [][]string {
217
+
tabs := [][]string{
218
+
{"overview", "/"},
219
+
{"issues", "/issues"},
220
+
{"pulls", "/pulls"},
221
+
}
222
+
223
+
if r.SettingsAllowed {
224
+
tabs = append(tabs, []string{"settings", "/settings"})
225
+
}
226
+
227
+
return tabs
228
+
}
229
+
198
230
type RepoIndexParams struct {
199
231
LoggedInUser *auth.User
200
232
RepoInfo RepoInfo
···
230
262
type RepoTreeParams struct {
231
263
LoggedInUser *auth.User
232
264
RepoInfo RepoInfo
265
+
Active string
266
+
BreadCrumbs [][]string
267
+
BaseTreeLink string
268
+
BaseBlobLink string
233
269
types.RepoTreeResponse
234
270
}
235
271
236
272
func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
273
+
params.Active = "overview"
237
274
return p.execute("repo/tree", w, params)
238
275
}
239
276
···
261
298
LoggedInUser *auth.User
262
299
RepoInfo RepoInfo
263
300
Active string
264
-
File string
265
-
PathElems []string
301
+
BreadCrumbs [][]string
266
302
types.RepoBlobResponse
267
303
}
268
304
269
305
func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error {
270
-
path := filepath.Dir(params.Path)
271
-
file := filepath.Base(params.Path)
272
-
273
-
params.PathElems = strings.Split(path, string(os.PathSeparator))
274
-
params.Path = path
275
-
params.File = file
276
306
params.Active = "overview"
277
307
return p.executeRepo("repo/blob", w, params)
278
308
}
+1
-1
appview/pages/templates/layouts/repobase.html
+1
-1
appview/pages/templates/layouts/repobase.html
···
16
16
<nav class="w-full mx-auto">
17
17
<div class="flex z-60 border-black border-b">
18
18
{{ $activeTabStyles := "border-black border-l border-r border-t border-b-0 -mb-px bg-white" }}
19
-
{{ $tabs := assoc "overview" "/" "issues" "/issues" "pulls" "/pulls" "settings" "/settings" }}
19
+
{{ $tabs := .RepoInfo.GetTabs }}
20
20
{{ range $item := $tabs }}
21
21
{{ $key := index $item 0 }}
22
22
{{ $value := index $item 1 }}
+1
-1
appview/pages/templates/layouts/topbar.html
+1
-1
appview/pages/templates/layouts/topbar.html
+9
-4
appview/pages/templates/repo/blob.html
+9
-4
appview/pages/templates/repo/blob.html
···
3
3
{{ $tot_lines := len $lines }}
4
4
{{ $tot_chars := len (printf "%d" $tot_lines) }}
5
5
{{ $code_number_style := "text-gray-400 left-0 bg-white text-right mr-2 select-none" }}
6
-
<div class="pb-2 text-lg">
7
-
{{ range .PathElems }}
8
-
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ . }}" class="text-bold text-gray-500">{{ . }}</a> /
9
-
{{ end }}<span class="">{{ .File }}</span>
6
+
{{ $linkstyle := "no-underline hover:underline" }}
7
+
<div class="pb-2 text-base">
8
+
{{ range $idx, $value := .BreadCrumbs }}
9
+
{{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
10
+
<a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> /
11
+
{{ else }}
12
+
<a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a>
13
+
{{ end }}
14
+
{{ end }}
10
15
</div>
11
16
12
17
+33
-43
appview/pages/templates/repo/tree.html
+33
-43
appview/pages/templates/repo/tree.html
···
1
-
{{define "title"}} {{ .RepoInfo.FullName }} {{end}}
2
-
3
-
{{define "content"}}
1
+
{{define "repoContent"}}
2
+
<main>
3
+
<div class="tree">
4
+
{{ $containerstyle := "py-1" }}
5
+
{{ $linkstyle := "no-underline hover:underline" }}
4
6
5
-
<h1>
6
-
{{ .RepoInfo.FullName }}
7
-
</h1>
8
-
<main>
9
-
<div class="tree">
10
-
11
-
{{ if .Parent }}
12
-
<div></div>
13
-
<div></div>
14
-
<div><a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}/{{ .DotDot }}">..</a></div>
15
-
{{ end }}
7
+
<div class="pb-2 text-base">
8
+
{{ range .BreadCrumbs }}
9
+
<a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> /
10
+
{{ end }}
11
+
</div>
16
12
17
-
{{ range .Files }}
18
-
{{ if not .IsFile }}
19
-
<div class="mode">{{ .Mode }}</div>
20
-
<div class="size">{{ .Size }}</div>
21
-
<div>
22
-
{{ if $.Parent }}
23
-
<a href="/{{ .RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ $.Parent }}/{{ .Name }}">{{ .Name }}/</a>
24
-
{{ else }}
25
-
<a href="/{{ .RepoInfo.FullName }}/tree/{{ $.Ref }}/{{ .Name }}">{{ .Name }}/</a>
26
-
{{ end }}
13
+
{{ range .Files }}
14
+
{{ if not .IsFile }}
15
+
<div class="{{ $containerstyle }}">
16
+
<a href="/{{ $.BaseTreeLink }}/{{ .Name }}" class="{{ $linkstyle }}">
17
+
<div class="flex items-center gap-2">
18
+
<i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }}/
27
19
</div>
28
-
<hr />
29
-
{{ end }}
30
-
{{ end }}
20
+
</a>
21
+
</div>
22
+
{{ end }}
23
+
{{ end }}
31
24
32
-
{{ range .Files }}
33
-
{{ if .IsFile }}
34
-
<div class="mode">{{ .Mode }}</div>
35
-
<div class="size">{{ .Size }}</div>
36
-
<div>
37
-
{{ if $.Parent }}
38
-
<a href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref }}/{{ $.Parent }}/{{ .Name }}">{{ .Name }}</a>
39
-
{{ else }}
40
-
<a href="/{{ $.RepoInfo.FullName }}/blob/{{ $.Ref }}/{{ .Name }}">{{ .Name }}</a>
41
-
{{ end }}
25
+
{{ range .Files }}
26
+
{{ if .IsFile }}
27
+
<div class="{{ $containerstyle }}">
28
+
<a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}">
29
+
<div class="flex items-center gap-2">
30
+
<i class="w-3 h-3" data-lucide="file"></i>{{ .Name }}
31
+
</div>
32
+
</a>
42
33
</div>
43
-
<hr />
44
-
{{ end }}
45
-
{{ end }}
46
-
</div>
47
-
</main>
48
-
{{end}}
34
+
{{ end }}
35
+
{{ end }}
36
+
</div>
37
+
</main>
38
+
{{end}}
+28
-2
appview/state/repo.go
+28
-2
appview/state/repo.go
···
6
6
"io"
7
7
"log"
8
8
"net/http"
9
+
"path"
10
+
"strings"
9
11
10
12
"github.com/bluesky-social/indigo/atproto/identity"
11
13
securejoin "github.com/cyphar/filepath-securejoin"
···
170
172
return
171
173
}
172
174
173
-
log.Println(result)
175
+
user := s.auth.GetUser(r)
176
+
177
+
var breadcrumbs [][]string
178
+
breadcrumbs = append(breadcrumbs, []string{f.RepoName, fmt.Sprintf("/%s/%s/tree/%s", f.OwnerDid(), f.RepoName, ref)})
179
+
if treePath != "" {
180
+
for idx, elem := range strings.Split(treePath, "/") {
181
+
breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], elem)})
182
+
}
183
+
}
174
184
175
-
user := s.auth.GetUser(r)
185
+
baseTreeLink := path.Join(f.OwnerDid(), f.RepoName, "tree", ref, treePath)
186
+
baseBlobLink := path.Join(f.OwnerDid(), f.RepoName, "blob", ref, treePath)
187
+
176
188
s.pages.RepoTree(w, pages.RepoTreeParams{
177
189
LoggedInUser: user,
190
+
BreadCrumbs: breadcrumbs,
191
+
BaseTreeLink: baseTreeLink,
192
+
BaseBlobLink: baseBlobLink,
178
193
RepoInfo: pages.RepoInfo{
179
194
OwnerDid: f.OwnerDid(),
180
195
OwnerHandle: f.OwnerHandle(),
···
296
311
return
297
312
}
298
313
314
+
var breadcrumbs [][]string
315
+
breadcrumbs = append(breadcrumbs, []string{f.RepoName, fmt.Sprintf("/%s/%s/tree/%s", f.OwnerDid(), f.RepoName, ref)})
316
+
if filePath != "" {
317
+
for idx, elem := range strings.Split(filePath, "/") {
318
+
breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], elem)})
319
+
}
320
+
}
321
+
299
322
user := s.auth.GetUser(r)
300
323
s.pages.RepoBlob(w, pages.RepoBlobParams{
301
324
LoggedInUser: user,
···
306
329
SettingsAllowed: settingsAllowed(s, user, f),
307
330
},
308
331
RepoBlobResponse: result,
332
+
BreadCrumbs: breadcrumbs,
309
333
})
310
334
return
311
335
}
···
449
473
ok, err := s.enforcer.IsSettingsAllowed(u.Did, f.Knot, f.OwnerSlashRepo())
450
474
if err == nil && ok {
451
475
settingsAllowed = true
476
+
} else {
477
+
log.Println(err, ok)
452
478
}
453
479
}
454
480
+2
-1
appview/state/state.go
+2
-1
appview/state/state.go
···
535
535
}
536
536
537
537
// acls
538
-
p, _ := securejoin.SecureJoin(domain, repoName)
538
+
p, _ := securejoin.SecureJoin(user.Did, repoName)
539
539
err = s.enforcer.AddRepo(user.Did, domain, p)
540
540
if err != nil {
541
+
log.Println(err)
541
542
s.pages.Notice(w, "repo", "Failed to set up repository permissions.")
542
543
return
543
544
}