+40
-10
appview/pages/pages.go
+40
-10
appview/pages/pages.go
···
8
"io/fs"
9
"log"
10
"net/http"
11
-
"os"
12
"path"
13
-
"path/filepath"
14
"strings"
15
16
"github.com/dustin/go-humanize"
···
34
"add": func(a, b int) int {
35
return a + b
36
},
37
"didOrHandle": func(did, handle string) string {
38
if handle != "" {
39
return fmt.Sprintf("@%s", handle)
···
50
pairs = append(pairs, []string{values[i], values[i+1]})
51
}
52
return pairs, nil
53
},
54
"timeFmt": humanize.Time,
55
"length": func(v []string) int {
···
195
return path.Join(r.OwnerWithAt(), r.Name)
196
}
197
198
type RepoIndexParams struct {
199
LoggedInUser *auth.User
200
RepoInfo RepoInfo
···
230
type RepoTreeParams struct {
231
LoggedInUser *auth.User
232
RepoInfo RepoInfo
233
types.RepoTreeResponse
234
}
235
236
func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
237
return p.execute("repo/tree", w, params)
238
}
239
···
261
LoggedInUser *auth.User
262
RepoInfo RepoInfo
263
Active string
264
-
File string
265
-
PathElems []string
266
types.RepoBlobResponse
267
}
268
269
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
params.Active = "overview"
277
return p.executeRepo("repo/blob", w, params)
278
}
···
8
"io/fs"
9
"log"
10
"net/http"
11
"path"
12
"strings"
13
14
"github.com/dustin/go-humanize"
···
32
"add": func(a, b int) int {
33
return a + b
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
+
},
49
"didOrHandle": func(did, handle string) string {
50
if handle != "" {
51
return fmt.Sprintf("@%s", handle)
···
62
pairs = append(pairs, []string{values[i], values[i+1]})
63
}
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
71
},
72
"timeFmt": humanize.Time,
73
"length": func(v []string) int {
···
213
return path.Join(r.OwnerWithAt(), r.Name)
214
}
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
+
230
type RepoIndexParams struct {
231
LoggedInUser *auth.User
232
RepoInfo RepoInfo
···
262
type RepoTreeParams struct {
263
LoggedInUser *auth.User
264
RepoInfo RepoInfo
265
+
Active string
266
+
BreadCrumbs [][]string
267
+
BaseTreeLink string
268
+
BaseBlobLink string
269
types.RepoTreeResponse
270
}
271
272
func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
273
+
params.Active = "overview"
274
return p.execute("repo/tree", w, params)
275
}
276
···
298
LoggedInUser *auth.User
299
RepoInfo RepoInfo
300
Active string
301
+
BreadCrumbs [][]string
302
types.RepoBlobResponse
303
}
304
305
func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error {
306
params.Active = "overview"
307
return p.executeRepo("repo/blob", w, params)
308
}
+1
-1
appview/pages/templates/layouts/repobase.html
+1
-1
appview/pages/templates/layouts/repobase.html
···
16
<nav class="w-full mx-auto">
17
<div class="flex z-60 border-black border-b">
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" }}
20
{{ range $item := $tabs }}
21
{{ $key := index $item 0 }}
22
{{ $value := index $item 1 }}
···
16
<nav class="w-full mx-auto">
17
<div class="flex z-60 border-black border-b">
18
{{ $activeTabStyles := "border-black border-l border-r border-t border-b-0 -mb-px bg-white" }}
19
+
{{ $tabs := .RepoInfo.GetTabs }}
20
{{ range $item := $tabs }}
21
{{ $key := index $item 0 }}
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
{{ $tot_lines := len $lines }}
4
{{ $tot_chars := len (printf "%d" $tot_lines) }}
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>
10
</div>
11
12
···
3
{{ $tot_lines := len $lines }}
4
{{ $tot_chars := len (printf "%d" $tot_lines) }}
5
{{ $code_number_style := "text-gray-400 left-0 bg-white text-right mr-2 select-none" }}
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 }}
15
</div>
16
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"}}
4
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 }}
16
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 }}
27
</div>
28
-
<hr />
29
-
{{ end }}
30
-
{{ end }}
31
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 }}
42
</div>
43
-
<hr />
44
-
{{ end }}
45
-
{{ end }}
46
-
</div>
47
-
</main>
48
-
{{end}}
···
1
+
{{define "repoContent"}}
2
+
<main>
3
+
<div class="tree">
4
+
{{ $containerstyle := "py-1" }}
5
+
{{ $linkstyle := "no-underline hover:underline" }}
6
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>
12
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 }}/
19
</div>
20
+
</a>
21
+
</div>
22
+
{{ end }}
23
+
{{ end }}
24
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>
33
</div>
34
+
{{ end }}
35
+
{{ end }}
36
+
</div>
37
+
</main>
38
+
{{end}}
+28
-2
appview/state/repo.go
+28
-2
appview/state/repo.go
···
6
"io"
7
"log"
8
"net/http"
9
10
"github.com/bluesky-social/indigo/atproto/identity"
11
securejoin "github.com/cyphar/filepath-securejoin"
···
170
return
171
}
172
173
-
log.Println(result)
174
175
-
user := s.auth.GetUser(r)
176
s.pages.RepoTree(w, pages.RepoTreeParams{
177
LoggedInUser: user,
178
RepoInfo: pages.RepoInfo{
179
OwnerDid: f.OwnerDid(),
180
OwnerHandle: f.OwnerHandle(),
···
296
return
297
}
298
299
user := s.auth.GetUser(r)
300
s.pages.RepoBlob(w, pages.RepoBlobParams{
301
LoggedInUser: user,
···
306
SettingsAllowed: settingsAllowed(s, user, f),
307
},
308
RepoBlobResponse: result,
309
})
310
return
311
}
···
449
ok, err := s.enforcer.IsSettingsAllowed(u.Did, f.Knot, f.OwnerSlashRepo())
450
if err == nil && ok {
451
settingsAllowed = true
452
}
453
}
454
···
6
"io"
7
"log"
8
"net/http"
9
+
"path"
10
+
"strings"
11
12
"github.com/bluesky-social/indigo/atproto/identity"
13
securejoin "github.com/cyphar/filepath-securejoin"
···
172
return
173
}
174
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
+
}
184
185
+
baseTreeLink := path.Join(f.OwnerDid(), f.RepoName, "tree", ref, treePath)
186
+
baseBlobLink := path.Join(f.OwnerDid(), f.RepoName, "blob", ref, treePath)
187
+
188
s.pages.RepoTree(w, pages.RepoTreeParams{
189
LoggedInUser: user,
190
+
BreadCrumbs: breadcrumbs,
191
+
BaseTreeLink: baseTreeLink,
192
+
BaseBlobLink: baseBlobLink,
193
RepoInfo: pages.RepoInfo{
194
OwnerDid: f.OwnerDid(),
195
OwnerHandle: f.OwnerHandle(),
···
311
return
312
}
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
+
322
user := s.auth.GetUser(r)
323
s.pages.RepoBlob(w, pages.RepoBlobParams{
324
LoggedInUser: user,
···
329
SettingsAllowed: settingsAllowed(s, user, f),
330
},
331
RepoBlobResponse: result,
332
+
BreadCrumbs: breadcrumbs,
333
})
334
return
335
}
···
473
ok, err := s.enforcer.IsSettingsAllowed(u.Did, f.Knot, f.OwnerSlashRepo())
474
if err == nil && ok {
475
settingsAllowed = true
476
+
} else {
477
+
log.Println(err, ok)
478
}
479
}
480
+2
-1
appview/state/state.go
+2
-1
appview/state/state.go