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

appview: add fork button

Changed files
+64 -47
appview
db
pages
templates
fragments
layouts
state
+6 -5
appview/db/profile.go
···
package db
import (
"sort"
"time"
)
···
pulls, err := GetPullsByOwnerDid(e, forDid)
if err != nil {
-
return timeline, err
}
for _, pull := range pulls {
repo, err := GetRepoByAtUri(e, string(pull.RepoAt))
if err != nil {
-
return timeline, err
}
timeline = append(timeline, ProfileTimelineEvent{
···
issues, err := GetIssuesByOwnerDid(e, forDid)
if err != nil {
-
return timeline, err
}
for _, issue := range issues {
repo, err := GetRepoByAtUri(e, string(issue.RepoAt))
if err != nil {
-
return timeline, err
}
timeline = append(timeline, ProfileTimelineEvent{
···
repos, err := GetAllReposByDid(e, forDid)
if err != nil {
-
return timeline, err
}
for _, repo := range repos {
···
package db
import (
+
"fmt"
"sort"
"time"
)
···
pulls, err := GetPullsByOwnerDid(e, forDid)
if err != nil {
+
return timeline, fmt.Errorf("error getting pulls by owner did: %w", err)
}
for _, pull := range pulls {
repo, err := GetRepoByAtUri(e, string(pull.RepoAt))
if err != nil {
+
return timeline, fmt.Errorf("error getting repo by at uri: %w", err)
}
timeline = append(timeline, ProfileTimelineEvent{
···
issues, err := GetIssuesByOwnerDid(e, forDid)
if err != nil {
+
return timeline, fmt.Errorf("error getting issues by owner did: %w", err)
}
for _, issue := range issues {
repo, err := GetRepoByAtUri(e, string(issue.RepoAt))
if err != nil {
+
return timeline, fmt.Errorf("error getting repo by at uri: %w", err)
}
timeline = append(timeline, ProfileTimelineEvent{
···
repos, err := GetAllReposByDid(e, forDid)
if err != nil {
+
return timeline, fmt.Errorf("error getting all repos by did: %w", err)
}
for _, repo := range repos {
+5 -4
appview/db/repos.go
···
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
}
···
}
func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) {
-
var source string
-
err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&source)
if err != nil {
return "", err
}
-
return source, nil
}
func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
···
var repoStats RepoStats
var createdAt string
var nullableDescription sql.NullString
+
var nullableSource sql.NullString
+
err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount, &nullableSource)
if err != nil {
return nil, err
}
···
}
func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) {
+
var nullableSource sql.NullString
+
err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&nullableSource)
if err != nil {
return "", err
}
+
return nullableSource.String, nil
}
func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
+3 -3
appview/pages/pages.go
···
return p.executePlain("fragments/follow", w, params)
}
-
type StarFragmentParams struct {
IsStarred bool
RepoAt syntax.ATURI
Stats db.RepoStats
}
-
func (p *Pages) StarFragment(w io.Writer, params StarFragmentParams) error {
-
return p.executePlain("fragments/star", w, params)
}
type RepoDescriptionParams struct {
···
return p.executePlain("fragments/follow", w, params)
}
+
type RepoActionsFragmentParams struct {
IsStarred bool
RepoAt syntax.ATURI
Stats db.RepoStats
}
+
func (p *Pages) RepoActionsFragment(w io.Writer, params RepoActionsFragmentParams) error {
+
return p.executePlain("fragments/repoActions", w, params)
}
type RepoDescriptionParams struct {
+8 -2
appview/pages/templates/fragments/star.html appview/pages/templates/fragments/repoActions.html
···
-
{{ define "fragments/star" }}
<button id="starBtn"
-
class="text-sm disabled:opacity-50 disabled:cursor-not-allowed"
{{ if .IsStarred }}
hx-delete="/star?subject={{.RepoAt}}&countHint={{.Stats.StarCount}}"
···
</span>
</div>
</button>
{{ end }}
···
+
{{ define "fragments/repoActions" }}
+
<div class="flex items-center">
<button id="starBtn"
+
class="btn disabled:opacity-50 disabled:cursor-not-allowed"
{{ if .IsStarred }}
hx-delete="/star?subject={{.RepoAt}}&countHint={{.Stats.StarCount}}"
···
</span>
</div>
</button>
+
<a class="btn no-underline hover:no-underline flex items-center" href="/{{ .FullName }}/fork">
+
{{ i "git-fork" "w-3 h-3 mr-1"}}
+
fork
+
</a>
+
</div>
{{ end }}
+26 -22
appview/pages/templates/layouts/repobase.html
···
{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }}
{{ define "content" }}
-
<section id="repo-header" class="mb-4 py-2 px-6 dark:text-white">
-
{{ if .RepoInfo.Source }}
-
<p class="text-sm">
-
<div class="flex items-center">
-
{{ i "git-fork" "w-3 h-3 mr-1"}}
-
forked from
-
{{ $sourceOwner := didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }}
-
<a class="ml-1 underline" href="/{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}">{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}</a>
-
</div>
-
</p>
-
{{ end }}
-
<p class="text-lg">
-
<a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a>
-
<span class="select-none">/</span>
-
<a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a>
-
<span class="ml-3">
-
{{ template "fragments/star" .RepoInfo }}
-
</span>
-
</p>
-
{{ template "fragments/repoDescription" . }}
-
</section>
<section class="min-h-screen flex flex-col drop-shadow-sm">
<nav class="w-full pl-4 overflow-auto">
<div class="flex z-60">
···
{{ end }}
"
>
-
{{ $key }}
{{ if not (isNil $meta) }}
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm">{{ $meta }}</span>
{{ end }}
···
{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }}
{{ define "content" }}
+
<section id="repo-header" class="mb-4 py-2 px-6 dark:text-white">
+
{{ if .RepoInfo.Source }}
+
<p class="text-sm">
+
<div class="flex items-center">
+
{{ i "git-fork" "w-3 h-3 mr-1"}}
+
forked from
+
{{ $sourceOwner := didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }}
+
<a class="ml-1 underline" href="/{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}">{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}</a>
+
</div>
+
</p>
+
{{ end }}
+
<div class="text-lg flex items-center justify-between">
+
<div>
+
<a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a>
+
<span class="select-none">/</span>
+
<a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a>
+
</div>
+
<div class="flex items-center">
+
<span class="mr-3">
+
{{ template "fragments/repoActions" .RepoInfo }}
+
</span>
+
</div>
+
</div>
+
{{ template "fragments/repoDescription" . }}
+
</section>
<section class="min-h-screen flex flex-col drop-shadow-sm">
<nav class="w-full pl-4 overflow-auto">
<div class="flex z-60">
···
{{ end }}
"
>
+
{{ $key }}
{{ if not (isNil $meta) }}
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm">{{ $meta }}</span>
{{ end }}
+14 -9
appview/state/repo.go
···
if errors.Is(err, sql.ErrNoRows) {
source = ""
} else if err != nil {
-
log.Println("failed to get repo source for ", f.RepoAt)
}
var sourceRepo *db.Repo
···
}
}
-
knot := f.Knot
-
if knot == "knot1.tangled.sh" {
-
knot = "tangled.sh"
-
}
-
var sourceHandle *identity.Identity
if sourceRepo != nil {
sourceHandle, err = s.resolver.ResolveIdent(context.Background(), sourceRepo.Did)
···
}
}
-
return pages.RepoInfo{
OwnerDid: f.OwnerDid(),
OwnerHandle: f.OwnerHandle(),
Name: f.RepoName,
···
IssueCount: issueCount,
PullCount: pullCount,
},
-
Source: sourceRepo,
-
SourceHandle: sourceHandle.Handle.String(),
}
}
func (s *State) RepoSingleIssue(w http.ResponseWriter, r *http.Request) {
···
if errors.Is(err, sql.ErrNoRows) {
source = ""
} else if err != nil {
+
log.Println("failed to get repo source for ", f.RepoAt, err)
}
var sourceRepo *db.Repo
···
}
}
var sourceHandle *identity.Identity
if sourceRepo != nil {
sourceHandle, err = s.resolver.ResolveIdent(context.Background(), sourceRepo.Did)
···
}
}
+
knot := f.Knot
+
if knot == "knot1.tangled.sh" {
+
knot = "tangled.sh"
+
}
+
+
repoInfo := pages.RepoInfo{
OwnerDid: f.OwnerDid(),
OwnerHandle: f.OwnerHandle(),
Name: f.RepoName,
···
IssueCount: issueCount,
PullCount: pullCount,
},
+
}
+
+
if sourceRepo != nil {
+
repoInfo.Source = sourceRepo
+
repoInfo.SourceHandle = sourceHandle.Handle.String()
}
+
+
return repoInfo
}
func (s *State) RepoSingleIssue(w http.ResponseWriter, r *http.Request) {
+2 -2
appview/state/star.go
···
log.Println("created atproto record: ", resp.Uri)
-
s.pages.StarFragment(w, pages.StarFragmentParams{
IsStarred: true,
RepoAt: subjectUri,
Stats: db.RepoStats{
···
log.Println("failed to get star count for ", subjectUri)
}
-
s.pages.StarFragment(w, pages.StarFragmentParams{
IsStarred: false,
RepoAt: subjectUri,
Stats: db.RepoStats{
···
log.Println("created atproto record: ", resp.Uri)
+
s.pages.RepoActionsFragment(w, pages.RepoActionsFragmentParams{
IsStarred: true,
RepoAt: subjectUri,
Stats: db.RepoStats{
···
log.Println("failed to get star count for ", subjectUri)
}
+
s.pages.RepoActionsFragment(w, pages.RepoActionsFragmentParams{
IsStarred: false,
RepoAt: subjectUri,
Stats: db.RepoStats{