Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).

show stars in profile; styles for issue comments

+116 -26
+75 -4
appview/db/repos.go
··· 13 13 Created time.Time 14 14 AtUri string 15 15 Description string 16 + 17 + // optionally, populate this when querying for reverse mappings 18 + RepoStats *RepoStats 16 19 } 17 20 18 21 func GetAllRepos(e Execer, limit int) ([]Repo, error) { ··· 55 52 func GetAllReposByDid(e Execer, did string) ([]Repo, error) { 56 53 var repos []Repo 57 54 58 - rows, err := e.Query(`select did, name, knot, rkey, description, created from repos where did = ?`, did) 55 + rows, err := e.Query( 56 + `select 57 + r.did, 58 + r.name, 59 + r.knot, 60 + r.rkey, 61 + r.description, 62 + r.created, 63 + count(s.id) as star_count 64 + from 65 + repos r 66 + left join 67 + stars s on r.at_uri = s.repo_at 68 + where 69 + r.did = ? 70 + group by 71 + r.at_uri`, did) 59 72 if err != nil { 60 73 return nil, err 61 74 } ··· 79 60 80 61 for rows.Next() { 81 62 var repo Repo 82 - err := scanRepo(rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created) 63 + var repoStats RepoStats 64 + var createdAt string 65 + var nullableDescription sql.NullString 66 + 67 + err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount) 83 68 if err != nil { 84 69 return nil, err 85 70 } 71 + 72 + if nullableDescription.Valid { 73 + repo.Description = nullableDescription.String 74 + } else { 75 + repo.Description = "" 76 + } 77 + 78 + createdAtTime, err := time.Parse(time.RFC3339, createdAt) 79 + if err != nil { 80 + repo.Created = time.Now() 81 + } else { 82 + repo.Created = createdAtTime 83 + } 84 + 85 + repo.RepoStats = &repoStats 86 + 86 87 repos = append(repos, repo) 87 88 } 88 89 ··· 189 150 func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) { 190 151 var repos []Repo 191 152 192 - rows, err := e.Query(`select r.did, r.name, r.knot, r.rkey, r.description, r.created from repos r join collaborators c on r.id = c.repo where c.did = ?;`, collaborator) 153 + rows, err := e.Query( 154 + `select 155 + r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count 156 + from 157 + repos r 158 + join 159 + collaborators c on r.id = c.repo 160 + left join 161 + stars s on r.at_uri = s.repo_at 162 + where 163 + c.did = ? 164 + group by 165 + r.id;`, collaborator) 193 166 if err != nil { 194 167 return nil, err 195 168 } ··· 209 158 210 159 for rows.Next() { 211 160 var repo Repo 212 - err := scanRepo(rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created) 161 + var repoStats RepoStats 162 + var createdAt string 163 + var nullableDescription sql.NullString 164 + 165 + err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount) 213 166 if err != nil { 214 167 return nil, err 215 168 } 169 + 170 + if nullableDescription.Valid { 171 + repo.Description = nullableDescription.String 172 + } else { 173 + repo.Description = "" 174 + } 175 + 176 + createdAtTime, err := time.Parse(time.RFC3339, createdAt) 177 + if err != nil { 178 + repo.Created = time.Now() 179 + } else { 180 + repo.Created = createdAtTime 181 + } 182 + 183 + repo.RepoStats = &repoStats 184 + 216 185 repos = append(repos, repo) 217 186 } 218 187
+3 -1
appview/db/star.go
··· 10 10 type Star struct { 11 11 StarredByDid string 12 12 RepoAt syntax.ATURI 13 - Repo *Repo 14 13 Created time.Time 15 14 Rkey string 15 + 16 + // optionally, populate this when querying for reverse mappings 17 + Repo *Repo 16 18 } 17 19 18 20 func (star *Star) ResolveRepo(e Execer) error {
+6 -1
appview/pages/pages.go
··· 523 523 524 524 func Cache(h http.Handler) http.Handler { 525 525 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 526 - w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") 526 + if strings.HasSuffix(r.URL.Path, ".css") { 527 + // on day for css files 528 + w.Header().Set("Cache-Control", "public, max-age=86400") 529 + } else { 530 + w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") 531 + } 527 532 h.ServeHTTP(w, r) 528 533 }) 529 534 }
-3
appview/pages/templates/fragments/star.html
··· 22 22 <span> 23 23 {{ .Stats.StarCount }} 24 24 </span> 25 - <span id="starSpinner" class="hidden"> 26 - loading 27 - </span> 28 25 </div> 29 26 </button> 30 27 <script>
+11 -8
appview/pages/templates/repo/issues/issue.html
··· 4 4 {{ end }} 5 5 6 6 {{ define "repoContent" }} 7 - <h1> 7 + <header> 8 + <p class="text-2xl font-bold"> 8 9 {{ .Issue.Title }} 9 - <span class="text-gray-400">#{{ .Issue.IssueId }}</span> 10 - </h1> 10 + <span class="text-gray-500">#{{ .Issue.IssueId }}</span> 11 + </p> 12 + </header> 11 13 12 14 {{ $bgColor := "bg-gray-800" }} 13 15 {{ $icon := "ban" }} ··· 25 23 <i data-lucide="{{ $icon }}" class="w-4 h-4 mr-1.5 text-white" ></i> 26 24 <span class="text-white">{{ .State }}</span> 27 25 </div> 28 - <span class="text-gray-400 text-sm"> 26 + <span class="text-gray-500 text-sm"> 29 27 opened by 30 28 {{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }} 31 29 <a href="/{{ $owner }}" class="no-underline hover:underline" ··· 37 35 </div> 38 36 39 37 {{ if .Issue.Body }} 40 - <article id="body" class="mt-8 prose"> 38 + <article id="body" class="mt-4 prose"> 41 39 {{ .Issue.Body | markdown }} 42 40 </article> 43 41 {{ end }} ··· 49 47 {{ range $index, $comment := .Comments }} 50 48 <div 51 49 id="comment-{{ .CommentId }}" 52 - class="rounded bg-white p-4 relative" 50 + class="rounded bg-white px-6 py-4 relative" 53 51 > 54 52 {{ if eq $index 0 }} 55 53 <div ··· 60 58 class="absolute left-8 -top-4 w-px h-4 bg-gray-300" 61 59 ></div> 62 60 {{ end }} 63 - <div class="flex items-center gap-2 mb-2 text-gray-400"> 61 + <div class="flex items-center gap-2 mb-2 text-gray-500"> 64 62 {{ $owner := index $.DidHandleMap .OwnerDid }} 65 63 <span class="text-sm"> 66 64 <a ··· 69 67 >{{ $owner }}</a 70 68 > 71 69 </span> 72 - <span class="px-1 select-none before:content-['\00B7']"></span> 70 + 71 + <span class="before:content-['·']"></span> 73 72 <a 74 73 href="#{{ .CommentId }}" 75 74 class="text-gray-500 text-sm hover:text-gray-500 hover:underline no-underline"
+4 -4
appview/pages/templates/repo/issues/issues.html
··· 4 4 <div class="flex justify-between items-center"> 5 5 <p> 6 6 filtering 7 - <select class="font-bold border border-gray-200 rounded" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value"> 7 + <select class="border px-1 bg-white border-gray-200" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value"> 8 8 <option value="open" {{ if .FilteringByOpen }}selected{{ end }}>open</option> 9 9 <option value="closed" {{ if not .FilteringByOpen }}selected{{ end }}>closed</option> 10 10 </select> ··· 30 30 class="no-underline hover:underline" 31 31 > 32 32 {{ .Title }} 33 - <span class="text-gray-400">#{{ .IssueId }}</span> 33 + <span class="text-gray-500">#{{ .IssueId }}</span> 34 34 </a> 35 35 </div> 36 - <p class="text-sm text-gray-400"> 36 + <p class="text-sm text-gray-500"> 37 37 {{ $bgColor := "bg-gray-800" }} 38 38 {{ $icon := "ban" }} 39 39 {{ $state := "closed" }} ··· 64 64 {{ if eq .Metadata.CommentCount 1 }} 65 65 {{ $s = "" }} 66 66 {{ end }} 67 - <a href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}" class="text-gray-400">{{ .Metadata.CommentCount }} comment{{$s}}</a> 67 + <a href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}" class="text-gray-500">{{ .Metadata.CommentCount }} comment{{$s}}</a> 68 68 </span> 69 69 </p> 70 70 </div>
+17 -5
appview/pages/templates/user/profile.html
··· 44 44 class="py-4 px-6 drop-shadow-sm rounded bg-white" 45 45 > 46 46 <div id="repo-card-name" class="font-medium"> 47 - <a href="/@{{ or $.UserHandle $.UserDid }}/{{ .Name }}" 48 - >{{ .Name }}</a 49 - > 47 + <a href="/@{{ or $.UserHandle $.UserDid }}/{{ .Name }}">{{ .Name }}</a> 50 48 </div> 51 49 {{ if .Description }} 52 50 <div class="text-gray-600 text-sm"> 53 51 {{ .Description }} 54 52 </div> 55 53 {{ end }} 56 - <div class="text-gray-600 text-sm font-mono"> 54 + <div class="text-gray-600 text-sm font-mono inline-flex gap-4"> 57 55 {{ .Knot }} 56 + 57 + {{ if .RepoStats.StarCount }} 58 + <div class="flex gap-1 items-center text-sm"> 59 + <span class="w-2 h-2 fill-current" data-lucide="star"></span> 60 + <span>{{ .RepoStats.StarCount }}</span> 61 + </div> 62 + {{ end }} 58 63 </div> 59 64 </div> 60 65 {{ else }} ··· 86 81 {{ .Description }} 87 82 </div> 88 83 {{ end }} 89 - <div class="text-gray-600 text-sm font-mono"> 84 + <div class="text-gray-600 text-sm font-mono inline-flex gap-4"> 90 85 {{ .Knot }} 86 + 87 + {{ if .RepoStats.StarCount }} 88 + <div class="flex gap-1 items-center text-sm"> 89 + <span class="w-2 h-2 fill-current" data-lucide="star"></span> 90 + <span>{{ .RepoStats.StarCount }}</span> 91 + </div> 92 + {{ end }} 91 93 </div> 92 94 </div> 93 95 {{ else }}