forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

appview: state: dedup profile pages

- rename existing ProfilePage to ProfileHomePage

Signed-off-by: dusk <y.bera003.06@protonmail.com>

authored by ptr.pet and committed by Tangled 4e5b1f20 5b6b7aea

Changed files
+112 -124
appview
pages
state
+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
··· 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