+1
-1
.air/appview.toml
+1
-1
.air/appview.toml
appview/pages/knot.html
appview/pages/templates/knot.html
appview/pages/knot.html
appview/pages/templates/knot.html
appview/pages/knots.html
appview/pages/templates/knots.html
appview/pages/knots.html
appview/pages/templates/knots.html
-20
appview/pages/layout.html
-20
appview/pages/layout.html
···
1
-
<!DOCTYPE html>
2
-
<html lang="en">
3
-
<head>
4
-
<meta charset="UTF-8">
5
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6
-
<script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
7
-
<title>{{block "title" .}}tangled{{end}}</title>
8
-
</head>
9
-
<body>
10
-
11
-
<div class="navbar">
12
-
<a href="/" style="color: white; text-decoration: none;">Home</a>
13
-
</div>
14
-
15
-
<div class="content">
16
-
{{block "content" .}}{{end}}
17
-
</div>
18
-
19
-
</body>
20
-
</html>
···
-14
appview/pages/login.html
-14
appview/pages/login.html
···
1
-
{{define "title"}}login{{end}}
2
-
3
-
{{define "content"}}
4
-
<h1>login</h1>
5
-
<form method="POST" action="/login">
6
-
<label for="handle">handle</label>
7
-
<input type="text" id="handle" name="handle" required>
8
-
9
-
<label for="app_password">app password</label>
10
-
<input type="password" id="app_password" name="app_password" required>
11
-
12
-
<button type="submit">login</button>
13
-
</form>
14
-
{{end}}
···
appview/pages/new-repo.html
appview/pages/templates/new-repo.html
appview/pages/new-repo.html
appview/pages/templates/new-repo.html
+59
-30
appview/pages/pages.go
+59
-30
appview/pages/pages.go
···
2
3
import (
4
"embed"
5
"html/template"
6
"io"
7
-
"sync"
8
9
"github.com/sotangled/tangled/appview/auth"
10
"github.com/sotangled/tangled/appview/db"
11
)
12
13
-
//go:embed *.html
14
var files embed.FS
15
16
-
var (
17
-
cache = make(map[string]*template.Template)
18
-
mutex sync.Mutex
19
-
)
20
21
-
func parse(file string) *template.Template {
22
-
mutex.Lock()
23
-
defer mutex.Unlock()
24
25
-
if tmpl, found := cache[file]; found {
26
-
return tmpl
27
}
28
29
-
tmpl := template.Must(
30
-
template.New("layout.html").ParseFS(files, "layout.html", file),
31
-
)
32
33
-
cache[file] = tmpl
34
-
return tmpl
35
}
36
37
type LoginParams struct {
38
}
39
40
-
func Login(w io.Writer, p LoginParams) error {
41
-
return parse("login.html").Execute(w, p)
42
}
43
44
type TimelineParams struct {
45
User *auth.User
46
}
47
48
-
func Timeline(w io.Writer, p TimelineParams) error {
49
-
return parse("timeline.html").Execute(w, p)
50
}
51
52
type SettingsParams struct {
···
54
PubKeys []db.PublicKey
55
}
56
57
-
func Settings(w io.Writer, p SettingsParams) error {
58
-
return parse("settings.html").Execute(w, p)
59
}
60
61
type KnotsParams struct {
···
63
Registrations []db.Registration
64
}
65
66
-
func Knots(w io.Writer, p KnotsParams) error {
67
-
return parse("knots.html").Execute(w, p)
68
}
69
70
type KnotParams struct {
···
74
IsOwner bool
75
}
76
77
-
func Knot(w io.Writer, p KnotParams) error {
78
-
return parse("knot.html").Execute(w, p)
79
}
80
81
type NewRepoParams struct {
82
User *auth.User
83
}
84
85
-
func NewRepo(w io.Writer, p NewRepoParams) error {
86
-
return parse("new-repo.html").Execute(w, p)
87
}
88
89
type ProfilePageParams struct {
···
93
Repos []db.Repo
94
}
95
96
-
func ProfilePage(w io.Writer, p ProfilePageParams) error {
97
-
return parse("profile.html").Execute(w, p)
98
}
···
2
3
import (
4
"embed"
5
+
"fmt"
6
"html/template"
7
"io"
8
+
"io/fs"
9
+
"log"
10
+
"strings"
11
12
"github.com/sotangled/tangled/appview/auth"
13
"github.com/sotangled/tangled/appview/db"
14
)
15
16
+
//go:embed templates/*
17
var files embed.FS
18
19
+
type Pages struct {
20
+
t map[string]*template.Template
21
+
}
22
+
23
+
func NewPages() *Pages {
24
+
templates := make(map[string]*template.Template)
25
+
26
+
// Walk through embedded templates directory and parse all .html files
27
+
err := fs.WalkDir(files, "templates", func(path string, d fs.DirEntry, err error) error {
28
+
if err != nil {
29
+
return err
30
+
}
31
+
32
+
if !d.IsDir() && strings.HasSuffix(path, ".html") {
33
+
name := strings.TrimPrefix(path, "templates/")
34
+
name = strings.TrimSuffix(name, ".html")
35
36
+
if !strings.HasPrefix(path, "templates/layouts/") {
37
+
// Add the page template on top of the base
38
+
tmpl, err := template.New(name).ParseFS(files, path, "templates/layouts/*.html")
39
+
if err != nil {
40
+
return fmt.Errorf("setting up template: %w", err)
41
+
}
42
43
+
templates[name] = tmpl
44
+
log.Printf("loaded template: %s", name)
45
+
}
46
+
47
+
return nil
48
+
}
49
+
return nil
50
+
})
51
+
if err != nil {
52
+
log.Fatalf("walking template dir: %v", err)
53
}
54
55
+
log.Printf("total templates loaded: %d", len(templates))
56
57
+
return &Pages{
58
+
t: templates,
59
+
}
60
}
61
62
type LoginParams struct {
63
}
64
65
+
func (p *Pages) execute(name string, w io.Writer, params any) error {
66
+
return p.t[name].ExecuteTemplate(w, "layouts/base", params)
67
+
}
68
+
69
+
func (p *Pages) Login(w io.Writer, params LoginParams) error {
70
+
return p.t["user/login"].ExecuteTemplate(w, "layouts/base", params)
71
}
72
73
type TimelineParams struct {
74
User *auth.User
75
}
76
77
+
func (p *Pages) Timeline(w io.Writer, params TimelineParams) error {
78
+
return p.execute("timeline", w, params)
79
}
80
81
type SettingsParams struct {
···
83
PubKeys []db.PublicKey
84
}
85
86
+
func (p *Pages) Settings(w io.Writer, params SettingsParams) error {
87
+
return p.execute("settings/keys", w, params)
88
}
89
90
type KnotsParams struct {
···
92
Registrations []db.Registration
93
}
94
95
+
func (p *Pages) Knots(w io.Writer, params KnotsParams) error {
96
+
return p.execute("knots", w, params)
97
}
98
99
type KnotParams struct {
···
103
IsOwner bool
104
}
105
106
+
func (p *Pages) Knot(w io.Writer, params KnotParams) error {
107
+
return p.execute("knot", w, params)
108
}
109
110
type NewRepoParams struct {
111
User *auth.User
112
}
113
114
+
func (p *Pages) NewRepo(w io.Writer, params NewRepoParams) error {
115
+
return p.execute("repo/new", w, params)
116
}
117
118
type ProfilePageParams struct {
···
122
Repos []db.Repo
123
}
124
125
+
func (p *Pages) ProfilePage(w io.Writer, params ProfilePageParams) error {
126
+
return p.execute("user/profile", w, params)
127
}
appview/pages/profile.html
appview/pages/templates/user/profile.html
appview/pages/profile.html
appview/pages/templates/user/profile.html
appview/pages/settings.html
appview/pages/templates/settings/keys.html
appview/pages/settings.html
appview/pages/templates/settings/keys.html
+10
appview/pages/templates/errors/404.html
+10
appview/pages/templates/errors/404.html
+10
appview/pages/templates/errors/500.html
+10
appview/pages/templates/errors/500.html
+21
appview/pages/templates/index.html
+21
appview/pages/templates/index.html
···
···
1
+
<html>
2
+
{{ template "layouts/head" . }}
3
+
4
+
<header>
5
+
<h1>{{ .meta.Title }}</h1>
6
+
<h2>{{ .meta.Description }}</h2>
7
+
</header>
8
+
<body>
9
+
<main>
10
+
<div class="index">
11
+
{{ range .info }}
12
+
<div class="index-name">
13
+
<a href="/{{ .Name }}">{{ .DisplayName }}</a>
14
+
</div>
15
+
<div class="desc">{{ .Desc }}</div>
16
+
<div>{{ .Idle }}</div>
17
+
{{ end }}
18
+
</div>
19
+
</main>
20
+
</body>
21
+
</html>
+18
appview/pages/templates/layouts/base.html
+18
appview/pages/templates/layouts/base.html
···
···
1
+
{{ define "layouts/base" }}
2
+
<!doctype html>
3
+
<html lang="en">
4
+
<head>
5
+
<meta charset="UTF-8" />
6
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+
<script
8
+
src="https://unpkg.com/htmx.org@2.0.4"
9
+
integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+"
10
+
crossorigin="anonymous"
11
+
></script>
12
+
<title>{{block "title" .}}{{end}}</title>
13
+
</head>
14
+
<body>
15
+
<main class="content">{{block "content" .}}{{end}}</main>
16
+
</body>
17
+
</html>
18
+
{{ end }}
+37
appview/pages/templates/layouts/head.html
+37
appview/pages/templates/layouts/head.html
···
···
1
+
<head>
2
+
<meta charset="utf-8" />
3
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
4
+
<link rel="stylesheet" href="/static/style.css" type="text/css" />
5
+
<link rel="icon" type="image/png" size="32x32" href="/static/legit.png" />
6
+
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
7
+
<meta name="htmx-config" content='{"selfRequestsOnly":false}' />
8
+
9
+
{{ if .parent }}
10
+
<title>
11
+
{{ .meta.Title }} — {{ .name }} ({{ .ref }}): {{ .parent }}/
12
+
</title>
13
+
14
+
{{ else if .path }}
15
+
<title>
16
+
{{ .meta.Title }} — {{ .name }} ({{ .ref }}): {{ .path }}
17
+
</title>
18
+
{{ else if .files }}
19
+
<title>{{ .meta.Title }} — {{ .name }} ({{ .ref }})</title>
20
+
{{ else if .commit }}
21
+
<title>{{ .meta.Title }} — {{ .name }}: {{ .commit.This }}</title>
22
+
{{ else if .branches }}
23
+
<title>{{ .meta.Title }} — {{ .name }}: refs</title>
24
+
{{ else if .commits }} {{ if .log }}
25
+
<title>{{ .meta.Title }} — {{ .name }}: log</title>
26
+
{{ else }}
27
+
<title>{{ .meta.Title }} — {{ .name }}</title>
28
+
{{ end }} {{ else }}
29
+
<title>{{ .meta.Title }}</title>
30
+
{{ end }} {{ if and .servername .gomod }}
31
+
<meta
32
+
name="go-import"
33
+
content="{{ .servername}}/{{ .name }} git https://{{ .servername }}/{{ .name }}"
34
+
/>
35
+
{{ end }}
36
+
<!-- other meta tags here -->
37
+
</head>
+11
appview/pages/templates/layouts/repo-header.html
+11
appview/pages/templates/layouts/repo-header.html
+5
appview/pages/templates/layouts/test.html
+5
appview/pages/templates/layouts/test.html
+100
appview/pages/templates/repo/commit.html
+100
appview/pages/templates/repo/commit.html
···
···
1
+
<html>
2
+
{{ template "layouts/head" . }}
3
+
4
+
{{ template "layouts/repo-header" . }}
5
+
<body>
6
+
{{ template "layouts/nav" . }}
7
+
<main>
8
+
<section class="commit">
9
+
<pre>{{- .commit.Message -}}</pre>
10
+
<div class="commit-info">
11
+
{{ .commit.Author.Name }} <a href="mailto:{{ .commit.Author.Email }}" class="commit-email">{{ .commit.Author.Email}}</a>
12
+
<div>{{ .commit.Author.When.Format "Mon, 02 Jan 2006 15:04:05 -0700" }}</div>
13
+
</div>
14
+
15
+
<div>
16
+
<strong>commit</strong>
17
+
<p><a href="/{{ .name }}/commit/{{ .commit.This }}" class="commit-hash">
18
+
{{ .commit.This }}
19
+
</a>
20
+
</p>
21
+
</div>
22
+
23
+
{{ if .commit.Parent }}
24
+
<div>
25
+
<strong>parent</strong>
26
+
<p><a href="/{{ .name }}/commit/{{ .commit.Parent }}" class="commit-hash">
27
+
{{ .commit.Parent }}
28
+
</a></p>
29
+
</div>
30
+
31
+
{{ end }}
32
+
<div class="diff-stat">
33
+
<div>
34
+
{{ .stat.FilesChanged }} files changed,
35
+
{{ .stat.Insertions }} insertions(+),
36
+
{{ .stat.Deletions }} deletions(-)
37
+
</div>
38
+
<div>
39
+
<br>
40
+
<strong>jump to</strong>
41
+
{{ range .diff }}
42
+
<ul>
43
+
<li><a href="#{{ .Name.New }}">{{ .Name.New }}</a></li>
44
+
</ul>
45
+
{{ end }}
46
+
</div>
47
+
</div>
48
+
</section>
49
+
<section>
50
+
{{ $repo := .name }}
51
+
{{ $this := .commit.This }}
52
+
{{ $parent := .commit.Parent }}
53
+
{{ range .diff }}
54
+
<div id="{{ .Name.New }}">
55
+
<div class="diff">
56
+
{{ if .IsNew }}
57
+
<span class="diff-type">A</span>
58
+
{{ end }}
59
+
{{ if .IsDelete }}
60
+
<span class="diff-type">D</span>
61
+
{{ end }}
62
+
{{ if not (or .IsNew .IsDelete) }}
63
+
<span class="diff-type">M</span>
64
+
{{ end }}
65
+
{{ if .Name.Old }}
66
+
<a href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}">{{ .Name.Old }}</a>
67
+
{{ if .Name.New }}
68
+
→
69
+
<a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a>
70
+
{{ end }}
71
+
{{ else }}
72
+
<a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a>
73
+
{{- end -}}
74
+
{{ if .IsBinary }}
75
+
<p>Not showing binary file.</p>
76
+
{{ else }}
77
+
<pre>
78
+
{{- range .TextFragments -}}
79
+
<p>{{- .Header -}}</p>
80
+
{{- range .Lines -}}
81
+
{{- if eq .Op.String "+" -}}
82
+
<span class="diff-add">{{ .String }}</span>
83
+
{{- end -}}
84
+
{{- if eq .Op.String "-" -}}
85
+
<span class="diff-del">{{ .String }}</span>
86
+
{{- end -}}
87
+
{{- if eq .Op.String " " -}}
88
+
<span class="diff-noop">{{ .String }}</span>
89
+
{{- end -}}
90
+
{{- end -}}
91
+
{{- end -}}
92
+
{{- end -}}
93
+
</pre>
94
+
</div>
95
+
</div>
96
+
{{ end }}
97
+
</section>
98
+
</main>
99
+
</body>
100
+
</html>
+9
appview/pages/templates/repo/empty.html
+9
appview/pages/templates/repo/empty.html
+34
appview/pages/templates/repo/file.html
+34
appview/pages/templates/repo/file.html
···
···
1
+
<html>
2
+
{{ template "layouts/head" . }}
3
+
{{ template "layouts/repo-header" . }}
4
+
<body>
5
+
{{ template "layouts/nav" . }}
6
+
<main>
7
+
<p>{{ .path }} (<a style="color: gray" href="?raw=true">view raw</a>)</p>
8
+
{{if .chroma }}
9
+
<div class="chroma-file-wrapper">
10
+
{{ .content }}
11
+
</div>
12
+
{{else}}
13
+
<div class="file-wrapper">
14
+
<table>
15
+
<tbody><tr>
16
+
<td class="line-numbers">
17
+
<pre>
18
+
{{- range .linecount }}
19
+
<a id="L{{ . }}" href="#L{{ . }}">{{ . }}</a>
20
+
{{- end -}}
21
+
</pre>
22
+
</td>
23
+
<td class="file-content">
24
+
<pre>
25
+
{{- .content -}}
26
+
</pre>
27
+
</td>
28
+
</tbody></tr>
29
+
</table>
30
+
</div>
31
+
{{end}}
32
+
</main>
33
+
</body>
34
+
</html>
+23
appview/pages/templates/repo/log.html
+23
appview/pages/templates/repo/log.html
···
···
1
+
<html>
2
+
{{ template "layouts/head" . }}
3
+
4
+
{{ template "layouts/repo-header" . }}
5
+
<body>
6
+
{{ template "layouts/nav" . }}
7
+
<main>
8
+
{{ $repo := .name }}
9
+
<div class="log">
10
+
{{ range .commits }}
11
+
<div>
12
+
<div><a href="/{{ $repo }}/commit/{{ .Hash.String }}" class="commit-hash">{{ slice .Hash.String 0 8 }}</a></div>
13
+
<pre>{{ .Message }}</pre>
14
+
</div>
15
+
<div class="commit-info">
16
+
{{ .Author.Name }} <a href="mailto:{{ .Author.Email }}" class="commit-email">{{ .Author.Email }}</a>
17
+
<div>{{ .Author.When.Format "Mon, 02 Jan 2006 15:04:05 -0700" }}</div>
18
+
</div>
19
+
{{ end }}
20
+
</div>
21
+
</main>
22
+
</body>
23
+
</html>
+14
appview/pages/templates/repo/new.html
+14
appview/pages/templates/repo/new.html
···
···
1
+
{{define "title"}}new repo{{end}}
2
+
3
+
{{define "content"}}
4
+
<h1>new repo</h1>
5
+
<form method="POST" action="/repo/new">
6
+
<label for="name">repo name</label>
7
+
<input type="text" id="name" name="name" required />
8
+
9
+
<label for="domain">domain</label>
10
+
<input type="domain" id="domain" name="domain" required />
11
+
12
+
<button type="submit">create repo</button>
13
+
</form>
14
+
{{end}}
+38
appview/pages/templates/repo/refs.html
+38
appview/pages/templates/repo/refs.html
···
···
1
+
<html>
2
+
{{ template "layouts/head" . }}
3
+
4
+
{{ template "layouts/repo-header" . }}
5
+
<body>
6
+
{{ template "layouts/nav" . }}
7
+
<main>
8
+
{{ $name := .name }}
9
+
<h3>branches</h3>
10
+
<div class="refs">
11
+
{{ range .branches }}
12
+
<div>
13
+
<strong>{{ .Name.Short }}</strong>
14
+
<a href="/{{ $name }}/tree/{{ .Name.Short }}/">browse</a>
15
+
<a href="/{{ $name }}/log/{{ .Name.Short }}">log</a>
16
+
<a href="/{{ $name }}/archive/{{ .Name.Short }}.tar.gz">tar.gz</a>
17
+
</div>
18
+
{{ end }}
19
+
</div>
20
+
{{ if .tags }}
21
+
<h3>tags</h3>
22
+
<div class="refs">
23
+
{{ range .tags }}
24
+
<div>
25
+
<strong>{{ .Name }}</strong>
26
+
<a href="/{{ $name }}/tree/{{ .Name }}/">browse</a>
27
+
<a href="/{{ $name }}/log/{{ .Name }}">log</a>
28
+
<a href="/{{ $name }}/archive/{{ .Name }}.tar.gz">tar.gz</a>
29
+
{{ if .Message }}
30
+
<pre>{{ .Message }}</pre>
31
+
</div>
32
+
{{ end }}
33
+
{{ end }}
34
+
</div>
35
+
{{ end }}
36
+
</main>
37
+
</body>
38
+
</html>
+36
appview/pages/templates/repo/repo.html
+36
appview/pages/templates/repo/repo.html
···
···
1
+
<html>
2
+
{{ template "layouts/head" . }}
3
+
4
+
{{ template "layouts/repo-header" . }}
5
+
6
+
<body>
7
+
{{ template "layouts/nav" . }}
8
+
<main>
9
+
{{ $repo := .name }}
10
+
<div class="log">
11
+
{{ range .commits }}
12
+
<div>
13
+
<div><a href="/{{ $repo }}/commit/{{ .Hash.String }}" class="commit-hash">{{ slice .Hash.String 0 8 }}</a></div>
14
+
<pre>{{ .Message }}</pre>
15
+
</div>
16
+
<div class="commit-info">
17
+
{{ .Author.Name }} <a href="mailto:{{ .Author.Email }}" class="commit-email">{{ .Author.Email }}</a>
18
+
<div>{{ .Author.When.Format "Mon, 02 Jan 2006 15:04:05 -0700" }}</div>
19
+
</div>
20
+
{{ end }}
21
+
</div>
22
+
{{- if .readme }}
23
+
<article class="readme">
24
+
{{- .readme -}}
25
+
</article>
26
+
{{- end -}}
27
+
28
+
<div class="clone-url">
29
+
<strong>clone</strong>
30
+
<pre>
31
+
git clone https://{{ .servername }}/{{ .name }}
32
+
</pre>
33
+
</div>
34
+
</main>
35
+
</body>
36
+
</html>
+53
appview/pages/templates/repo/tree.html
+53
appview/pages/templates/repo/tree.html
···
···
1
+
<html>
2
+
3
+
{{ template "layouts/head" . }}
4
+
5
+
{{ template "layouts/repo-header" . }}
6
+
<body>
7
+
{{ template "layouts/nav" . }}
8
+
<main>
9
+
{{ $repo := .name }}
10
+
{{ $ref := .ref }}
11
+
{{ $parent := .parent }}
12
+
13
+
<div class="tree">
14
+
{{ if $parent }}
15
+
<div></div>
16
+
<div></div>
17
+
<div><a href="/{{ $repo }}/tree/{{ $ref }}/{{ .dotdot }}">..</a></div>
18
+
{{ end }}
19
+
{{ range .files }}
20
+
{{ if not .IsFile }}
21
+
<div class="mode">{{ .Mode }}</div>
22
+
<div class="size">{{ .Size }}</div>
23
+
<div>
24
+
{{ if $parent }}
25
+
<a href="/{{ $repo }}/tree/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}/</a>
26
+
{{ else }}
27
+
<a href="/{{ $repo }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a>
28
+
{{ end }}
29
+
</div>
30
+
{{ end }}
31
+
{{ end }}
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="/{{ $repo }}/blob/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}</a>
39
+
{{ else }}
40
+
<a href="/{{ $repo }}/blob/{{ $ref }}/{{ .Name }}">{{ .Name }}</a>
41
+
{{ end }}
42
+
</div>
43
+
{{ end }}
44
+
{{ end }}
45
+
</div>
46
+
<article>
47
+
<pre>
48
+
{{- if .readme }}{{ .readme }}{{- end -}}
49
+
</pre>
50
+
</article>
51
+
</main>
52
+
</body>
53
+
</html>
+12
appview/pages/templates/user/login.html
+12
appview/pages/templates/user/login.html
···
···
1
+
{{ define "title" }}login{{end}} {{define "content"}}
2
+
<h1>login</h1>
3
+
<form method="POST" action="/login">
4
+
<label for="handle">handle</label>
5
+
<input type="text" id="handle" name="handle" required />
6
+
7
+
<label for="app_password">app password</label>
8
+
<input type="password" id="app_password" name="app_password" required />
9
+
10
+
<button type="submit">login</button>
11
+
</form>
12
+
{{end}}
appview/pages/timeline.html
appview/pages/templates/timeline.html
appview/pages/timeline.html
appview/pages/templates/timeline.html
+14
-9
appview/state/state.go
+14
-9
appview/state/state.go
···
29
auth *auth.Auth
30
enforcer *rbac.Enforcer
31
tidClock *syntax.TIDClock
32
}
33
34
func Make() (*State, error) {
35
-
36
db, err := db.Make(appview.SqliteDbPath)
37
if err != nil {
38
return nil, err
···
50
51
clock := syntax.NewTIDClock(0)
52
53
-
return &State{db, auth, enforcer, clock}, nil
54
}
55
56
func (s *State) TID() string {
···
62
63
switch r.Method {
64
case http.MethodGet:
65
-
pages.Login(w, pages.LoginParams{})
66
return
67
case http.MethodPost:
68
handle := r.FormValue("handle")
···
99
100
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
101
user := s.auth.GetUser(r)
102
-
pages.Timeline(w, pages.TimelineParams{
103
User: user,
104
})
105
return
···
149
log.Println(err)
150
}
151
152
-
pages.Settings(w, pages.SettingsParams{
153
User: user,
154
PubKeys: pubKeys,
155
})
···
358
IsOwner: isOwner,
359
}
360
361
-
pages.Knot(w, p)
362
}
363
364
// get knots registered by this user
···
370
log.Println(err)
371
}
372
373
-
pages.Knots(w, pages.KnotsParams{
374
User: user,
375
Registrations: registrations,
376
})
···
475
func (s *State) AddRepo(w http.ResponseWriter, r *http.Request) {
476
switch r.Method {
477
case http.MethodGet:
478
-
pages.NewRepo(w, pages.NewRepoParams{
479
User: s.auth.GetUser(r),
480
})
481
case http.MethodPost:
···
562
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
563
}
564
565
-
pages.ProfilePage(w, pages.ProfilePageParams{
566
LoggedInUser: s.auth.GetUser(r),
567
UserDid: ident.DID.String(),
568
UserHandle: ident.Handle.String(),
···
29
auth *auth.Auth
30
enforcer *rbac.Enforcer
31
tidClock *syntax.TIDClock
32
+
pages *pages.Pages
33
}
34
35
func Make() (*State, error) {
36
db, err := db.Make(appview.SqliteDbPath)
37
if err != nil {
38
return nil, err
···
50
51
clock := syntax.NewTIDClock(0)
52
53
+
pgs := pages.NewPages()
54
+
55
+
return &State{db, auth, enforcer, clock, pgs}, nil
56
}
57
58
func (s *State) TID() string {
···
64
65
switch r.Method {
66
case http.MethodGet:
67
+
err := s.pages.Login(w, pages.LoginParams{})
68
+
if err != nil {
69
+
log.Printf("rendering login page: %s", err)
70
+
}
71
return
72
case http.MethodPost:
73
handle := r.FormValue("handle")
···
104
105
func (s *State) Timeline(w http.ResponseWriter, r *http.Request) {
106
user := s.auth.GetUser(r)
107
+
s.pages.Timeline(w, pages.TimelineParams{
108
User: user,
109
})
110
return
···
154
log.Println(err)
155
}
156
157
+
s.pages.Settings(w, pages.SettingsParams{
158
User: user,
159
PubKeys: pubKeys,
160
})
···
363
IsOwner: isOwner,
364
}
365
366
+
s.pages.Knot(w, p)
367
}
368
369
// get knots registered by this user
···
375
log.Println(err)
376
}
377
378
+
s.pages.Knots(w, pages.KnotsParams{
379
User: user,
380
Registrations: registrations,
381
})
···
480
func (s *State) AddRepo(w http.ResponseWriter, r *http.Request) {
481
switch r.Method {
482
case http.MethodGet:
483
+
s.pages.NewRepo(w, pages.NewRepoParams{
484
User: s.auth.GetUser(r),
485
})
486
case http.MethodPost:
···
567
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
568
}
569
570
+
s.pages.ProfilePage(w, pages.ProfilePageParams{
571
LoggedInUser: s.auth.GetUser(r),
572
UserDid: ident.DID.String(),
573
UserHandle: ident.Handle.String(),