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

add detailed patch view

Changed files
+156 -6
appview
pages
templates
repo
state
+15
appview/pages/pages.go
··· 557 557 return p.executeRepo("repo/pulls/pull", w, params) 558 558 } 559 559 560 + type RepoPullPatchParams struct { 561 + LoggedInUser *auth.User 562 + DidHandleMap map[string]string 563 + RepoInfo RepoInfo 564 + Pull *db.Pull 565 + Diff types.NiceDiff 566 + Round int 567 + Submission *db.PullSubmission 568 + } 569 + 570 + // this name is a mouthful 571 + func (p *Pages) RepoPullPatchPage(w io.Writer, params RepoPullPatchParams) error { 572 + return p.execute("repo/pulls/patch", w, params) 573 + } 574 + 560 575 func (p *Pages) Static() http.Handler { 561 576 sub, err := fs.Sub(files, "static") 562 577 if err != nil {
+90
appview/pages/templates/repo/pulls/patch.html
··· 1 + {{ define "title" }} 2 + viewing patch of {{ .Pull.Title }} &middot; pull #{{ .Pull.PullId }} &middot; {{ .RepoInfo.FullName }} 3 + {{ end }} 4 + 5 + {{ define "content" }} 6 + {{ $oneIndexedRound := add .Round 1 }} 7 + {{ $stat := .Diff.Stat }} 8 + <div class="flex gap-2 items-center text-gray-500 mb-2 px-6"> 9 + <a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2"> 10 + <i data-lucide="arrow-left" class="w-4 h-4"></i> 11 + back 12 + </a> 13 + <span class="select-none before:content-['·']"></span> 14 + viewing round 15 + <span class="text-black">#{{ $oneIndexedRound }}</span> 16 + </div> 17 + <div class="rounded drop-shadow-sm bg-white py-4 px-6"> 18 + <header class="pb-4"> 19 + <h1 class="text-2xl"> 20 + {{ .Pull.Title }} 21 + <span class="text-gray-500">#{{ .Pull.PullId }}</span> 22 + </h1> 23 + </header> 24 + 25 + {{ $bgColor := "bg-gray-800" }} 26 + {{ $icon := "ban" }} 27 + 28 + {{ if .Pull.State.IsOpen }} 29 + {{ $bgColor = "bg-green-600" }} 30 + {{ $icon = "git-pull-request" }} 31 + {{ else if .Pull.State.IsMerged }} 32 + {{ $bgColor = "bg-purple-600" }} 33 + {{ $icon = "git-merge" }} 34 + {{ end }} 35 + 36 + <section> 37 + <div class="flex items-center gap-2"> 38 + <div 39 + id="state" 40 + class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}" 41 + > 42 + <i 43 + data-lucide="{{ $icon }}" 44 + class="w-4 h-4 mr-1.5 text-white" 45 + ></i> 46 + <span class="text-white">{{ .Pull.State.String }}</span> 47 + </div> 48 + <span class="text-gray-500 text-sm"> 49 + opened by 50 + {{ $owner := index $.DidHandleMap .Pull.OwnerDid }} 51 + <a href="/{{ $owner }}" class="no-underline hover:underline" 52 + >{{ $owner }}</a 53 + > 54 + <span class="select-none before:content-['\00B7']"></span> 55 + <time>{{ .Pull.Created | timeFmt }}</time> 56 + <span class="select-none before:content-['\00B7']"></span> 57 + <span>targeting branch 58 + <span class="text-xs rounded bg-gray-100 text-black font-mono px-2 mx-1/2 inline-flex items-center"> 59 + {{ .Pull.TargetBranch }} 60 + </span> 61 + </span> 62 + </span> 63 + </div> 64 + 65 + {{ if .Pull.Body }} 66 + <article id="body" class="mt-2 prose"> 67 + {{ .Pull.Body | markdown }} 68 + </article> 69 + {{ end }} 70 + </section> 71 + 72 + <div id="diff-stat"> 73 + <br> 74 + <strong class="text-sm uppercase mb-4">Changed files</strong> 75 + {{ range .Diff.Diff }} 76 + <ul> 77 + {{ if .IsDelete }} 78 + <li><a href="#file-{{ .Name.Old }}">{{ .Name.Old }}</a></li> 79 + {{ else }} 80 + <li><a href="#file-{{ .Name.New }}">{{ .Name.New }}</a></li> 81 + {{ end }} 82 + </ul> 83 + {{ end }} 84 + </div> 85 + </div> 86 + <section> 87 + {{ template "fragments/diff" (list .RepoInfo.FullName .Diff) }} 88 + </section> 89 + {{ end }} 90 +
+3 -5
appview/pages/templates/repo/pulls/pull.html
··· 51 51 </div> 52 52 53 53 {{ if .Pull.Body }} 54 - <article id="body" class="mt-8 prose"> 54 + <article id="body" class="mt-2 prose"> 55 55 {{ .Pull.Body | markdown }} 56 56 </article> 57 57 {{ end }} ··· 117 117 {{ $s = "" }} 118 118 {{ end }} 119 119 {{ len .Comments }} comment{{$s}} 120 + <span class="before:content-['·']"></span> 121 + <a href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}">view patch</a> 120 122 </span> 121 123 </div> 122 124 </div> 123 125 </summary> 124 126 <div class="pl-12 flex flex-col gap-2 mt-2 relative"> 125 - <div> 126 - {{ template "fragments/diff" (list $repoName $diff) }} 127 - </div> 128 - 129 127 {{ range .Comments }} 130 128 <div id="comment-{{.ID}}" class="bg-white rounded drop-shadow-sm py-2 px-4 relative w-fit"> 131 129 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
+47
appview/state/pull.go
··· 10 10 "strings" 11 11 "time" 12 12 13 + "github.com/go-chi/chi/v5" 13 14 "github.com/sotangled/tangled/api/tangled" 14 15 "github.com/sotangled/tangled/appview/db" 15 16 "github.com/sotangled/tangled/appview/pages" ··· 100 101 Pull: *pull, 101 102 MergeCheck: mergeCheckResponse, 102 103 }) 104 + } 105 + 106 + func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) { 107 + user := s.auth.GetUser(r) 108 + f, err := fullyResolvedRepo(r) 109 + if err != nil { 110 + log.Println("failed to get repo and knot", err) 111 + return 112 + } 113 + 114 + pull, ok := r.Context().Value("pull").(*db.Pull) 115 + if !ok { 116 + log.Println("failed to get pull") 117 + s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.") 118 + return 119 + } 120 + 121 + roundId := chi.URLParam(r, "round") 122 + roundIdInt, err := strconv.Atoi(roundId) 123 + if err != nil || roundIdInt >= len(pull.Submissions) { 124 + http.Error(w, "bad round id", http.StatusBadRequest) 125 + log.Println("failed to parse round id", err) 126 + return 127 + } 128 + 129 + identsToResolve := []string{pull.OwnerDid} 130 + resolvedIds := s.resolver.ResolveIdents(r.Context(), identsToResolve) 131 + didHandleMap := make(map[string]string) 132 + for _, identity := range resolvedIds { 133 + if !identity.Handle.IsInvalidHandle() { 134 + didHandleMap[identity.DID.String()] = fmt.Sprintf("@%s", identity.Handle.String()) 135 + } else { 136 + didHandleMap[identity.DID.String()] = identity.DID.String() 137 + } 138 + } 139 + 140 + s.pages.RepoPullPatchPage(w, pages.RepoPullPatchParams{ 141 + LoggedInUser: user, 142 + DidHandleMap: didHandleMap, 143 + RepoInfo: f.RepoInfo(s, user), 144 + Pull: pull, 145 + Round: roundIdInt, 146 + Submission: pull.Submissions[roundIdInt], 147 + Diff: pull.Submissions[roundIdInt].AsNiceDiff(pull.TargetBranch), 148 + }) 149 + 103 150 } 104 151 105 152 func (s *State) RepoPulls(w http.ResponseWriter, r *http.Request) {
+1 -1
appview/state/router.go
··· 66 66 r.Route("/{pull}", func(r chi.Router) { 67 67 r.Use(ResolvePull(s)) 68 68 r.Get("/", s.RepoSinglePull) 69 - r.Get("/patch", s.RepoSinglePull) 69 + r.Get("/round/{round}", s.RepoPullPatch) 70 70 71 71 // authorized requests below this point 72 72 r.Group(func(r chi.Router) {