forked from tangled.org/core
Monorepo for Tangled

appview: add fork button

authored by anirudh.fi and committed by oppi.li 1428c3be 4fac8249

Changed files
+64 -47
appview
db
pages
templates
fragments
layouts
state
+6 -5
appview/db/profile.go
··· 1 1 package db 2 2 3 3 import ( 4 + "fmt" 4 5 "sort" 5 6 "time" 6 7 ) ··· 19 20 20 21 pulls, err := GetPullsByOwnerDid(e, forDid) 21 22 if err != nil { 22 - return timeline, err 23 + return timeline, fmt.Errorf("error getting pulls by owner did: %w", err) 23 24 } 24 25 25 26 for _, pull := range pulls { 26 27 repo, err := GetRepoByAtUri(e, string(pull.RepoAt)) 27 28 if err != nil { 28 - return timeline, err 29 + return timeline, fmt.Errorf("error getting repo by at uri: %w", err) 29 30 } 30 31 31 32 timeline = append(timeline, ProfileTimelineEvent{ ··· 38 39 39 40 issues, err := GetIssuesByOwnerDid(e, forDid) 40 41 if err != nil { 41 - return timeline, err 42 + return timeline, fmt.Errorf("error getting issues by owner did: %w", err) 42 43 } 43 44 44 45 for _, issue := range issues { 45 46 repo, err := GetRepoByAtUri(e, string(issue.RepoAt)) 46 47 if err != nil { 47 - return timeline, err 48 + return timeline, fmt.Errorf("error getting repo by at uri: %w", err) 48 49 } 49 50 50 51 timeline = append(timeline, ProfileTimelineEvent{ ··· 57 58 58 59 repos, err := GetAllReposByDid(e, forDid) 59 60 if err != nil { 60 - return timeline, err 61 + return timeline, fmt.Errorf("error getting all repos by did: %w", err) 61 62 } 62 63 63 64 for _, repo := range repos {
+5 -4
appview/db/repos.go
··· 88 88 var repoStats RepoStats 89 89 var createdAt string 90 90 var nullableDescription sql.NullString 91 + var nullableSource sql.NullString 91 92 92 - err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount) 93 + err := rows.Scan(&repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &createdAt, &repoStats.StarCount, &nullableSource) 93 94 if err != nil { 94 95 return nil, err 95 96 } ··· 179 180 } 180 181 181 182 func GetRepoSource(e Execer, repoAt syntax.ATURI) (string, error) { 182 - var source string 183 - err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&source) 183 + var nullableSource sql.NullString 184 + err := e.QueryRow(`select source from repos where at_uri = ?`, repoAt).Scan(&nullableSource) 184 185 if err != nil { 185 186 return "", err 186 187 } 187 - return source, nil 188 + return nullableSource.String, nil 188 189 } 189 190 190 191 func AddCollaborator(e Execer, collaborator, repoOwnerDid, repoName, repoKnot string) error {
+3 -3
appview/pages/pages.go
··· 199 199 return p.executePlain("fragments/follow", w, params) 200 200 } 201 201 202 - type StarFragmentParams struct { 202 + type RepoActionsFragmentParams struct { 203 203 IsStarred bool 204 204 RepoAt syntax.ATURI 205 205 Stats db.RepoStats 206 206 } 207 207 208 - func (p *Pages) StarFragment(w io.Writer, params StarFragmentParams) error { 209 - return p.executePlain("fragments/star", w, params) 208 + func (p *Pages) RepoActionsFragment(w io.Writer, params RepoActionsFragmentParams) error { 209 + return p.executePlain("fragments/repoActions", w, params) 210 210 } 211 211 212 212 type RepoDescriptionParams struct {
+8 -2
appview/pages/templates/fragments/star.html appview/pages/templates/fragments/repoActions.html
··· 1 - {{ define "fragments/star" }} 1 + {{ define "fragments/repoActions" }} 2 + <div class="flex items-center"> 2 3 <button id="starBtn" 3 - class="text-sm disabled:opacity-50 disabled:cursor-not-allowed" 4 + class="btn disabled:opacity-50 disabled:cursor-not-allowed" 4 5 5 6 {{ if .IsStarred }} 6 7 hx-delete="/star?subject={{.RepoAt}}&countHint={{.Stats.StarCount}}" ··· 24 25 </span> 25 26 </div> 26 27 </button> 28 + <a class="btn no-underline hover:no-underline flex items-center" href="/{{ .FullName }}/fork"> 29 + {{ i "git-fork" "w-3 h-3 mr-1"}} 30 + fork 31 + </a> 32 + </div> 27 33 {{ end }} 28 34
+26 -22
appview/pages/templates/layouts/repobase.html
··· 1 1 {{ define "title" }}{{ .RepoInfo.FullName }}{{ end }} 2 2 3 3 {{ define "content" }} 4 - <section id="repo-header" class="mb-4 py-2 px-6 dark:text-white"> 5 - {{ if .RepoInfo.Source }} 6 - <p class="text-sm"> 7 - <div class="flex items-center"> 8 - {{ i "git-fork" "w-3 h-3 mr-1"}} 9 - forked from 10 - {{ $sourceOwner := didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }} 11 - <a class="ml-1 underline" href="/{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}">{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}</a> 12 - </div> 13 - </p> 14 - {{ end }} 15 - <p class="text-lg"> 16 - <a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a> 17 - <span class="select-none">/</span> 18 - <a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a> 19 - <span class="ml-3"> 20 - {{ template "fragments/star" .RepoInfo }} 21 - </span> 22 - </p> 23 - {{ template "fragments/repoDescription" . }} 24 - </section> 4 + <section id="repo-header" class="mb-4 py-2 px-6 dark:text-white"> 5 + {{ if .RepoInfo.Source }} 6 + <p class="text-sm"> 7 + <div class="flex items-center"> 8 + {{ i "git-fork" "w-3 h-3 mr-1"}} 9 + forked from 10 + {{ $sourceOwner := didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }} 11 + <a class="ml-1 underline" href="/{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}">{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}</a> 12 + </div> 13 + </p> 14 + {{ end }} 15 + <div class="text-lg flex items-center justify-between"> 16 + <div> 17 + <a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a> 18 + <span class="select-none">/</span> 19 + <a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a> 20 + </div> 21 + <div class="flex items-center"> 22 + <span class="mr-3"> 23 + {{ template "fragments/repoActions" .RepoInfo }} 24 + </span> 25 + </div> 26 + </div> 27 + {{ template "fragments/repoDescription" . }} 28 + </section> 25 29 <section class="min-h-screen flex flex-col drop-shadow-sm"> 26 30 <nav class="w-full pl-4 overflow-auto"> 27 31 <div class="flex z-60"> ··· 46 50 {{ end }} 47 51 " 48 52 > 49 - {{ $key }} 53 + {{ $key }} 50 54 {{ if not (isNil $meta) }} 51 55 <span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm">{{ $meta }}</span> 52 56 {{ end }}
+14 -9
appview/state/repo.go
··· 807 807 if errors.Is(err, sql.ErrNoRows) { 808 808 source = "" 809 809 } else if err != nil { 810 - log.Println("failed to get repo source for ", f.RepoAt) 810 + log.Println("failed to get repo source for ", f.RepoAt, err) 811 811 } 812 812 813 813 var sourceRepo *db.Repo ··· 818 818 } 819 819 } 820 820 821 - knot := f.Knot 822 - if knot == "knot1.tangled.sh" { 823 - knot = "tangled.sh" 824 - } 825 - 826 821 var sourceHandle *identity.Identity 827 822 if sourceRepo != nil { 828 823 sourceHandle, err = s.resolver.ResolveIdent(context.Background(), sourceRepo.Did) ··· 831 826 } 832 827 } 833 828 834 - return pages.RepoInfo{ 829 + knot := f.Knot 830 + if knot == "knot1.tangled.sh" { 831 + knot = "tangled.sh" 832 + } 833 + 834 + repoInfo := pages.RepoInfo{ 835 835 OwnerDid: f.OwnerDid(), 836 836 OwnerHandle: f.OwnerHandle(), 837 837 Name: f.RepoName, ··· 845 845 IssueCount: issueCount, 846 846 PullCount: pullCount, 847 847 }, 848 - Source: sourceRepo, 849 - SourceHandle: sourceHandle.Handle.String(), 848 + } 849 + 850 + if sourceRepo != nil { 851 + repoInfo.Source = sourceRepo 852 + repoInfo.SourceHandle = sourceHandle.Handle.String() 850 853 } 854 + 855 + return repoInfo 851 856 } 852 857 853 858 func (s *State) RepoSingleIssue(w http.ResponseWriter, r *http.Request) {
+2 -2
appview/state/star.go
··· 62 62 63 63 log.Println("created atproto record: ", resp.Uri) 64 64 65 - s.pages.StarFragment(w, pages.StarFragmentParams{ 65 + s.pages.RepoActionsFragment(w, pages.RepoActionsFragmentParams{ 66 66 IsStarred: true, 67 67 RepoAt: subjectUri, 68 68 Stats: db.RepoStats{ ··· 101 101 log.Println("failed to get star count for ", subjectUri) 102 102 } 103 103 104 - s.pages.StarFragment(w, pages.StarFragmentParams{ 104 + s.pages.RepoActionsFragment(w, pages.RepoActionsFragmentParams{ 105 105 IsStarred: false, 106 106 RepoAt: subjectUri, 107 107 Stats: db.RepoStats{