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

Compare changes

Choose any two refs to compare.

-13
.editorconfig
··· 1 - root = true 2 - 3 - [*.html] 4 - indent_size = 2 5 - 6 - [*.json] 7 - indent_size = 2 8 - 9 - [*.nix] 10 - indent_size = 2 11 - 12 - [*.yml] 13 - indent_size = 2
···
+9 -4
appview/issues/issues.go
··· 312 // notify about the issue closure 313 rp.notifier.NewIssueState(r.Context(), syntax.DID(user.Did), issue) 314 315 - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId)) 316 return 317 } else { 318 l.Error("user is not permitted to close issue") ··· 362 // notify about the issue reopen 363 rp.notifier.NewIssueState(r.Context(), syntax.DID(user.Did), issue) 364 365 - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId)) 366 return 367 } else { 368 l.Error("user is not the owner of the repo") ··· 466 } 467 rp.notifier.NewIssueComment(r.Context(), &comment, mentions) 468 469 - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d#comment-%d", f.OwnerSlashRepo(), issue.IssueId, commentId)) 470 } 471 472 func (rp *Issues) IssueComment(w http.ResponseWriter, r *http.Request) { ··· 970 } 971 } 972 rp.notifier.NewIssue(r.Context(), issue, mentions) 973 - rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId)) 974 return 975 } 976 }
··· 312 // notify about the issue closure 313 rp.notifier.NewIssueState(r.Context(), syntax.DID(user.Did), issue) 314 315 + ownerSlashRepo := rp.repoResolver.GetBaseRepoPath(r, &f.Repo) 316 + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) 317 return 318 } else { 319 l.Error("user is not permitted to close issue") ··· 363 // notify about the issue reopen 364 rp.notifier.NewIssueState(r.Context(), syntax.DID(user.Did), issue) 365 366 + ownerSlashRepo := rp.repoResolver.GetBaseRepoPath(r, &f.Repo) 367 + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) 368 return 369 } else { 370 l.Error("user is not the owner of the repo") ··· 468 } 469 rp.notifier.NewIssueComment(r.Context(), &comment, mentions) 470 471 + ownerSlashRepo := rp.repoResolver.GetBaseRepoPath(r, &f.Repo) 472 + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d#comment-%d", ownerSlashRepo, issue.IssueId, commentId)) 473 } 474 475 func (rp *Issues) IssueComment(w http.ResponseWriter, r *http.Request) { ··· 973 } 974 } 975 rp.notifier.NewIssue(r.Context(), issue, mentions) 976 + 977 + ownerSlashRepo := rp.repoResolver.GetBaseRepoPath(r, &f.Repo) 978 + rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) 979 return 980 } 981 }
+2 -2
appview/middleware/middleware.go
··· 164 ok, err := mw.enforcer.E.Enforce(actor.Did, f.Knot, f.DidSlashRepo(), requiredPerm) 165 if err != nil || !ok { 166 // we need a logged in user 167 - log.Printf("%s does not have perms of a %s in repo %s", actor.Did, requiredPerm, f.OwnerSlashRepo()) 168 http.Error(w, "Forbiden", http.StatusUnauthorized) 169 return 170 } ··· 327 return 328 } 329 330 - fullName := f.OwnerHandle() + "/" + f.Name 331 332 if r.Header.Get("User-Agent") == "Go-http-client/1.1" { 333 if r.URL.Query().Get("go-get") == "1" {
··· 164 ok, err := mw.enforcer.E.Enforce(actor.Did, f.Knot, f.DidSlashRepo(), requiredPerm) 165 if err != nil || !ok { 166 // we need a logged in user 167 + log.Printf("%s does not have perms of a %s in repo %s", actor.Did, requiredPerm, f.DidSlashRepo()) 168 http.Error(w, "Forbiden", http.StatusUnauthorized) 169 return 170 } ··· 327 return 328 } 329 330 + fullName := mw.repoResolver.GetBaseRepoPath(r, &f.Repo) 331 332 if r.Header.Get("User-Agent") == "Go-http-client/1.1" { 333 if r.URL.Query().Get("go-get") == "1" {
+28 -8
appview/pages/funcmap.go
··· 22 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 23 "github.com/alecthomas/chroma/v2/lexers" 24 "github.com/alecthomas/chroma/v2/styles" 25 - "github.com/bluesky-social/indigo/atproto/syntax" 26 "github.com/dustin/go-humanize" 27 "github.com/go-enry/go-enry/v2" 28 "tangled.org/core/appview/filetree" 29 "tangled.org/core/appview/pages/markup" 30 "tangled.org/core/crypto" 31 ) ··· 70 } 71 72 return identity.Handle.String() 73 }, 74 "truncateAt30": func(s string) string { 75 if len(s) <= 30 { ··· 130 } 131 132 return b 133 - }, 134 - "didOrHandle": func(did, handle string) string { 135 - if handle != "" && handle != syntax.HandleInvalid.String() { 136 - return handle 137 - } else { 138 - return did 139 - } 140 }, 141 "assoc": func(values ...string) ([][]string, error) { 142 if len(values)%2 != 0 { ··· 369 } 370 } 371 372 func (p *Pages) AvatarUrl(handle, size string) string { 373 handle = strings.TrimPrefix(handle, "@") 374 375 secret := p.avatar.SharedSecret 376 h := hmac.New(sha256.New, []byte(secret))
··· 22 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 23 "github.com/alecthomas/chroma/v2/lexers" 24 "github.com/alecthomas/chroma/v2/styles" 25 "github.com/dustin/go-humanize" 26 "github.com/go-enry/go-enry/v2" 27 "tangled.org/core/appview/filetree" 28 + "tangled.org/core/appview/models" 29 "tangled.org/core/appview/pages/markup" 30 "tangled.org/core/crypto" 31 ) ··· 70 } 71 72 return identity.Handle.String() 73 + }, 74 + "ownerSlashRepo": func(repo *models.Repo) string { 75 + ownerId, err := p.resolver.ResolveIdent(context.Background(), repo.Did) 76 + if err != nil { 77 + return repo.DidSlashRepo() 78 + } 79 + handle := ownerId.Handle 80 + if handle != "" && !handle.IsInvalidHandle() { 81 + return string(handle)+"/"+repo.Name 82 + } 83 + return repo.DidSlashRepo() 84 }, 85 "truncateAt30": func(s string) string { 86 if len(s) <= 30 { ··· 141 } 142 143 return b 144 }, 145 "assoc": func(values ...string) ([][]string, error) { 146 if len(values)%2 != 0 { ··· 373 } 374 } 375 376 + func (p *Pages) resolveDid(did string) string { 377 + identity, err := p.resolver.ResolveIdent(context.Background(), did) 378 + 379 + if err != nil { 380 + return did 381 + } 382 + 383 + if identity.Handle.IsInvalidHandle() { 384 + return "handle.invalid" 385 + } 386 + 387 + return identity.Handle.String() 388 + } 389 + 390 func (p *Pages) AvatarUrl(handle, size string) string { 391 handle = strings.TrimPrefix(handle, "@") 392 + 393 + handle = p.resolveDid(handle) 394 395 secret := p.avatar.SharedSecret 396 h := hmac.New(sha256.New, []byte(secret))
-2
appview/pages/pages.go
··· 482 483 type ProfileCard struct { 484 UserDid string 485 - UserHandle string 486 FollowStatus models.FollowStatus 487 Punchcard *models.Punchcard 488 Profile *models.Profile ··· 832 833 type Collaborator struct { 834 Did string 835 - Handle string 836 Role string 837 } 838
··· 482 483 type ProfileCard struct { 484 UserDid string 485 FollowStatus models.FollowStatus 486 Punchcard *models.Punchcard 487 Profile *models.Profile ··· 831 832 type Collaborator struct { 833 Did string 834 Role string 835 } 836
+4 -4
appview/pages/repoinfo/repoinfo.go
··· 9 "tangled.org/core/appview/state/userutil" 10 ) 11 12 - func (r RepoInfo) Owner() string { 13 if r.OwnerHandle != "" { 14 return r.OwnerHandle 15 } else { ··· 18 } 19 20 func (r RepoInfo) FullName() string { 21 - return path.Join(r.Owner(), r.Name) 22 } 23 24 - func (r RepoInfo) OwnerWithoutAt() string { 25 if r.OwnerHandle != "" { 26 return r.OwnerHandle 27 } else { ··· 30 } 31 32 func (r RepoInfo) FullNameWithoutAt() string { 33 - return path.Join(r.OwnerWithoutAt(), r.Name) 34 } 35 36 func (r RepoInfo) GetTabs() [][]string {
··· 9 "tangled.org/core/appview/state/userutil" 10 ) 11 12 + func (r RepoInfo) owner() string { 13 if r.OwnerHandle != "" { 14 return r.OwnerHandle 15 } else { ··· 18 } 19 20 func (r RepoInfo) FullName() string { 21 + return path.Join(r.owner(), r.Name) 22 } 23 24 + func (r RepoInfo) ownerWithoutAt() string { 25 if r.OwnerHandle != "" { 26 return r.OwnerHandle 27 } else { ··· 30 } 31 32 func (r RepoInfo) FullNameWithoutAt() string { 33 + return path.Join(r.ownerWithoutAt(), r.Name) 34 } 35 36 func (r RepoInfo) GetTabs() [][]string {
+8 -7
appview/pages/templates/layouts/profilebase.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 - {{ $avatarUrl := fullAvatar .Card.UserHandle }} 5 - <meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" /> 6 <meta property="og:type" content="profile" /> 7 - <meta property="og:url" content="https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}?tab={{ .Active }}" /> 8 - <meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" /> 9 <meta property="og:image" content="{{ $avatarUrl }}" /> 10 <meta property="og:image:width" content="512" /> 11 <meta property="og:image:height" content="512" /> 12 13 <meta name="twitter:card" content="summary" /> 14 - <meta name="twitter:title" content="{{ or .Card.UserHandle .Card.UserDid }}" /> 15 - <meta name="twitter:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" /> 16 <meta name="twitter:image" content="{{ $avatarUrl }}" /> 17 {{ end }} 18
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 + {{ $handle := resolve .Card.UserDid }} 5 + {{ $avatarUrl := fullAvatar $handle }} 6 + <meta property="og:title" content="{{ $handle }}" /> 7 <meta property="og:type" content="profile" /> 8 + <meta property="og:url" content="https://tangled.org/{{ $handle }}?tab={{ .Active }}" /> 9 + <meta property="og:description" content="{{ or .Card.Profile.Description $handle }}" /> 10 <meta property="og:image" content="{{ $avatarUrl }}" /> 11 <meta property="og:image:width" content="512" /> 12 <meta property="og:image:height" content="512" /> 13 14 <meta name="twitter:card" content="summary" /> 15 + <meta name="twitter:title" content="{{ $handle }}" /> 16 + <meta name="twitter:description" content="{{ or .Card.Profile.Description $handle }}" /> 17 <meta name="twitter:image" content="{{ $avatarUrl }}" /> 18 {{ end }} 19
+1 -1
appview/pages/templates/repo/empty.html
··· 35 36 <p><span class="{{$bullet}}">1</span>First, generate a new <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key" class="underline">SSH key pair</a>.</p> 37 <p><span class="{{$bullet}}">2</span>Then add the public key to your account from the <a href="/settings" class="underline">settings</a> page.</p> 38 - <p><span class="{{$bullet}}">3</span>Configure your remote to <code>git@{{ $knot | stripPort }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code></p> 39 <p><span class="{{$bullet}}">4</span>Push!</p> 40 </div> 41 </div>
··· 35 36 <p><span class="{{$bullet}}">1</span>First, generate a new <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key" class="underline">SSH key pair</a>.</p> 37 <p><span class="{{$bullet}}">2</span>Then add the public key to your account from the <a href="/settings" class="underline">settings</a> page.</p> 38 + <p><span class="{{$bullet}}">3</span>Configure your remote to <code>git@{{ $knot | stripPort }}:{{ resolve .RepoInfo.OwnerDid }}/{{ .RepoInfo.Name }}</code></p> 39 <p><span class="{{$bullet}}">4</span>Push!</p> 40 </div> 41 </div>
+3 -2
appview/pages/templates/repo/fragments/cloneDropdown.html
··· 43 44 <!-- SSH Clone --> 45 <div class="mb-3"> 46 <label class="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1">SSH</label> 47 <div class="flex items-center border border-gray-300 dark:border-gray-600 rounded"> 48 <code 49 class="flex-1 px-3 py-2 text-sm bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-l select-all cursor-pointer whitespace-nowrap overflow-x-auto" 50 onclick="window.getSelection().selectAllChildren(this)" 51 - data-url="git@{{ $knot | stripPort }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}" 52 - >git@{{ $knot | stripPort }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code> 53 <button 54 onclick="copyToClipboard(this, this.previousElementSibling.getAttribute('data-url'))" 55 class="px-3 py-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 border-l border-gray-300 dark:border-gray-600"
··· 43 44 <!-- SSH Clone --> 45 <div class="mb-3"> 46 + {{ $repoOwnerHandle := resolve .RepoInfo.OwnerDid }} 47 <label class="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1">SSH</label> 48 <div class="flex items-center border border-gray-300 dark:border-gray-600 rounded"> 49 <code 50 class="flex-1 px-3 py-2 text-sm bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-l select-all cursor-pointer whitespace-nowrap overflow-x-auto" 51 onclick="window.getSelection().selectAllChildren(this)" 52 + data-url="git@{{ $knot | stripPort }}:{{ $repoOwnerHandle }}/{{ .RepoInfo.Name }}" 53 + >git@{{ $knot | stripPort }}:{{ $repoOwnerHandle }}/{{ .RepoInfo.Name }}</code> 54 <button 55 onclick="copyToClipboard(this, this.previousElementSibling.getAttribute('data-url'))" 56 class="px-3 py-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 border-l border-gray-300 dark:border-gray-600"
+5 -4
appview/pages/templates/repo/settings/access.html
··· 29 {{ template "addCollaboratorButton" . }} 30 {{ end }} 31 {{ range .Collaborators }} 32 <div class="border border-gray-200 dark:border-gray-700 rounded p-4"> 33 <div class="flex items-center gap-3"> 34 <img 35 - src="{{ fullAvatar .Handle }}" 36 - alt="{{ .Handle }}" 37 class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0"/> 38 39 <div class="flex-1 min-w-0"> 40 - <a href="/{{ .Handle }}" class="block truncate"> 41 - {{ didOrHandle .Did .Handle }} 42 </a> 43 <p class="text-sm text-gray-500 dark:text-gray-400">{{ .Role }}</p> 44 </div>
··· 29 {{ template "addCollaboratorButton" . }} 30 {{ end }} 31 {{ range .Collaborators }} 32 + {{ $handle := resolve .Did }} 33 <div class="border border-gray-200 dark:border-gray-700 rounded p-4"> 34 <div class="flex items-center gap-3"> 35 <img 36 + src="{{ fullAvatar $handle }}" 37 + alt="{{ $handle }}" 38 class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0"/> 39 40 <div class="flex-1 min-w-0"> 41 + <a href="/{{ $handle }}" class="block truncate"> 42 + {{ $handle }} 43 </a> 44 <p class="text-sm text-gray-500 dark:text-gray-400">{{ .Role }}</p> 45 </div>
+6 -5
appview/pages/templates/strings/dashboard.html
··· 1 - {{ define "title" }}strings by {{ or .Card.UserHandle .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 - <meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" /> 5 <meta property="og:type" content="profile" /> 6 - <meta property="og:url" content="https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}" /> 7 - <meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" /> 8 {{ end }} 9 10 ··· 35 {{ $s := index . 1 }} 36 <div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800"> 37 <div class="font-medium dark:text-white flex gap-2 items-center"> 38 - <a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 39 </div> 40 {{ with $s.Description }} 41 <div class="text-gray-600 dark:text-gray-300 text-sm">
··· 1 + {{ define "title" }}strings by {{ resolve .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 + {{ $handle := resolve .Card.UserDid }} 5 + <meta property="og:title" content="{{ $handle }}" /> 6 <meta property="og:type" content="profile" /> 7 + <meta property="og:url" content="https://tangled.org/{{ $handle }}" /> 8 + <meta property="og:description" content="{{ or .Card.Profile.Description $handle }}" /> 9 {{ end }} 10 11 ··· 36 {{ $s := index . 1 }} 37 <div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800"> 38 <div class="font-medium dark:text-white flex gap-2 items-center"> 39 + <a href="/strings/{{ resolve $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 40 </div> 41 {{ with $s.Description }} 42 <div class="text-gray-600 dark:text-gray-300 text-sm">
+3 -3
appview/pages/templates/strings/string.html
··· 1 - {{ define "title" }}{{ .String.Filename }} · by {{ didOrHandle .Owner.DID.String .Owner.Handle.String }}{{ end }} 2 3 {{ define "extrameta" }} 4 - {{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }} 5 <meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" /> 6 <meta property="og:type" content="object" /> 7 <meta property="og:url" content="https://tangled.org/strings/{{ $ownerId }}/{{ .String.Rkey }}" /> ··· 9 {{ end }} 10 11 {{ define "content" }} 12 - {{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }} 13 <section id="string-header" class="mb-4 py-2 px-6 dark:text-white"> 14 <div class="text-lg flex items-center justify-between"> 15 <div>
··· 1 + {{ define "title" }}{{ .String.Filename }} · by {{ resolve .Owner.DID.String }}{{ end }} 2 3 {{ define "extrameta" }} 4 + {{ $ownerId := resolve .Owner.DID.String }} 5 <meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" /> 6 <meta property="og:type" content="object" /> 7 <meta property="og:url" content="https://tangled.org/strings/{{ $ownerId }}/{{ .String.Rkey }}" /> ··· 9 {{ end }} 10 11 {{ define "content" }} 12 + {{ $ownerId := resolve .Owner.DID.String }} 13 <section id="string-header" class="mb-4 py-2 px-6 dark:text-white"> 14 <div class="text-lg flex items-center justify-between"> 15 <div>
+1 -1
appview/pages/templates/user/followers.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · followers {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-followers" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · followers {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-followers" class="md:col-span-8 order-2 md:order-2">
+1 -1
appview/pages/templates/user/following.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · following {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-following" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · following {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-following" class="md:col-span-8 order-2 md:order-2">
+1 -1
appview/pages/templates/user/fragments/profileCard.html
··· 1 {{ define "user/fragments/profileCard" }} 2 - {{ $userIdent := didOrHandle .UserDid .UserHandle }} 3 <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 <div class="w-3/4 aspect-square relative">
··· 1 {{ define "user/fragments/profileCard" }} 2 + {{ $userIdent := resolve .UserDid }} 3 <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 <div class="w-3/4 aspect-square relative">
+2 -2
appview/pages/templates/user/overview.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-4 order-2 md:order-2"> ··· 224 {{ define "ownRepos" }} 225 <div> 226 <div class="text-sm font-bold px-2 pb-4 dark:text-white flex items-center gap-2"> 227 - <a href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos" 228 class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group"> 229 <span>PINNED REPOS</span> 230 </a>
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }}{{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-4 order-2 md:order-2"> ··· 224 {{ define "ownRepos" }} 225 <div> 226 <div class="text-sm font-bold px-2 pb-4 dark:text-white flex items-center gap-2"> 227 + <a href="/{{ resolve $.Card.UserDid }}?tab=repos" 228 class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group"> 229 <span>PINNED REPOS</span> 230 </a>
+1 -1
appview/pages/templates/user/repos.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
+1 -1
appview/pages/templates/user/starred.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
+2 -2
appview/pages/templates/user/strings.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · strings {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-strings" class="md:col-span-8 order-2 md:order-2"> ··· 23 {{ $s := index . 1 }} 24 <div class="py-4 px-6 rounded bg-white dark:bg-gray-800"> 25 <div class="font-medium dark:text-white flex gap-2 items-center"> 26 - <a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 27 </div> 28 {{ with $s.Description }} 29 <div class="text-gray-600 dark:text-gray-300 text-sm">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · strings {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-strings" class="md:col-span-8 order-2 md:order-2"> ··· 23 {{ $s := index . 1 }} 24 <div class="py-4 px-6 rounded bg-white dark:bg-gray-800"> 25 <div class="font-medium dark:text-white flex gap-2 items-center"> 26 + <a href="/strings/{{ resolve $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 27 </div> 28 {{ with $s.Description }} 29 <div class="text-gray-600 dark:text-gray-300 text-sm">
+16 -8
appview/pulls/pulls.go
··· 800 } 801 s.notifier.NewPullComment(r.Context(), comment, mentions) 802 803 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", f.OwnerSlashRepo(), pull.PullId, commentId)) 804 return 805 } 806 } ··· 1271 1272 s.notifier.NewPull(r.Context(), pull) 1273 1274 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pullId)) 1275 } 1276 1277 func (s *Pulls) createStackedPullRequest( ··· 1372 return 1373 } 1374 1375 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", f.OwnerSlashRepo())) 1376 } 1377 1378 func (s *Pulls) ValidatePatch(w http.ResponseWriter, r *http.Request) { ··· 1920 return 1921 } 1922 1923 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) 1924 } 1925 1926 func (s *Pulls) resubmitStackedPullHelper( ··· 2113 return 2114 } 2115 2116 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) 2117 } 2118 2119 func (s *Pulls) MergePull(w http.ResponseWriter, r *http.Request) { ··· 2231 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) 2232 } 2233 2234 - s.pages.HxLocation(w, fmt.Sprintf("/@%s/%s/pulls/%d", f.OwnerHandle(), f.Name, pull.PullId)) 2235 } 2236 2237 func (s *Pulls) ClosePull(w http.ResponseWriter, r *http.Request) { ··· 2303 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) 2304 } 2305 2306 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) 2307 } 2308 2309 func (s *Pulls) ReopenPull(w http.ResponseWriter, r *http.Request) { ··· 2376 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) 2377 } 2378 2379 - s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", f.OwnerSlashRepo(), pull.PullId)) 2380 } 2381 2382 func newStack(f *reporesolver.ResolvedRepo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) {
··· 800 } 801 s.notifier.NewPullComment(r.Context(), comment, mentions) 802 803 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 804 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", ownerSlashRepo, pull.PullId, commentId)) 805 return 806 } 807 } ··· 1272 1273 s.notifier.NewPull(r.Context(), pull) 1274 1275 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 1276 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pullId)) 1277 } 1278 1279 func (s *Pulls) createStackedPullRequest( ··· 1374 return 1375 } 1376 1377 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 1378 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls", ownerSlashRepo)) 1379 } 1380 1381 func (s *Pulls) ValidatePatch(w http.ResponseWriter, r *http.Request) { ··· 1923 return 1924 } 1925 1926 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 1927 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) 1928 } 1929 1930 func (s *Pulls) resubmitStackedPullHelper( ··· 2117 return 2118 } 2119 2120 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 2121 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) 2122 } 2123 2124 func (s *Pulls) MergePull(w http.ResponseWriter, r *http.Request) { ··· 2236 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) 2237 } 2238 2239 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 2240 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) 2241 } 2242 2243 func (s *Pulls) ClosePull(w http.ResponseWriter, r *http.Request) { ··· 2309 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) 2310 } 2311 2312 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 2313 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) 2314 } 2315 2316 func (s *Pulls) ReopenPull(w http.ResponseWriter, r *http.Request) { ··· 2383 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), p) 2384 } 2385 2386 + ownerSlashRepo := s.repoResolver.GetBaseRepoPath(r, &f.Repo) 2387 + s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) 2388 } 2389 2390 func newStack(f *reporesolver.ResolvedRepo, user *oauth.User, targetBranch, patch string, pullSource *models.PullSource, stackId string) (models.Stack, error) {
+3 -1
appview/repo/blob.go
··· 62 return 63 } 64 65 // Use XRPC response directly instead of converting to internal types 66 var breadcrumbs [][]string 67 - breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", f.OwnerSlashRepo(), url.PathEscape(ref))}) 68 if filePath != "" { 69 for idx, elem := range strings.Split(filePath, "/") { 70 breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], url.PathEscape(elem))})
··· 62 return 63 } 64 65 + ownerSlashRepo := rp.repoResolver.GetBaseRepoPath(r, &f.Repo) 66 + 67 // Use XRPC response directly instead of converting to internal types 68 var breadcrumbs [][]string 69 + breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", ownerSlashRepo, url.PathEscape(ref))}) 70 if filePath != "" { 71 for idx, elem := range strings.Split(filePath, "/") { 72 breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], url.PathEscape(elem))})
+3 -2
appview/repo/tree.go
··· 79 result.ReadmeFileName = xrpcResp.Readme.Filename 80 result.Readme = xrpcResp.Readme.Contents 81 } 82 // redirects tree paths trying to access a blob; in this case the result.Files is unpopulated, 83 // so we can safely redirect to the "parent" (which is the same file). 84 if len(result.Files) == 0 && result.Parent == treePath { 85 - redirectTo := fmt.Sprintf("/%s/blob/%s/%s", f.OwnerSlashRepo(), url.PathEscape(ref), result.Parent) 86 http.Redirect(w, r, redirectTo, http.StatusFound) 87 return 88 } 89 user := rp.oauth.GetUser(r) 90 var breadcrumbs [][]string 91 - breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", f.OwnerSlashRepo(), url.PathEscape(ref))}) 92 if treePath != "" { 93 for idx, elem := range strings.Split(treePath, "/") { 94 breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], url.PathEscape(elem))})
··· 79 result.ReadmeFileName = xrpcResp.Readme.Filename 80 result.Readme = xrpcResp.Readme.Contents 81 } 82 + ownerSlashRepo := rp.repoResolver.GetBaseRepoPath(r, &f.Repo) 83 // redirects tree paths trying to access a blob; in this case the result.Files is unpopulated, 84 // so we can safely redirect to the "parent" (which is the same file). 85 if len(result.Files) == 0 && result.Parent == treePath { 86 + redirectTo := fmt.Sprintf("/%s/blob/%s/%s", ownerSlashRepo, url.PathEscape(ref), result.Parent) 87 http.Redirect(w, r, redirectTo, http.StatusFound) 88 return 89 } 90 user := rp.oauth.GetUser(r) 91 var breadcrumbs [][]string 92 + breadcrumbs = append(breadcrumbs, []string{f.Name, fmt.Sprintf("/%s/tree/%s", ownerSlashRepo, url.PathEscape(ref))}) 93 if treePath != "" { 94 for idx, elem := range strings.Split(treePath, "/") { 95 breadcrumbs = append(breadcrumbs, []string{elem, fmt.Sprintf("%s/%s", breadcrumbs[idx][1], url.PathEscape(elem))})
+12 -14
appview/reporesolver/resolver.go
··· 44 return &RepoResolver{config: config, enforcer: enforcer, idResolver: resolver, execer: execer} 45 } 46 47 func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { 48 repo, ok := r.Context().Value("repo").(*models.Repo) 49 if !ok { ··· 113 114 c := pages.Collaborator{ 115 Did: did, 116 - Handle: "", 117 Role: role, 118 } 119 collaborators = append(collaborators, c) 120 - } 121 - 122 - // populate all collborators with handles 123 - identsToResolve := make([]string, len(collaborators)) 124 - for i, collab := range collaborators { 125 - identsToResolve[i] = collab.Did 126 - } 127 - 128 - resolvedIdents := f.rr.idResolver.ResolveIdents(ctx, identsToResolve) 129 - for i, resolved := range resolvedIdents { 130 - if resolved != nil { 131 - collaborators[i].Handle = resolved.Handle.String() 132 - } 133 } 134 135 return collaborators, nil
··· 44 return &RepoResolver{config: config, enforcer: enforcer, idResolver: resolver, execer: execer} 45 } 46 47 + // NOTE: this... should not even be here. the entire package will be removed in future refactor 48 + func (rr *RepoResolver) GetBaseRepoPath(r *http.Request, repo *models.Repo) string { 49 + var ( 50 + user = chi.URLParam(r, "user") 51 + name = chi.URLParam(r, "repo") 52 + ) 53 + if user == "" || name == "" { 54 + return repo.DidSlashRepo() 55 + } 56 + return path.Join(user, name) 57 + } 58 + 59 func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { 60 repo, ok := r.Context().Value("repo").(*models.Repo) 61 if !ok { ··· 125 126 c := pages.Collaborator{ 127 Did: did, 128 Role: role, 129 } 130 collaborators = append(collaborators, c) 131 } 132 133 return collaborators, nil
+5 -6
appview/state/profile.go
··· 96 97 return &pages.ProfileCard{ 98 UserDid: did, 99 - UserHandle: ident.Handle.String(), 100 Profile: profile, 101 FollowStatus: followStatus, 102 Stats: pages.ProfileStats{ ··· 119 s.pages.Error500(w) 120 return 121 } 122 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 123 124 repos, err := db.GetRepos( 125 s.db, ··· 180 s.pages.Error500(w) 181 return 182 } 183 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 184 185 repos, err := db.GetRepos( 186 s.db, ··· 209 s.pages.Error500(w) 210 return 211 } 212 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 213 214 stars, err := db.GetStars(s.db, 0, db.FilterEq("starred_by_did", profile.UserDid)) 215 if err != nil { ··· 240 s.pages.Error500(w) 241 return 242 } 243 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 244 245 strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 246 if err != nil { ··· 272 if err != nil { 273 return nil, err 274 } 275 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 276 277 loggedInUser := s.oauth.GetUser(r) 278 params := FollowsPageParams{
··· 96 97 return &pages.ProfileCard{ 98 UserDid: did, 99 Profile: profile, 100 FollowStatus: followStatus, 101 Stats: pages.ProfileStats{ ··· 118 s.pages.Error500(w) 119 return 120 } 121 + l = l.With("profileDid", profile.UserDid) 122 123 repos, err := db.GetRepos( 124 s.db, ··· 179 s.pages.Error500(w) 180 return 181 } 182 + l = l.With("profileDid", profile.UserDid) 183 184 repos, err := db.GetRepos( 185 s.db, ··· 208 s.pages.Error500(w) 209 return 210 } 211 + l = l.With("profileDid", profile.UserDid) 212 213 stars, err := db.GetStars(s.db, 0, db.FilterEq("starred_by_did", profile.UserDid)) 214 if err != nil { ··· 239 s.pages.Error500(w) 240 return 241 } 242 + l = l.With("profileDid", profile.UserDid) 243 244 strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 245 if err != nil { ··· 271 if err != nil { 272 return nil, err 273 } 274 + l = l.With("profileDid", profile.UserDid) 275 276 loggedInUser := s.oauth.GetUser(r) 277 params := FollowsPageParams{
+1 -1
types/repo.go
··· 66 type Branch struct { 67 Reference `json:"reference"` 68 Commit *object.Commit `json:"commit,omitempty"` 69 - IsDefault bool `json:"is_default,omitempty"` 70 } 71 72 type RepoTagsResponse struct {
··· 66 type Branch struct { 67 Reference `json:"reference"` 68 Commit *object.Commit `json:"commit,omitempty"` 69 + IsDefault bool `json:"is_deafult,omitempty"` 70 } 71 72 type RepoTagsResponse struct {