feature: show starred repos on homescreen #23

closed
opened by dvjn.dev targeting master

show starred repos by the user on the user's homescreen

Changed files
+113
appview
db
pages
state
+63
appview/db/repos.go
··· 243 243 return repos, nil 244 244 } 245 245 246 + func GetStarredRepos(e Execer, did string) ([]Repo, error) { 247 + var repos []Repo 248 + 249 + rows, err := e.Query( 250 + `select 251 + r.did, 252 + r.name, 253 + r.knot, 254 + r.rkey, 255 + r.description, 256 + r.created, 257 + count(s.id) as star_count 258 + from 259 + repos r 260 + join 261 + stars s on r.at_uri = s.repo_at 262 + left join 263 + stars su on r.at_uri = su.repo_at 264 + where 265 + su.starred_by_did = ? 266 + group by 267 + r.at_uri`, did) 268 + if err != nil { 269 + return nil, err 270 + } 271 + defer rows.Close() 272 + 273 + for rows.Next() { 274 + var repo Repo 275 + var repoStats RepoStats 276 + var createdAt string 277 + var nullableDescription sql.NullString 278 + 279 + err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount) 280 + if err != nil { 281 + return nil, err 282 + } 283 + 284 + if nullableDescription.Valid { 285 + repo.Description = nullableDescription.String 286 + } else { 287 + repo.Description = "" 288 + } 289 + 290 + createdAtTime, err := time.Parse(time.RFC3339, createdAt) 291 + if err != nil { 292 + repo.Created = time.Now() 293 + } else { 294 + repo.Created = createdAtTime 295 + } 296 + 297 + repo.RepoStats = &repoStats 298 + 299 + repos = append(repos, repo) 300 + } 301 + 302 + if err := rows.Err(); err != nil { 303 + return nil, err 304 + } 305 + 306 + return repos, nil 307 + } 308 + 246 309 type RepoStats struct { 247 310 StarCount int 248 311 IssueCount IssueCount
+1
appview/pages/pages.go
··· 111 111 type TimelineParams struct { 112 112 LoggedInUser *auth.User 113 113 Timeline []db.TimelineEvent 114 + StarredRepos []db.Repo 114 115 DidHandleMap map[string]string 115 116 } 116 117
+40
appview/pages/templates/timeline.html
··· 9 9 10 10 {{ define "content" }} 11 11 {{ with .LoggedInUser }} 12 + {{ block "starredRepos" $ }} {{ end }} 12 13 {{ block "timeline" $ }} {{ end }} 13 14 {{ else }} 14 15 {{ block "hero" $ }} {{ end }} ··· 29 30 </div> 30 31 {{ end }} 31 32 33 + {{ define "starredRepos" }} 34 + <div> 35 + <div class="p-6"> 36 + <p class="text-xl font-bold dark:text-white">Starred Repos</p> 37 + </div> 38 + <div id="repos" class="grid grid-cols-1 lg:grid-cols-3 md:grid-cols-2 gap-4 mb-6"> 39 + {{ range .StarredRepos }} 40 + <div 41 + id="repo-card" 42 + class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800" 43 + > 44 + <div id="repo-card-name" class="font-medium dark:text-white"> 45 + <a href="/{{ .Did }}/{{ .Name }}" 46 + >{{ .Name }}</a 47 + > 48 + </div> 49 + {{ if .Description }} 50 + <div class="text-gray-600 dark:text-gray-300 text-sm"> 51 + {{ .Description }} 52 + </div> 53 + {{ end }} 54 + <div 55 + class="text-gray-400 pt-1 text-sm font-mono inline-flex gap-4 mt-auto" 56 + > 57 + {{ if .RepoStats.StarCount }} 58 + <div class="flex gap-1 items-center text-sm"> 59 + {{ i "star" "w-3 h-3 fill-current" }} 60 + <span>{{ .RepoStats.StarCount }}</span> 61 + </div> 62 + {{ end }} 63 + </div> 64 + </div> 65 + {{ else }} 66 + <p class="px-6 dark:text-white">You have not starred any repos yet.</p> 67 + {{ end }} 68 + </div> 69 + </div> 70 + {{ end }} 71 + 32 72 {{ define "timeline" }} 33 73 <div> 34 74 <div class="p-6">
+9
appview/state/state.go
··· 209 209 } 210 210 } 211 211 212 + var starredRepos []db.Repo 213 + if user != nil { 214 + starredRepos, err = db.GetStarredRepos(s.db, user.Did) 215 + if err != nil { 216 + log.Println(err) 217 + } 218 + } 219 + 212 220 s.pages.Timeline(w, pages.TimelineParams{ 213 221 LoggedInUser: user, 214 222 Timeline: timeline, 215 223 DidHandleMap: didHandleMap, 224 + StarredRepos: starredRepos, 216 225 }) 217 226 218 227 return