Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add comment and resubmit actions in fragments

improve merge check a bit too

Akshay ee40b846 fdfe19a4

+376 -114
+5 -1
appview/db/pulls.go
··· 101 101 } 102 102 103 103 func (p *Pull) LatestPatch() string { 104 - latestSubmission := p.Submissions[len(p.Submissions)-1] 104 + latestSubmission := p.Submissions[p.LastRoundNumber()] 105 105 return latestSubmission.Patch 106 + } 107 + 108 + func (p *Pull) LastRoundNumber() int { 109 + return len(p.Submissions) - 1 106 110 } 107 111 108 112 func (s PullSubmission) AsNiceDiff(targetBranch string) types.NiceDiff {
+15
appview/pages/funcmap.go
··· 1 1 package pages 2 2 3 3 import ( 4 + "errors" 4 5 "fmt" 5 6 "html" 6 7 "html/template" ··· 121 120 }, 122 121 "list": func(args ...any) []any { 123 122 return args 123 + }, 124 + "dict": func(values ...any) (map[string]any, error) { 125 + if len(values)%2 != 0 { 126 + return nil, errors.New("invalid dict call") 127 + } 128 + dict := make(map[string]any, len(values)/2) 129 + for i := 0; i < len(values); i += 2 { 130 + key, ok := values[i].(string) 131 + if !ok { 132 + return nil, errors.New("dict keys must be strings") 133 + } 134 + dict[key] = values[i+1] 135 + } 136 + return dict, nil 124 137 }, 125 138 "i": func(name string, classes ...string) template.HTML { 126 139 data, err := icon(name, classes)
+34
appview/pages/pages.go
··· 576 576 return p.execute("repo/pulls/patch", w, params) 577 577 } 578 578 579 + type PullResubmitParams struct { 580 + LoggedInUser *auth.User 581 + RepoInfo RepoInfo 582 + Pull *db.Pull 583 + SubmissionId int 584 + } 585 + 586 + func (p *Pages) PullResubmitFragment(w io.Writer, params PullResubmitParams) error { 587 + return p.executePlain("fragments/pullResubmit", w, params) 588 + } 589 + 590 + type PullActionsParams struct { 591 + LoggedInUser *auth.User 592 + RepoInfo RepoInfo 593 + Pull *db.Pull 594 + RoundNumber int 595 + MergeCheck types.MergeCheckResponse 596 + } 597 + 598 + func (p *Pages) PullActionsFragment(w io.Writer, params PullActionsParams) error { 599 + return p.executePlain("fragments/pullActions", w, params) 600 + } 601 + 602 + type PullNewCommentParams struct { 603 + LoggedInUser *auth.User 604 + RepoInfo RepoInfo 605 + Pull *db.Pull 606 + RoundNumber int 607 + } 608 + 609 + func (p *Pages) PullNewCommentFragment(w io.Writer, params PullNewCommentParams) error { 610 + return p.executePlain("fragments/pullNewComment", w, params) 611 + } 612 + 579 613 func (p *Pages) Static() http.Handler { 580 614 sub, err := fs.Sub(Files, "static") 581 615 if err != nil {
+2 -2
appview/pages/templates/fragments/editRepoDescription.html
··· 2 2 <form hx-put="/{{ .RepoInfo.FullName }}/description" hx-target="this" hx-swap="outerHTML" class="flex flex-wrap gap-2"> 3 3 <input type="text" class="p-1" name="description" value="{{ .RepoInfo.Description }}"> 4 4 <button type="submit" class="btn p-2 flex items-center gap-2 no-underline text-sm"> 5 - save {{ i "check" "w-3 h-3" }} 5 + {{ i "check" "w-3 h-3" }} save 6 6 </button> 7 7 <button type="button" class="btn p-2 flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description" > 8 - cancel {{ i "x" "w-3 h-3" }} 8 + {{ i "x" "w-3 h-3" }} cancel 9 9 </button> 10 10 </form> 11 11 {{ end }}
+72
appview/pages/templates/fragments/pullActions.html
··· 1 + {{ define "fragments/pullActions" }} 2 + {{ $lastIdx := sub (len .Pull.Submissions) 1 }} 3 + {{ $roundNumber := .RoundNumber }} 4 + 5 + {{ $isPushAllowed := .RepoInfo.Roles.IsPushAllowed }} 6 + {{ $isMerged := .Pull.State.IsMerged }} 7 + {{ $isClosed := .Pull.State.IsClosed }} 8 + {{ $isOpen := .Pull.State.IsOpen }} 9 + {{ $isConflicted := and .MergeCheck (or .MergeCheck.Error .MergeCheck.IsConflicted) }} 10 + {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }} 11 + {{ $isLastRound := eq $roundNumber $lastIdx }} 12 + <div class="relative w-fit"> 13 + <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> 14 + <div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2"> 15 + <button 16 + hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment" 17 + hx-target="#actions-{{$roundNumber}}" 18 + hx-swap="outerHtml" 19 + class="btn p-2 flex items-center gap-2 no-underline hover:no-underline"> 20 + {{ i "message-square-plus" "w-4 h-4" }} 21 + <span>comment</span> 22 + </button> 23 + {{ if and $isPushAllowed $isOpen $isLastRound }} 24 + {{ $disabled := "" }} 25 + {{ if $isConflicted }} 26 + {{ $disabled = "disabled" }} 27 + {{ end }} 28 + <button 29 + hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge" 30 + hx-swap="none" 31 + hx-confirm="Are you sure you want to merge this pull request?" 32 + class="btn p-2 flex items-center gap-2" {{ $disabled }}> 33 + {{ i "git-merge" "w-4 h-4" }} 34 + <span>merge</span> 35 + </button> 36 + {{ end }} 37 + 38 + {{ if and $isPullAuthor $isOpen $isLastRound }} 39 + <button 40 + hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit" 41 + hx-target="#actions-{{$roundNumber}}" 42 + hx-swap="outerHtml" 43 + class="btn p-2 flex items-center gap-2"> 44 + {{ i "rotate-ccw" "w-4 h-4" }} 45 + <span>resubmit</span> 46 + </button> 47 + {{ end }} 48 + 49 + {{ if and $isPullAuthor $isPushAllowed $isOpen $isLastRound }} 50 + <button 51 + hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/close" 52 + hx-swap="none" 53 + class="btn p-2 flex items-center gap-2"> 54 + {{ i "ban" "w-4 h-4" }} 55 + <span>close</span> 56 + </button> 57 + {{ end }} 58 + 59 + {{ if and $isPullAuthor $isPushAllowed $isClosed $isLastRound }} 60 + <button 61 + hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/reopen" 62 + hx-swap="none" 63 + class="btn p-2 flex items-center gap-2"> 64 + {{ i "circle-dot" "w-4 h-4" }} 65 + <span>reopen</span> 66 + </button> 67 + {{ end }} 68 + </div> 69 + </div> 70 + {{ end }} 71 + 72 +
+32
appview/pages/templates/fragments/pullNewComment.html
··· 1 + {{ define "fragments/pullNewComment" }} 2 + <div 3 + id="pull-comment-card-{{ .RoundNumber }}" 4 + class="bg-white rounded drop-shadow-sm py-4 px-6 relative w-full flex flex-col gap-2"> 5 + <div class="text-sm text-gray-500"> 6 + {{ didOrHandle .LoggedInUser.Did .LoggedInUser.Handle }} 7 + </div> 8 + <form 9 + hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/comment" 10 + hx-swap="none" 11 + class="w-full flex flex-wrap gap-2"> 12 + <textarea 13 + name="body" 14 + class="w-full p-2 rounded border border-gray-200" 15 + placeholder="Add to the discussion..."></textarea> 16 + <button type="submit" class="btn flex items-center gap-2"> 17 + {{ i "message-square" "w-4 h-4" }} comment 18 + </button> 19 + <button 20 + type="button" 21 + class="btn flex items-center gap-2" 22 + hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/actions" 23 + hx-swap="outerHTML" 24 + hx-target="#pull-comment-card-{{ .RoundNumber }}"> 25 + {{ i "x" "w-4 h-4" }} 26 + <span>cancel</span> 27 + </button> 28 + <div id="pull-comment"></div> 29 + </form> 30 + </div> 31 + {{ end }} 32 +
+52
appview/pages/templates/fragments/pullResubmit.html
··· 1 + {{ define "fragments/pullResubmit" }} 2 + <div 3 + id="resubmit-pull-card" 4 + class="rounded relative border bg-amber-50 border-amber-200 px-6 py-2"> 5 + 6 + <div class="flex items-center gap-2 text-amber-500"> 7 + {{ i "pencil" "w-4 h-4" }} 8 + <span class="font-medium">resubmit your patch</span> 9 + </div> 10 + 11 + <div class="mt-2 text-sm text-gray-700"> 12 + You can update this patch to address any reviews. 13 + This will begin a new round of reviews, 14 + but you'll still be able to view your previous submissions and feedback. 15 + </div> 16 + 17 + <div class="mt-4 flex flex-col"> 18 + <form 19 + hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit" 20 + hx-swap="none" 21 + class="w-full flex flex-wrap gap-2"> 22 + <textarea 23 + name="patch" 24 + class="w-full p-2 mb-2 rounded border border-gray-200" 25 + placeholder="Paste your updated patch here." 26 + rows="15" 27 + ></textarea> 28 + <button 29 + type="submit" 30 + class="btn flex items-center gap-2" 31 + {{ if or .Pull.State.IsClosed }} 32 + disabled 33 + {{ end }}> 34 + {{ i "rotate-ccw" "w-4 h-4" }} 35 + <span>resubmit</span> 36 + </button> 37 + <button 38 + type="button" 39 + class="btn flex items-center gap-2" 40 + hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Pull.LastRoundNumber }}/actions" 41 + hx-swap="outerHTML" 42 + hx-target="#resubmit-pull-card"> 43 + {{ i "x" "w-4 h-4" }} 44 + <span>cancel</span> 45 + </button> 46 + </form> 47 + 48 + <div id="resubmit-error" class="error"></div> 49 + <div id="resubmit-success" class="success"></div> 50 + </div> 51 + </div> 52 + {{ end }}
+1 -2
appview/pages/templates/fragments/repoDescription.html
··· 8 8 9 9 {{ if .RepoInfo.Roles.IsOwner }} 10 10 <button class="btn p-2 flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description/edit"> 11 - edit 12 - {{ i "pencil" "w-3 h-3" }} 11 + {{ i "pencil" "w-3 h-3" }} edit 13 12 </button> 14 13 {{ end }} 15 14 </span>
+22 -67
appview/pages/templates/repo/pulls/pull.html
··· 115 115 </div> 116 116 {{ end }} 117 117 118 - {{ block "mergeStatus" $ }} {{ end }} 118 + {{ if eq $lastIdx .RoundNumber }} 119 + {{ block "mergeStatus" $ }} {{ end }} 120 + {{ end }} 119 121 120 122 {{ if $.LoggedInUser }} 121 - {{ block "actions" (list $ .ID) }} {{ end }} 123 + {{ template "fragments/pullActions" (dict "LoggedInUser" $.LoggedInUser "Pull" $.Pull "RepoInfo" $.RepoInfo "RoundNumber" .RoundNumber "MergeCheck" $.MergeCheck) }} 122 124 {{ else }} 123 125 <div class="bg-white rounded drop-shadow-sm px-6 py-4 w-fit"> 124 126 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> ··· 134 132 {{ end }} 135 133 136 134 {{ define "mergeStatus" }} 137 - {{ if .Pull.State.IsMerged }} 135 + {{ if .Pull.State.IsClosed }} 136 + <div class="bg-gray-50 border border-black rounded drop-shadow-sm px-6 py-2 relative w-fit"> 137 + <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> 138 + <div class="flex items-center gap-2 text-black"> 139 + {{ i "ban" "w-4 h-4" }} 140 + <span class="font-medium">closed without merging</span 141 + > 142 + </div> 143 + </div> 144 + {{ else if .Pull.State.IsMerged }} 138 145 <div class="bg-purple-50 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit"> 139 146 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> 140 147 <div class="flex items-center gap-2 text-purple-500"> ··· 152 141 > 153 142 </div> 154 143 </div> 144 + {{ else if and .MergeCheck .MergeCheck.Error }} 145 + <div class="bg-red-50 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit"> 146 + <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> 147 + <div class="flex items-center gap-2 text-red-500"> 148 + {{ i "triangle-alert" "w-4 h-4" }} 149 + <span class="font-medium">{{ .MergeCheck.Error }}</span> 150 + </div> 151 + </div> 155 152 {{ else if and .MergeCheck .MergeCheck.IsConflicted }} 156 153 <div class="bg-red-50 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit"> 157 154 <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> ··· 186 167 <span class="font-medium">no conflicts, ready to merge</span> 187 168 </div> 188 169 </div> 189 - {{ end }} 190 - {{ end }} 191 - 192 - {{ define "actions" }} 193 - {{ $rootObj := index . 0 }} 194 - {{ $submissionId := index . 1 }} 195 - 196 - {{ with $rootObj }} 197 - {{ $isPushAllowed := .RepoInfo.Roles.IsPushAllowed }} 198 - {{ $isMerged := .Pull.State.IsMerged }} 199 - {{ $isClosed := .Pull.State.IsClosed }} 200 - {{ $isOpen := .Pull.State.IsOpen }} 201 - {{ $isConflicted := and .MergeCheck .MergeCheck.IsConflicted }} 202 - {{ $isPullAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Pull.OwnerDid) }} 203 - <div class="relative w-fit"> 204 - <div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div> 205 - <div class="flex flex-wrap gap-2"> 206 - <button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline"> 207 - {{ i "message-square-plus" "w-4 h-4" }} 208 - <span>comment</span> 209 - </button> 210 - {{ if and $isPushAllowed $isOpen }} 211 - {{ $disabled := "" }} 212 - {{ if $isConflicted }} 213 - {{ $disabled = "disabled" }} 214 - {{ end }} 215 - <button 216 - hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge" 217 - hx-swap="none" 218 - hx-confirm="Are you sure you want to merge this pull request?" 219 - class="btn p-2 flex items-center gap-2" {{ $disabled }}> 220 - {{ i "git-merge" "w-4 h-4" }} 221 - <span>merge</span> 222 - </button> 223 - {{ end }} 224 - 225 - {{ if and $isPullAuthor $isOpen }} 226 - <button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline"> 227 - {{ i "rotate-ccw" "w-4 h-4" }} 228 - <span>resubmit</span> 229 - </button> 230 - {{ end }} 231 - 232 - {{ if and $isPullAuthor $isPushAllowed $isOpen }} 233 - <button 234 - hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/close" 235 - hx-swap="none" 236 - class="btn p-2 flex items-center gap-2"> 237 - {{ i "ban" "w-4 h-4" }} 238 - <span>close</span> 239 - </button> 240 - {{ end }} 241 - 242 - {{ if and $isPullAuthor $isPushAllowed $isClosed }} 243 - <button 244 - hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/reopen" 245 - hx-swap="none" 246 - class="btn p-2 flex items-center gap-2"> 247 - {{ i "circle-dot" "w-4 h-4" }} 248 - <span>reopen</span> 249 - </button> 250 - {{ end }} 251 - </div> 252 - </div> 253 170 {{ end }} 254 171 {{ end }} 255 172
+124 -39
appview/state/pull.go
··· 20 20 lexutil "github.com/bluesky-social/indigo/lex/util" 21 21 ) 22 22 23 + // htmx fragment 24 + func (s *State) PullActions(w http.ResponseWriter, r *http.Request) { 25 + switch r.Method { 26 + case http.MethodGet: 27 + user := s.auth.GetUser(r) 28 + f, err := fullyResolvedRepo(r) 29 + if err != nil { 30 + log.Println("failed to get repo and knot", err) 31 + return 32 + } 33 + 34 + pull, ok := r.Context().Value("pull").(*db.Pull) 35 + if !ok { 36 + log.Println("failed to get pull") 37 + s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.") 38 + return 39 + } 40 + 41 + roundNumberStr := chi.URLParam(r, "round") 42 + roundNumber, err := strconv.Atoi(roundNumberStr) 43 + if err != nil { 44 + roundNumber = pull.LastRoundNumber() 45 + } 46 + if roundNumber >= len(pull.Submissions) { 47 + http.Error(w, "bad round id", http.StatusBadRequest) 48 + log.Println("failed to parse round id", err) 49 + return 50 + } 51 + 52 + mergeCheckResponse := s.mergeCheck(f, pull) 53 + 54 + s.pages.PullActionsFragment(w, pages.PullActionsParams{ 55 + LoggedInUser: user, 56 + RepoInfo: f.RepoInfo(s, user), 57 + Pull: pull, 58 + RoundNumber: roundNumber, 59 + MergeCheck: mergeCheckResponse, 60 + }) 61 + return 62 + } 63 + } 64 + 23 65 func (s *State) RepoSinglePull(w http.ResponseWriter, r *http.Request) { 24 66 user := s.auth.GetUser(r) 25 67 f, err := fullyResolvedRepo(r) ··· 104 62 } 105 63 } 106 64 107 - var mergeCheckResponse types.MergeCheckResponse 108 - 109 - // Only perform merge check if the pull request is not already merged 110 - if pull.State != db.PullMerged { 111 - secret, err := db.GetRegistrationKey(s.db, f.Knot) 112 - if err != nil { 113 - log.Printf("failed to get registration key for %s", f.Knot) 114 - s.pages.Notice(w, "pull", "Failed to load pull request. Try again later.") 115 - return 116 - } 117 - 118 - ksClient, err := NewSignedClient(f.Knot, secret, s.config.Dev) 119 - if err == nil { 120 - resp, err := ksClient.MergeCheck([]byte(pull.LatestPatch()), pull.OwnerDid, f.RepoName, pull.TargetBranch) 121 - if err != nil { 122 - log.Println("failed to check for mergeability:", err) 123 - } else { 124 - respBody, err := io.ReadAll(resp.Body) 125 - if err != nil { 126 - log.Println("failed to read merge check response body") 127 - } else { 128 - err = json.Unmarshal(respBody, &mergeCheckResponse) 129 - if err != nil { 130 - log.Println("failed to unmarshal merge check response", err) 131 - } 132 - } 133 - } 134 - } else { 135 - log.Printf("failed to setup signed client for %s; ignoring...", f.Knot) 136 - } 137 - } 65 + mergeCheckResponse := s.mergeCheck(f, pull) 138 66 139 67 s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{ 140 68 LoggedInUser: user, ··· 113 101 Pull: *pull, 114 102 MergeCheck: mergeCheckResponse, 115 103 }) 104 + } 105 + 106 + func (s *State) mergeCheck(f *FullyResolvedRepo, pull *db.Pull) types.MergeCheckResponse { 107 + if pull.State == db.PullMerged { 108 + return types.MergeCheckResponse{} 109 + } 110 + 111 + secret, err := db.GetRegistrationKey(s.db, f.Knot) 112 + if err != nil { 113 + log.Printf("failed to get registration key: %w", err) 114 + return types.MergeCheckResponse{ 115 + Error: "failed to check merge status: this knot is unregistered", 116 + } 117 + } 118 + 119 + ksClient, err := NewSignedClient(f.Knot, secret, s.config.Dev) 120 + if err != nil { 121 + log.Printf("failed to setup signed client for %s; ignoring: %v", f.Knot, err) 122 + return types.MergeCheckResponse{ 123 + Error: "failed to check merge status", 124 + } 125 + } 126 + 127 + resp, err := ksClient.MergeCheck([]byte(pull.LatestPatch()), pull.OwnerDid, f.RepoName, pull.TargetBranch) 128 + if err != nil { 129 + log.Println("failed to check for mergeability:", err) 130 + switch resp.StatusCode { 131 + case 400: 132 + return types.MergeCheckResponse{ 133 + Error: "failed to check merge status: does this knot support PRs?", 134 + } 135 + default: 136 + return types.MergeCheckResponse{ 137 + Error: "failed to check merge status: this knot is unreachable", 138 + } 139 + } 140 + } 141 + 142 + respBody, err := io.ReadAll(resp.Body) 143 + if err != nil { 144 + log.Println("failed to read merge check response body") 145 + return types.MergeCheckResponse{ 146 + Error: "failed to check merge status: knot is not speaking the right language", 147 + } 148 + } 149 + defer resp.Body.Close() 150 + 151 + var mergeCheckResponse types.MergeCheckResponse 152 + err = json.Unmarshal(respBody, &mergeCheckResponse) 153 + if err != nil { 154 + log.Println("failed to unmarshal merge check response", err) 155 + return types.MergeCheckResponse{ 156 + Error: "failed to check merge status: knot is not speaking the right language", 157 + } 158 + } 159 + 160 + return mergeCheckResponse 116 161 } 117 162 118 163 func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) { ··· 282 213 return 283 214 } 284 215 216 + roundNumberStr := chi.URLParam(r, "round") 217 + roundNumber, err := strconv.Atoi(roundNumberStr) 218 + if err != nil || roundNumber >= len(pull.Submissions) { 219 + http.Error(w, "bad round id", http.StatusBadRequest) 220 + log.Println("failed to parse round id", err) 221 + return 222 + } 223 + 285 224 switch r.Method { 225 + case http.MethodGet: 226 + s.pages.PullNewCommentFragment(w, pages.PullNewCommentParams{ 227 + LoggedInUser: user, 228 + RepoInfo: f.RepoInfo(s, user), 229 + Pull: pull, 230 + RoundNumber: roundNumber, 231 + }) 232 + return 286 233 case http.MethodPost: 287 234 body := r.FormValue("body") 288 235 if body == "" { 289 236 s.pages.Notice(w, "pull", "Comment body is required") 290 - return 291 - } 292 - 293 - submissionIdstr := r.FormValue("submissionId") 294 - submissionId, err := strconv.Atoi(submissionIdstr) 295 - if err != nil { 296 - s.pages.Notice(w, "pull", "Invalid comment submission.") 297 237 return 298 238 } 299 239 ··· 341 263 }, 342 264 }, 343 265 }) 266 + log.Println(atResp.Uri) 344 267 if err != nil { 345 268 log.Println("failed to create pull comment", err) 346 269 s.pages.Notice(w, "pull-comment", "Failed to create comment.") ··· 355 276 PullId: pull.PullId, 356 277 Body: body, 357 278 CommentAt: atResp.Uri, 358 - SubmissionId: submissionId, 279 + SubmissionId: pull.Submissions[roundNumber].ID, 359 280 }) 360 281 if err != nil { 361 282 log.Println("failed to create pull comment", err) ··· 512 433 } 513 434 514 435 switch r.Method { 436 + case http.MethodGet: 437 + s.pages.PullResubmitFragment(w, pages.PullResubmitParams{ 438 + RepoInfo: f.RepoInfo(s, user), 439 + Pull: pull, 440 + }) 441 + return 515 442 case http.MethodPost: 516 443 patch := r.FormValue("patch") 517 444
+17 -3
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("/round/{round}", s.RepoPullPatch) 69 + 70 + r.Route("/round/{round}", func(r chi.Router) { 71 + r.Get("/", s.RepoPullPatch) 72 + r.Get("/actions", s.PullActions) 73 + r.Route("/comment", func(r chi.Router) { 74 + r.Get("/", s.PullComment) 75 + r.Post("/", s.PullComment) 76 + }) 77 + }) 70 78 71 79 // authorized requests below this point 72 80 r.Group(func(r chi.Router) { 73 81 r.Use(AuthMiddleware(s)) 74 - r.Post("/resubmit", s.ResubmitPull) 75 - r.Post("/comment", s.PullComment) 82 + r.Route("/resubmit", func(r chi.Router) { 83 + r.Get("/", s.ResubmitPull) 84 + r.Post("/", s.ResubmitPull) 85 + }) 86 + r.Route("/comment", func(r chi.Router) { 87 + r.Get("/", s.PullComment) 88 + r.Post("/", s.PullComment) 89 + }) 76 90 r.Post("/close", s.ClosePull) 77 91 r.Post("/reopen", s.ReopenPull) 78 92 // collaborators only