forked from tangled.org/core
this repo has no description

show stars in profile; styles for issue comments

Changed files
+116 -26
appview
db
pages
templates
fragments
repo
user
+75 -4
appview/db/repos.go
···
Created time.Time
AtUri string
Description string
+
+
// optionally, populate this when querying for reverse mappings
+
RepoStats *RepoStats
}
func GetAllRepos(e Execer, limit int) ([]Repo, error) {
···
func GetAllReposByDid(e Execer, did string) ([]Repo, error) {
var repos []Repo
-
rows, err := e.Query(`select did, name, knot, rkey, description, created from repos where did = ?`, did)
+
rows, err := e.Query(
+
`select
+
r.did,
+
r.name,
+
r.knot,
+
r.rkey,
+
r.description,
+
r.created,
+
count(s.id) as star_count
+
from
+
repos r
+
left join
+
stars s on r.at_uri = s.repo_at
+
where
+
r.did = ?
+
group by
+
r.at_uri`, did)
if err != nil {
return nil, err
}
···
for rows.Next() {
var repo Repo
-
err := scanRepo(rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created)
+
var repoStats RepoStats
+
var createdAt string
+
var nullableDescription sql.NullString
+
+
err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount)
if err != nil {
return nil, err
}
+
+
if nullableDescription.Valid {
+
repo.Description = nullableDescription.String
+
} else {
+
repo.Description = ""
+
}
+
+
createdAtTime, err := time.Parse(time.RFC3339, createdAt)
+
if err != nil {
+
repo.Created = time.Now()
+
} else {
+
repo.Created = createdAtTime
+
}
+
+
repo.RepoStats = &repoStats
+
repos = append(repos, repo)
}
···
func CollaboratingIn(e Execer, collaborator string) ([]Repo, error) {
var repos []Repo
-
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)
+
rows, err := e.Query(
+
`select
+
r.did, r.name, r.knot, r.rkey, r.description, r.created, count(s.id) as star_count
+
from
+
repos r
+
join
+
collaborators c on r.id = c.repo
+
left join
+
stars s on r.at_uri = s.repo_at
+
where
+
c.did = ?
+
group by
+
r.id;`, collaborator)
if err != nil {
return nil, err
}
···
for rows.Next() {
var repo Repo
-
err := scanRepo(rows, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &repo.Description, &repo.Created)
+
var repoStats RepoStats
+
var createdAt string
+
var nullableDescription sql.NullString
+
+
err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount)
if err != nil {
return nil, err
}
+
+
if nullableDescription.Valid {
+
repo.Description = nullableDescription.String
+
} else {
+
repo.Description = ""
+
}
+
+
createdAtTime, err := time.Parse(time.RFC3339, createdAt)
+
if err != nil {
+
repo.Created = time.Now()
+
} else {
+
repo.Created = createdAtTime
+
}
+
+
repo.RepoStats = &repoStats
+
repos = append(repos, repo)
}
+3 -1
appview/db/star.go
···
type Star struct {
StarredByDid string
RepoAt syntax.ATURI
-
Repo *Repo
Created time.Time
Rkey string
+
+
// optionally, populate this when querying for reverse mappings
+
Repo *Repo
}
func (star *Star) ResolveRepo(e Execer) error {
+6 -1
appview/pages/pages.go
···
func Cache(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
+
if strings.HasSuffix(r.URL.Path, ".css") {
+
// on day for css files
+
w.Header().Set("Cache-Control", "public, max-age=86400")
+
} else {
+
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
+
}
h.ServeHTTP(w, r)
})
}
-3
appview/pages/templates/fragments/star.html
···
<span>
{{ .Stats.StarCount }}
</span>
-
<span id="starSpinner" class="hidden">
-
loading
-
</span>
</div>
</button>
<script>
+11 -8
appview/pages/templates/repo/issues/issue.html
···
{{ end }}
{{ define "repoContent" }}
-
<h1>
+
<header>
+
<p class="text-2xl font-bold">
{{ .Issue.Title }}
-
<span class="text-gray-400">#{{ .Issue.IssueId }}</span>
-
</h1>
+
<span class="text-gray-500">#{{ .Issue.IssueId }}</span>
+
</p>
+
</header>
{{ $bgColor := "bg-gray-800" }}
{{ $icon := "ban" }}
···
<i data-lucide="{{ $icon }}" class="w-4 h-4 mr-1.5 text-white" ></i>
<span class="text-white">{{ .State }}</span>
</div>
-
<span class="text-gray-400 text-sm">
+
<span class="text-gray-500 text-sm">
opened by
{{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
<a href="/{{ $owner }}" class="no-underline hover:underline"
···
</div>
{{ if .Issue.Body }}
-
<article id="body" class="mt-8 prose">
+
<article id="body" class="mt-4 prose">
{{ .Issue.Body | markdown }}
</article>
{{ end }}
···
{{ range $index, $comment := .Comments }}
<div
id="comment-{{ .CommentId }}"
-
class="rounded bg-white p-4 relative"
+
class="rounded bg-white px-6 py-4 relative"
>
{{ if eq $index 0 }}
<div
···
class="absolute left-8 -top-4 w-px h-4 bg-gray-300"
></div>
{{ end }}
-
<div class="flex items-center gap-2 mb-2 text-gray-400">
+
<div class="flex items-center gap-2 mb-2 text-gray-500">
{{ $owner := index $.DidHandleMap .OwnerDid }}
<span class="text-sm">
<a
···
>{{ $owner }}</a
>
</span>
-
<span class="px-1 select-none before:content-['\00B7']"></span>
+
+
<span class="before:content-['·']"></span>
<a
href="#{{ .CommentId }}"
class="text-gray-500 text-sm hover:text-gray-500 hover:underline no-underline"
+4 -4
appview/pages/templates/repo/issues/issues.html
···
<div class="flex justify-between items-center">
<p>
filtering
-
<select class="font-bold border border-gray-200 rounded" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value">
+
<select class="border px-1 bg-white border-gray-200" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value">
<option value="open" {{ if .FilteringByOpen }}selected{{ end }}>open</option>
<option value="closed" {{ if not .FilteringByOpen }}selected{{ end }}>closed</option>
</select>
···
class="no-underline hover:underline"
>
{{ .Title }}
-
<span class="text-gray-400">#{{ .IssueId }}</span>
+
<span class="text-gray-500">#{{ .IssueId }}</span>
</a>
</div>
-
<p class="text-sm text-gray-400">
+
<p class="text-sm text-gray-500">
{{ $bgColor := "bg-gray-800" }}
{{ $icon := "ban" }}
{{ $state := "closed" }}
···
{{ if eq .Metadata.CommentCount 1 }}
{{ $s = "" }}
{{ end }}
-
<a href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}" class="text-gray-400">{{ .Metadata.CommentCount }} comment{{$s}}</a>
+
<a href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}" class="text-gray-500">{{ .Metadata.CommentCount }} comment{{$s}}</a>
</span>
</p>
</div>
+17 -5
appview/pages/templates/user/profile.html
···
class="py-4 px-6 drop-shadow-sm rounded bg-white"
>
<div id="repo-card-name" class="font-medium">
-
<a href="/@{{ or $.UserHandle $.UserDid }}/{{ .Name }}"
-
>{{ .Name }}</a
-
>
+
<a href="/@{{ or $.UserHandle $.UserDid }}/{{ .Name }}">{{ .Name }}</a>
</div>
{{ if .Description }}
<div class="text-gray-600 text-sm">
{{ .Description }}
</div>
{{ end }}
-
<div class="text-gray-600 text-sm font-mono">
+
<div class="text-gray-600 text-sm font-mono inline-flex gap-4">
{{ .Knot }}
+
+
{{ if .RepoStats.StarCount }}
+
<div class="flex gap-1 items-center text-sm">
+
<span class="w-2 h-2 fill-current" data-lucide="star"></span>
+
<span>{{ .RepoStats.StarCount }}</span>
+
</div>
+
{{ end }}
</div>
</div>
{{ else }}
···
{{ .Description }}
</div>
{{ end }}
-
<div class="text-gray-600 text-sm font-mono">
+
<div class="text-gray-600 text-sm font-mono inline-flex gap-4">
{{ .Knot }}
+
+
{{ if .RepoStats.StarCount }}
+
<div class="flex gap-1 items-center text-sm">
+
<span class="w-2 h-2 fill-current" data-lucide="star"></span>
+
<span>{{ .RepoStats.StarCount }}</span>
+
</div>
+
{{ end }}
</div>
</div>
{{ else }}