+2
-2
appview/pages/pages.go
+2
-2
appview/pages/pages.go
···
408
return p.execute("repo/fork", w, params)
409
}
410
411
-
type ProfilePageParams struct {
412
LoggedInUser *oauth.User
413
Repos []db.Repo
414
CollaboratingRepos []db.Repo
···
427
Profile *db.Profile
428
}
429
430
-
func (p *Pages) ProfilePage(w io.Writer, params ProfilePageParams) error {
431
return p.execute("user/profile", w, params)
432
}
433
···
408
return p.execute("repo/fork", w, params)
409
}
410
411
+
type ProfileHomePageParams struct {
412
LoggedInUser *oauth.User
413
Repos []db.Repo
414
CollaboratingRepos []db.Repo
···
427
Profile *db.Profile
428
}
429
430
+
func (p *Pages) ProfileHomePage(w io.Writer, params ProfileHomePageParams) error {
431
return p.execute("user/profile", w, params)
432
}
433
+110
-122
appview/state/profile.go
+110
-122
appview/state/profile.go
···
2
3
import (
4
"context"
5
-
"errors"
6
"fmt"
7
"log"
8
"net/http"
···
26
tabVal := r.URL.Query().Get("tab")
27
switch tabVal {
28
case "":
29
-
s.profilePage(w, r)
30
case "repos":
31
s.reposPage(w, r)
32
case "followers":
···
36
}
37
}
38
39
-
func (s *State) profilePage(w http.ResponseWriter, r *http.Request) {
40
didOrHandle := chi.URLParam(r, "user")
41
if didOrHandle == "" {
42
-
http.Error(w, "Bad request", http.StatusBadRequest)
43
-
return
44
}
45
46
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
47
if !ok {
48
-
s.pages.Error404(w)
49
-
return
50
}
51
52
-
profile, err := db.GetProfile(s.db, ident.DID.String())
53
if err != nil {
54
-
log.Printf("getting profile data for %s: %s", ident.DID.String(), err)
55
}
56
57
repos, err := db.GetRepos(
58
s.db,
59
0,
60
-
db.FilterEq("did", ident.DID.String()),
61
)
62
if err != nil {
63
-
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
64
}
65
66
// filter out ones that are pinned
67
pinnedRepos := []db.Repo{}
68
for i, r := range repos {
···
77
}
78
}
79
80
-
collaboratingRepos, err := db.CollaboratingIn(s.db, ident.DID.String())
81
if err != nil {
82
-
log.Printf("getting collaborating repos for %s: %s", ident.DID.String(), err)
83
}
84
85
pinnedCollaboratingRepos := []db.Repo{}
···
90
}
91
}
92
93
-
timeline, err := db.MakeProfileTimeline(s.db, ident.DID.String())
94
if err != nil {
95
-
log.Printf("failed to create profile timeline for %s: %s", ident.DID.String(), err)
96
}
97
98
-
followers, following, err := db.GetFollowerFollowingCount(s.db, ident.DID.String())
99
-
if err != nil {
100
-
log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err)
101
}
102
-
103
-
loggedInUser := s.oauth.GetUser(r)
104
-
followStatus := db.IsNotFollowing
105
-
if loggedInUser != nil {
106
-
followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, ident.DID.String())
107
}
108
109
now := time.Now()
110
startOfYear := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
111
punchcard, err := db.MakePunchcard(
112
s.db,
113
-
db.FilterEq("did", ident.DID.String()),
114
db.FilterGte("date", startOfYear.Format(time.DateOnly)),
115
db.FilterLte("date", now.Format(time.DateOnly)),
116
)
117
if err != nil {
118
-
log.Println("failed to get punchcard for did", "did", ident.DID.String(), "err", err)
119
}
120
121
-
s.pages.ProfilePage(w, pages.ProfilePageParams{
122
-
LoggedInUser: loggedInUser,
123
Repos: pinnedRepos,
124
CollaboratingRepos: pinnedCollaboratingRepos,
125
-
Card: pages.ProfileCard{
126
-
UserDid: ident.DID.String(),
127
-
UserHandle: ident.Handle.String(),
128
-
Profile: profile,
129
-
FollowStatus: followStatus,
130
-
FollowersCount: followers,
131
-
FollowingCount: following,
132
-
},
133
-
Punchcard: punchcard,
134
-
ProfileTimeline: timeline,
135
})
136
}
137
138
func (s *State) reposPage(w http.ResponseWriter, r *http.Request) {
139
-
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
140
-
if !ok {
141
-
s.pages.Error404(w)
142
return
143
}
144
145
-
profile, err := db.GetProfile(s.db, ident.DID.String())
146
-
if err != nil {
147
-
log.Printf("getting profile data for %s: %s", ident.DID.String(), err)
148
-
}
149
-
150
repos, err := db.GetRepos(
151
s.db,
152
0,
153
-
db.FilterEq("did", ident.DID.String()),
154
)
155
if err != nil {
156
-
log.Printf("getting repos for %s: %s", ident.DID.String(), err)
157
-
}
158
-
159
-
loggedInUser := s.oauth.GetUser(r)
160
-
followStatus := db.IsNotFollowing
161
-
if loggedInUser != nil {
162
-
followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, ident.DID.String())
163
-
}
164
-
165
-
followers, following, err := db.GetFollowerFollowingCount(s.db, ident.DID.String())
166
-
if err != nil {
167
-
log.Printf("getting follow stats repos for %s: %s", ident.DID.String(), err)
168
}
169
170
s.pages.ReposPage(w, pages.ReposPageParams{
171
-
LoggedInUser: loggedInUser,
172
Repos: repos,
173
-
Card: pages.ProfileCard{
174
-
UserDid: ident.DID.String(),
175
-
UserHandle: ident.Handle.String(),
176
-
Profile: profile,
177
-
FollowStatus: followStatus,
178
-
FollowersCount: followers,
179
-
FollowingCount: following,
180
-
},
181
})
182
}
183
···
188
}
189
190
func (s *State) followPage(w http.ResponseWriter, r *http.Request, fetchFollows func(db.Execer, string) ([]db.Follow, error), extractDid func(db.Follow) string) (FollowsPageParams, error) {
191
-
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
192
-
if !ok {
193
-
s.pages.Error404(w)
194
-
return FollowsPageParams{}, errors.New("identity not found")
195
-
}
196
-
did := ident.DID.String()
197
-
198
-
profile, err := db.GetProfile(s.db, did)
199
-
if err != nil {
200
-
log.Printf("getting profile data for %s: %s", did, err)
201
-
return FollowsPageParams{}, err
202
-
}
203
-
204
-
loggedInUser := s.oauth.GetUser(r)
205
-
206
-
follows, err := fetchFollows(s.db, did)
207
-
if err != nil {
208
-
log.Printf("getting followers for %s: %s", did, err)
209
-
return FollowsPageParams{}, err
210
-
}
211
-
212
-
var loggedInUserFollowing map[string]struct{}
213
-
if loggedInUser != nil {
214
-
following, err := db.GetFollowing(s.db, loggedInUser.Did)
215
-
if err != nil {
216
-
return FollowsPageParams{}, err
217
-
}
218
-
if len(following) > 0 {
219
-
loggedInUserFollowing = make(map[string]struct{}, len(following))
220
-
for _, follow := range following {
221
-
loggedInUserFollowing[follow.SubjectDid] = struct{}{}
222
-
}
223
-
}
224
}
225
226
-
followStatus := db.IsNotFollowing
227
-
if loggedInUser != nil {
228
-
followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, did)
229
-
}
230
231
-
followersCount, followingCount, err := db.GetFollowerFollowingCount(s.db, did)
232
if err != nil {
233
-
log.Printf("getting follow stats followers for %s: %s", did, err)
234
return FollowsPageParams{}, err
235
}
236
···
238
return FollowsPageParams{
239
LoggedInUser: loggedInUser,
240
Follows: []pages.FollowCard{},
241
-
Card: pages.ProfileCard{
242
-
UserDid: did,
243
-
UserHandle: ident.Handle.String(),
244
-
Profile: profile,
245
-
FollowStatus: followStatus,
246
-
FollowersCount: followersCount,
247
-
FollowingCount: followingCount,
248
-
},
249
}, nil
250
}
251
···
258
if err != nil {
259
log.Printf("getting profile for %s: %s", followDids, err)
260
return FollowsPageParams{}, err
261
}
262
263
followCards := make([]pages.FollowCard, 0, len(follows))
···
293
return FollowsPageParams{
294
LoggedInUser: loggedInUser,
295
Follows: followCards,
296
-
Card: pages.ProfileCard{
297
-
UserDid: did,
298
-
UserHandle: ident.Handle.String(),
299
-
Profile: profile,
300
-
FollowStatus: followStatus,
301
-
FollowersCount: followersCount,
302
-
FollowingCount: followingCount,
303
-
},
304
}, nil
305
}
306
···
2
3
import (
4
"context"
5
"fmt"
6
"log"
7
"net/http"
···
25
tabVal := r.URL.Query().Get("tab")
26
switch tabVal {
27
case "":
28
+
s.profileHomePage(w, r)
29
case "repos":
30
s.reposPage(w, r)
31
case "followers":
···
35
}
36
}
37
38
+
type ProfilePageParams struct {
39
+
Id identity.Identity
40
+
LoggedInUser *oauth.User
41
+
Card pages.ProfileCard
42
+
}
43
+
44
+
func (s *State) profilePage(w http.ResponseWriter, r *http.Request) *ProfilePageParams {
45
didOrHandle := chi.URLParam(r, "user")
46
if didOrHandle == "" {
47
+
http.Error(w, "bad request", http.StatusBadRequest)
48
+
return nil
49
}
50
51
ident, ok := r.Context().Value("resolvedId").(identity.Identity)
52
if !ok {
53
+
log.Printf("malformed middleware")
54
+
w.WriteHeader(http.StatusInternalServerError)
55
+
return nil
56
}
57
+
did := ident.DID.String()
58
59
+
profile, err := db.GetProfile(s.db, did)
60
if err != nil {
61
+
log.Printf("getting profile data for %s: %s", did, err)
62
+
s.pages.Error500(w)
63
+
return nil
64
+
}
65
+
66
+
followersCount, followingCount, err := db.GetFollowerFollowingCount(s.db, did)
67
+
if err != nil {
68
+
log.Printf("getting follow stats for %s: %s", did, err)
69
+
}
70
+
71
+
loggedInUser := s.oauth.GetUser(r)
72
+
followStatus := db.IsNotFollowing
73
+
if loggedInUser != nil {
74
+
followStatus = db.GetFollowStatus(s.db, loggedInUser.Did, did)
75
+
}
76
+
77
+
return &ProfilePageParams{
78
+
Id: ident,
79
+
LoggedInUser: loggedInUser,
80
+
Card: pages.ProfileCard{
81
+
UserDid: did,
82
+
UserHandle: ident.Handle.String(),
83
+
Profile: profile,
84
+
FollowStatus: followStatus,
85
+
FollowersCount: followersCount,
86
+
FollowingCount: followingCount,
87
+
},
88
+
}
89
+
}
90
+
91
+
func (s *State) profileHomePage(w http.ResponseWriter, r *http.Request) {
92
+
pageWithProfile := s.profilePage(w, r)
93
+
if pageWithProfile == nil {
94
+
return
95
}
96
97
+
id := pageWithProfile.Id
98
repos, err := db.GetRepos(
99
s.db,
100
0,
101
+
db.FilterEq("did", id.DID),
102
)
103
if err != nil {
104
+
log.Printf("getting repos for %s: %s", id.DID, err)
105
}
106
107
+
profile := pageWithProfile.Card.Profile
108
// filter out ones that are pinned
109
pinnedRepos := []db.Repo{}
110
for i, r := range repos {
···
119
}
120
}
121
122
+
collaboratingRepos, err := db.CollaboratingIn(s.db, id.DID.String())
123
if err != nil {
124
+
log.Printf("getting collaborating repos for %s: %s", id.DID, err)
125
}
126
127
pinnedCollaboratingRepos := []db.Repo{}
···
132
}
133
}
134
135
+
timeline, err := db.MakeProfileTimeline(s.db, id.DID.String())
136
if err != nil {
137
+
log.Printf("failed to create profile timeline for %s: %s", id.DID, err)
138
}
139
140
+
var didsToResolve []string
141
+
for _, r := range collaboratingRepos {
142
+
didsToResolve = append(didsToResolve, r.Did)
143
}
144
+
for _, byMonth := range timeline.ByMonth {
145
+
for _, pe := range byMonth.PullEvents.Items {
146
+
didsToResolve = append(didsToResolve, pe.Repo.Did)
147
+
}
148
+
for _, ie := range byMonth.IssueEvents.Items {
149
+
didsToResolve = append(didsToResolve, ie.Metadata.Repo.Did)
150
+
}
151
+
for _, re := range byMonth.RepoEvents {
152
+
didsToResolve = append(didsToResolve, re.Repo.Did)
153
+
if re.Source != nil {
154
+
didsToResolve = append(didsToResolve, re.Source.Did)
155
+
}
156
+
}
157
}
158
159
now := time.Now()
160
startOfYear := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
161
punchcard, err := db.MakePunchcard(
162
s.db,
163
+
db.FilterEq("did", id.DID),
164
db.FilterGte("date", startOfYear.Format(time.DateOnly)),
165
db.FilterLte("date", now.Format(time.DateOnly)),
166
)
167
if err != nil {
168
+
log.Println("failed to get punchcard for did", "did", id.DID, "err", err)
169
}
170
171
+
s.pages.ProfileHomePage(w, pages.ProfileHomePageParams{
172
+
LoggedInUser: pageWithProfile.LoggedInUser,
173
Repos: pinnedRepos,
174
CollaboratingRepos: pinnedCollaboratingRepos,
175
+
Card: pageWithProfile.Card,
176
+
Punchcard: punchcard,
177
+
ProfileTimeline: timeline,
178
})
179
}
180
181
func (s *State) reposPage(w http.ResponseWriter, r *http.Request) {
182
+
pageWithProfile := s.profilePage(w, r)
183
+
if pageWithProfile == nil {
184
return
185
}
186
187
+
id := pageWithProfile.Id
188
repos, err := db.GetRepos(
189
s.db,
190
0,
191
+
db.FilterEq("did", id.DID),
192
)
193
if err != nil {
194
+
log.Printf("getting repos for %s: %s", id.DID, err)
195
}
196
197
s.pages.ReposPage(w, pages.ReposPageParams{
198
+
LoggedInUser: pageWithProfile.LoggedInUser,
199
Repos: repos,
200
+
Card: pageWithProfile.Card,
201
})
202
}
203
···
208
}
209
210
func (s *State) followPage(w http.ResponseWriter, r *http.Request, fetchFollows func(db.Execer, string) ([]db.Follow, error), extractDid func(db.Follow) string) (FollowsPageParams, error) {
211
+
pageWithProfile := s.profilePage(w, r)
212
+
if pageWithProfile == nil {
213
+
return FollowsPageParams{}, nil
214
}
215
216
+
id := pageWithProfile.Id
217
+
loggedInUser := pageWithProfile.LoggedInUser
218
219
+
follows, err := fetchFollows(s.db, id.DID.String())
220
if err != nil {
221
+
log.Printf("getting followers for %s: %s", id.DID, err)
222
return FollowsPageParams{}, err
223
}
224
···
226
return FollowsPageParams{
227
LoggedInUser: loggedInUser,
228
Follows: []pages.FollowCard{},
229
+
Card: pageWithProfile.Card,
230
}, nil
231
}
232
···
239
if err != nil {
240
log.Printf("getting profile for %s: %s", followDids, err)
241
return FollowsPageParams{}, err
242
+
}
243
+
244
+
var loggedInUserFollowing map[string]struct{}
245
+
if loggedInUser != nil {
246
+
following, err := db.GetFollowing(s.db, loggedInUser.Did)
247
+
if err != nil {
248
+
return FollowsPageParams{}, err
249
+
}
250
+
if len(following) > 0 {
251
+
loggedInUserFollowing = make(map[string]struct{}, len(following))
252
+
for _, follow := range following {
253
+
loggedInUserFollowing[follow.SubjectDid] = struct{}{}
254
+
}
255
+
}
256
}
257
258
followCards := make([]pages.FollowCard, 0, len(follows))
···
288
return FollowsPageParams{
289
LoggedInUser: loggedInUser,
290
Follows: followCards,
291
+
Card: pageWithProfile.Card,
292
}, nil
293
}
294