appview/appview
appview/appview
This is a binary file and will not be displayed.
+6
appview/db/db.go
+6
appview/db/db.go
···
49
49
created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
50
50
unique(did, name, knot)
51
51
);
52
+
create table if not exists collaborators (
53
+
id integer primary key autoincrement,
54
+
did text not null,
55
+
repo integer not null,
56
+
foreign key (repo) references repos(id) on delete cascade
57
+
);
52
58
create table if not exists follows (
53
59
user_did text not null,
54
60
subject_did text not null,
+57
-7
appview/db/repos.go
+57
-7
appview/db/repos.go
···
1
1
package db
2
2
3
-
import "time"
3
+
import (
4
+
"database/sql"
5
+
"time"
6
+
)
4
7
5
8
type Repo struct {
6
9
Did string
···
19
22
defer rows.Close()
20
23
21
24
for rows.Next() {
22
-
var repo Repo
23
-
var createdAt string
24
-
if err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt); err != nil {
25
+
repo, err := scanRepo(rows)
26
+
if err != nil {
25
27
return nil, err
26
28
}
27
-
createdAtTime, _ := time.Parse(time.RFC3339, createdAt)
28
-
repo.Created = &createdAtTime
29
-
repos = append(repos, repo)
29
+
repos = append(repos, *repo)
30
30
}
31
31
32
32
if err := rows.Err(); err != nil {
···
60
60
_, err := d.db.Exec(`delete from repos where did = ? and name = ? and knot = ?`, did, name, knot)
61
61
return err
62
62
}
63
+
64
+
func (d *DB) AddCollaborator(collaborator, repoOwnerDid, repoName, repoKnot string) error {
65
+
_, err := d.db.Exec(
66
+
`insert into collaborators (did, repo)
67
+
values (?, (select id from repos where did = ? and name = ? and knot = ?));`,
68
+
collaborator, repoOwnerDid, repoName, repoKnot)
69
+
return err
70
+
}
71
+
72
+
func (d *DB) CollaboratingIn(collaborator string) ([]Repo, error) {
73
+
var repos []Repo
74
+
75
+
rows, err := d.db.Query(`select r.* from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator)
76
+
if err != nil {
77
+
return nil, err
78
+
}
79
+
defer rows.Close()
80
+
81
+
for rows.Next() {
82
+
repo, err := scanRepo(rows)
83
+
if err != nil {
84
+
return nil, err
85
+
}
86
+
repos = append(repos, *repo)
87
+
}
88
+
89
+
if err := rows.Err(); err != nil {
90
+
return nil, err
91
+
}
92
+
93
+
return repos, nil
94
+
}
95
+
96
+
func scanRepo(rows *sql.Rows) (*Repo, error) {
97
+
var repo Repo
98
+
var createdAt string
99
+
if err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt); err != nil {
100
+
return nil, err
101
+
}
102
+
103
+
createdAtTime, err := time.Parse(time.RFC3339, createdAt)
104
+
if err != nil {
105
+
now := time.Now()
106
+
repo.Created = &now
107
+
}
108
+
109
+
repo.Created = &createdAtTime
110
+
111
+
return &repo, nil
112
+
}
+11
-4
appview/pages/pages.go
+11
-4
appview/pages/pages.go
···
29
29
"split": func(s string) []string {
30
30
return strings.Split(s, "\n")
31
31
},
32
+
"splitOn": func(s, sep string) []string {
33
+
return strings.Split(s, sep)
34
+
},
32
35
"add": func(a, b int) int {
33
36
return a + b
34
37
},
···
89
92
}
90
93
91
94
return strings.Join(paragraphs, "\n\n")
95
+
},
96
+
"sequence": func(n int) []struct{} {
97
+
return make([]struct{}, n)
92
98
},
93
99
}
94
100
}
···
200
206
}
201
207
202
208
type ProfilePageParams struct {
203
-
LoggedInUser *auth.User
204
-
UserDid string
205
-
UserHandle string
206
-
Repos []db.Repo
209
+
LoggedInUser *auth.User
210
+
UserDid string
211
+
UserHandle string
212
+
Repos []db.Repo
213
+
CollaboratingRepos []db.Repo
207
214
}
208
215
209
216
func (p *Pages) ProfilePage(w io.Writer, params ProfilePageParams) error {
+5
-4
appview/pages/templates/repo/commit.html
+5
-4
appview/pages/templates/repo/commit.html
···
102
102
{{ else }}
103
103
<pre class="overflow-auto">
104
104
{{- range .TextFragments -}}
105
-
<div class="bg-gray-100 text-gray-500">{{ nl2br .Header }}</div>
105
+
<div class="bg-gray-100 text-gray-500 select-none">{{ .Comment }}</div>
106
+
106
107
{{- range .Lines -}}
107
108
{{- if eq .Op.String "+" -}}
108
-
<div class="bg-green-100 text-green-700">{{ .String }}</div>
109
+
<div class="bg-green-100 text-green-700"><span class="select-none">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
109
110
{{- end -}}
110
111
111
112
{{- if eq .Op.String "-" -}}
112
-
<div class="bg-red-100 text-red-700">{{ .String }}</div>
113
+
<div class="bg-red-100 text-red-700"><span class="select-none">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
113
114
{{- end -}}
114
115
115
116
{{- if eq .Op.String " " -}}
116
-
<div class="text-gray-500">{{ .String }}</div>
117
+
<div class="text-gray-500"><span class="select-none">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
117
118
{{- end -}}
118
119
119
120
{{- end -}}
+25
-1
appview/pages/templates/user/profile.html
+25
-1
appview/pages/templates/user/profile.html
···
2
2
3
3
{{ define "content" }}
4
4
<h1>{{ didOrHandle .UserDid .UserHandle }}</h1>
5
-
<div id="my-repos" class="grid grid-cols-1 md:grid-cols-2 gap-4">
5
+
<p class="text-xs font-bold py-2">REPOS</p>
6
+
<div id="repos" class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
6
7
{{ range .Repos }}
7
8
<div
8
9
id="repo-card"
···
22
23
</div>
23
24
{{ else }}
24
25
<p>This user does not have any repos yet.</p>
26
+
{{ end }}
27
+
</div>
28
+
<p class="text-xs font-bold py-2">COLLABORATING ON</p>
29
+
<div id="collaborating" class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
30
+
{{ range .CollaboratingRepos }}
31
+
<div
32
+
id="repo-card"
33
+
class="border border-black p-4 shadow-sm bg-white"
34
+
>
35
+
<div id="repo-card-name" class="font-medium">
36
+
<a href="/@{{ or $.UserHandle $.UserDid }}/{{ .Name }}">
37
+
@{{ or $.UserHandle $.UserDid }}/{{ .Name }}
38
+
</a>
39
+
</div>
40
+
<div
41
+
id="repo-knot-name"
42
+
class="text-gray-600 text-sm font-mono"
43
+
>
44
+
{{ .Knot }}
45
+
</div>
46
+
</div>
47
+
{{ else }}
48
+
<p>This user is not collaborating.</p>
25
49
{{ end }}
26
50
</div>
27
51
{{ end }}
+6
appview/state/repo.go
+6
appview/state/repo.go
···
393
393
return
394
394
}
395
395
396
+
err = s.db.AddCollaborator(collaboratorIdent.DID.String(), f.OwnerDid(), f.RepoName, f.Knot)
397
+
if err != nil {
398
+
w.Write([]byte(fmt.Sprint("failed to add collaborator: ", err)))
399
+
return
400
+
}
401
+
396
402
w.Write([]byte(fmt.Sprint("added collaborator: ", collaboratorIdent.Handle.String())))
397
403
398
404
}
+10
-4
appview/state/state.go
+10
-4
appview/state/state.go
···
580
580
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
581
581
}
582
582
583
+
collaboratingRepos, err := s.db.CollaboratingIn(ident.DID.String())
584
+
if err != nil {
585
+
log.Printf("getting collaborating repos for %s: %s", ident.DID.String(), err)
586
+
}
587
+
583
588
s.pages.ProfilePage(w, pages.ProfilePageParams{
584
-
LoggedInUser: s.auth.GetUser(r),
585
-
UserDid: ident.DID.String(),
586
-
UserHandle: ident.Handle.String(),
587
-
Repos: repos,
589
+
LoggedInUser: s.auth.GetUser(r),
590
+
UserDid: ident.DID.String(),
591
+
UserHandle: ident.Handle.String(),
592
+
Repos: repos,
593
+
CollaboratingRepos: collaboratingRepos,
588
594
})
589
595
}
590
596
+2
-2
knotserver/git/diff.go
+2
-2
knotserver/git/diff.go