Fix template error when comment review doesn't exist (#29888)

Fix #29885
pull/29897/head^2
wxiaoguang 8 months ago committed by GitHub
parent 0e183d81fc
commit 828701ff2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      models/fixtures/comment.yml
  2. 9
      models/fixtures/review.yml
  3. 17
      routers/web/repo/pull_review_test.go
  4. 2
      templates/repo/diff/comments.tmpl
  5. 128
      templates/repo/diff/conversation.tmpl
  6. 28
      templates/repo/issue/view_content/comments.tmpl
  7. 248
      templates/repo/issue/view_content/conversation.tmpl
  8. 14
      tests/integration/pull_review_test.go

@ -75,3 +75,11 @@
content: "comment in private pository" content: "comment in private pository"
created_unix: 946684811 created_unix: 946684811
updated_unix: 946684811 updated_unix: 946684811
-
id: 9
type: 22 # review
poster_id: 2
issue_id: 2 # in repo_id 1
review_id: 20
created_unix: 946684810

@ -170,3 +170,12 @@
content: "review request for user15" content: "review request for user15"
updated_unix: 946684835 updated_unix: 946684835
created_unix: 946684835 created_unix: 946684835
-
id: 20
type: 22
reviewer_id: 1
issue_id: 2
content: "Review Comment"
updated_unix: 946684810
created_unix: 946684810

@ -4,6 +4,7 @@
package repo package repo
import ( import (
"net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@ -73,4 +74,20 @@ func TestRenderConversation(t *testing.T) {
renderConversation(ctx, preparedComment, "timeline") renderConversation(ctx, preparedComment, "timeline")
assert.Contains(t, resp.Body.String(), `<div id="code-comments-`) assert.Contains(t, resp.Body.String(), `<div id="code-comments-`)
}) })
run("diff non-existing review", func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder) {
err := db.TruncateBeans(db.DefaultContext, &issues_model.Review{})
assert.NoError(t, err)
ctx.Data["ShowOutdatedComments"] = true
renderConversation(ctx, preparedComment, "diff")
assert.Equal(t, http.StatusOK, resp.Code)
assert.NotContains(t, resp.Body.String(), `status-page-500`)
})
run("timeline non-existing review", func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder) {
err := db.TruncateBeans(db.DefaultContext, &issues_model.Review{})
assert.NoError(t, err)
ctx.Data["ShowOutdatedComments"] = true
renderConversation(ctx, preparedComment, "timeline")
assert.Equal(t, http.StatusOK, resp.Code)
assert.NotContains(t, resp.Body.String(), `status-page-500`)
})
} }

@ -37,7 +37,7 @@
{{ctx.Locale.Tr "repo.issues.review.outdated"}} {{ctx.Locale.Tr "repo.issues.review.outdated"}}
</a> </a>
{{end}} {{end}}
{{if and .Review}} {{if .Review}}
{{if eq .Review.Type 0}} {{if eq .Review.Type 0}}
<div class="ui label basic small yellow pending-label" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.review.pending.tooltip" (ctx.Locale.Tr "repo.diff.review") (ctx.Locale.Tr "repo.diff.review.approve") (ctx.Locale.Tr "repo.diff.review.comment") (ctx.Locale.Tr "repo.diff.review.reject")}}"> <div class="ui label basic small yellow pending-label" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.review.pending.tooltip" (ctx.Locale.Tr "repo.diff.review") (ctx.Locale.Tr "repo.diff.review.approve") (ctx.Locale.Tr "repo.diff.review.comment") (ctx.Locale.Tr "repo.diff.review.reject")}}">
{{ctx.Locale.Tr "repo.issues.review.pending"}} {{ctx.Locale.Tr "repo.issues.review.pending"}}

@ -1,66 +1,72 @@
{{$resolved := (index .comments 0).IsResolved}} {{if len .comments}}
{{$invalid := (index .comments 0).Invalidated}} {{$comment := index .comments 0}}
{{$resolveDoer := (index .comments 0).ResolveDoer}} {{$resolved := $comment.IsResolved}}
{{$isNotPending := (not (eq (index .comments 0).Review.Type 0))}} {{$invalid := $comment.Invalidated}}
{{$referenceUrl := printf "%s#%s" $.Issue.Link (index .comments 0).HashTag}} {{$resolveDoer := $comment.ResolveDoer}}
<div class="conversation-holder" data-path="{{(index .comments 0).TreePath}}" data-side="{{if lt (index .comments 0).Line 0}}left{{else}}right{{end}}" data-idx="{{(index .comments 0).UnsignedLine}}"> {{$hasReview := and $comment.Review}}
{{if $resolved}} {{$isReviewPending := and $hasReview (eq $comment.Review.Type 0)}}
<div class="ui attached header resolved-placeholder gt-df gt-ac gt-sb"> {{$referenceUrl := printf "%s#%s" $.Issue.Link $comment.HashTag}}
<div class="ui grey text gt-df gt-ac gt-fw gt-gap-2"> <div class="conversation-holder" data-path="{{$comment.TreePath}}" data-side="{{if lt $comment.Line 0}}left{{else}}right{{end}}" data-idx="{{$comment.UnsignedLine}}">
{{svg "octicon-check" 16 "icon gt-mr-2"}} {{if $resolved}}
<b>{{$resolveDoer.Name}}</b> {{ctx.Locale.Tr "repo.issues.review.resolved_by"}} <div class="ui attached header resolved-placeholder gt-df gt-ac gt-sb">
{{if $invalid}} <div class="ui grey text gt-df gt-ac gt-fw gt-gap-2">
<!-- {{svg "octicon-check" 16 "icon gt-mr-2"}}
We only handle the case $resolved=true and $invalid=true in this template because if the comment is not resolved it has the outdated label in the comments area (not the header above). <b>{{$resolveDoer.Name}}</b> {{ctx.Locale.Tr "repo.issues.review.resolved_by"}}
The case $resolved=false and $invalid=true is handled in repo/diff/comments.tmpl {{if $invalid}}
--> <!--
<a href="{{$referenceUrl}}" class="ui label basic small gt-ml-3" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.review.outdated_description"}}"> We only handle the case $resolved=true and $invalid=true in this template because if the comment is not resolved it has the outdated label in the comments area (not the header above).
{{ctx.Locale.Tr "repo.issues.review.outdated"}} The case $resolved=false and $invalid=true is handled in repo/diff/comments.tmpl
</a> -->
{{end}} <a href="{{$referenceUrl}}" class="ui label basic small gt-ml-3" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.review.outdated_description"}}">
{{ctx.Locale.Tr "repo.issues.review.outdated"}}
</a>
{{end}}
</div>
<div class="gt-df gt-ac gt-gap-3">
<button id="show-outdated-{{$comment.ID}}" data-comment="{{$comment.ID}}" class="ui tiny labeled button show-outdated gt-df gt-ac">
{{svg "octicon-unfold" 16 "gt-mr-3"}}
{{ctx.Locale.Tr "repo.issues.review.show_resolved"}}
</button>
<button id="hide-outdated-{{$comment.ID}}" data-comment="{{$comment.ID}}" class="ui tiny labeled button hide-outdated gt-df gt-ac gt-hidden">
{{svg "octicon-fold" 16 "gt-mr-3"}}
{{ctx.Locale.Tr "repo.issues.review.hide_resolved"}}
</button>
</div>
</div> </div>
<div class="gt-df gt-ac gt-gap-3"> {{end}}
<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny labeled button show-outdated gt-df gt-ac"> <div id="code-comments-{{$comment.ID}}" class="field comment-code-cloud {{if $resolved}}gt-hidden{{end}}">
{{svg "octicon-unfold" 16 "gt-mr-3"}} <div class="comment-list">
{{ctx.Locale.Tr "repo.issues.review.show_resolved"}} <ui class="ui comments">
</button> {{template "repo/diff/comments" dict "root" $ "comments" .comments}}
<button id="hide-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="ui tiny labeled button hide-outdated gt-df gt-ac gt-hidden"> </ui>
{{svg "octicon-fold" 16 "gt-mr-3"}}
{{ctx.Locale.Tr "repo.issues.review.hide_resolved"}}
</button>
</div> </div>
</div> <div class="gt-df gt-je gt-ac gt-fw gt-mt-3">
{{end}} <div class="ui buttons gt-mr-2">
<div id="code-comments-{{(index .comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}gt-hidden{{end}}"> <button class="ui icon tiny basic button previous-conversation">
<div class="comment-list"> {{svg "octicon-arrow-up" 12 "icon"}} {{ctx.Locale.Tr "repo.issues.previous"}}
<ui class="ui comments"> </button>
{{template "repo/diff/comments" dict "root" $ "comments" .comments}} <button class="ui icon tiny basic button next-conversation">
</ui> {{svg "octicon-arrow-down" 12 "icon"}} {{ctx.Locale.Tr "repo.issues.next"}}
</div> </button>
<div class="gt-df gt-je gt-ac gt-fw gt-mt-3"> </div>
<div class="ui buttons gt-mr-2"> {{if and $.CanMarkConversation $hasReview (not $isReviewPending)}}
<button class="ui icon tiny basic button previous-conversation"> <button class="ui icon tiny basic button resolve-conversation" data-origin="diff" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{$comment.ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation">
{{svg "octicon-arrow-up" 12 "icon"}} {{ctx.Locale.Tr "repo.issues.previous"}} {{if $resolved}}
</button> {{ctx.Locale.Tr "repo.issues.review.un_resolve_conversation"}}
<button class="ui icon tiny basic button next-conversation"> {{else}}
{{svg "octicon-arrow-down" 12 "icon"}} {{ctx.Locale.Tr "repo.issues.next"}} {{ctx.Locale.Tr "repo.issues.review.resolve_conversation"}}
</button> {{end}}
</button>
{{end}}
{{if and $.SignedUserID (not $.Repository.IsArchived)}}
<button class="comment-form-reply ui primary tiny labeled icon button gt-ml-2 gt-mr-0">
{{svg "octicon-reply" 16 "reply icon gt-mr-2"}}{{ctx.Locale.Tr "repo.diff.comment.reply"}}
</button>
{{end}}
</div> </div>
{{if and $.CanMarkConversation $isNotPending}} {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" $comment.ReviewID "root" $ "comment" $comment}}
<button class="ui icon tiny basic button resolve-conversation" data-origin="diff" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index .comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation">
{{if $resolved}}
{{ctx.Locale.Tr "repo.issues.review.un_resolve_conversation"}}
{{else}}
{{ctx.Locale.Tr "repo.issues.review.resolve_conversation"}}
{{end}}
</button>
{{end}}
{{if and $.SignedUserID (not $.Repository.IsArchived)}}
<button class="comment-form-reply ui primary tiny labeled icon button gt-ml-2 gt-mr-0">
{{svg "octicon-reply" 16 "reply icon gt-mr-2"}}{{ctx.Locale.Tr "repo.diff.comment.reply"}}
</button>
{{end}}
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index .comments 0).ReviewID "root" $ "comment" (index .comments 0)}}
</div> </div>
</div> {{else}}
{{template "repo/diff/conversation_outdated"}}
{{end}}

@ -371,27 +371,31 @@
{{else if eq .Type 22}} {{else if eq .Type 22}}
<div class="timeline-item-group" id="{{.HashTag}}"> <div class="timeline-item-group" id="{{.HashTag}}">
<div class="timeline-item event"> <div class="timeline-item event">
{{$reviewType := -1}}
{{if .Review}}{{$reviewType = .Review.Type}}{{end}}
{{if not .OriginalAuthor}} {{if not .OriginalAuthor}}
{{/* Some timeline avatars need a offset to correctly align with their speech {{/* Some timeline avatars need a offset to correctly align with their speech
bubble. The condition depends on review type and for positive reviews whether bubble. The condition depends on review type and for positive reviews whether
there is a comment element or not */}} there is a comment element or not */}}
<a class="timeline-avatar{{if or (and (eq .Review.Type 1) (or .Content .Attachments)) (and (eq .Review.Type 2) (or .Content .Attachments)) (eq .Review.Type 3)}} timeline-avatar-offset{{end}}"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}> <a class="timeline-avatar{{if or (and (eq $reviewType 1) (or .Content .Attachments)) (and (eq $reviewType 2) (or .Content .Attachments)) (eq $reviewType 3)}} timeline-avatar-offset{{end}}"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>
{{ctx.AvatarUtils.Avatar .Poster 40}} {{ctx.AvatarUtils.Avatar .Poster 40}}
</a> </a>
{{end}} {{end}}
<span class="badge{{if eq .Review.Type 1}} tw-bg-green tw-text-white{{else if eq .Review.Type 3}} tw-bg-red tw-text-white{{end}}">{{svg (printf "octicon-%s" .Review.Type.Icon)}}</span> <span class="badge{{if eq $reviewType 1}} tw-bg-green tw-text-white{{else if eq $reviewType 3}} tw-bg-red tw-text-white{{end}}">
{{if .Review}}{{svg (printf "octicon-%s" .Review.Type.Icon)}}{{end}}
</span>
<span class="text grey muted-links"> <span class="text grey muted-links">
{{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}} {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}}
{{if eq .Review.Type 1}} {{if eq $reviewType 1}}
{{ctx.Locale.Tr "repo.issues.review.approve" $createdStr}} {{ctx.Locale.Tr "repo.issues.review.approve" $createdStr}}
{{else if eq .Review.Type 2}} {{else if eq $reviewType 2}}
{{ctx.Locale.Tr "repo.issues.review.comment" $createdStr}} {{ctx.Locale.Tr "repo.issues.review.comment" $createdStr}}
{{else if eq .Review.Type 3}} {{else if eq $reviewType 3}}
{{ctx.Locale.Tr "repo.issues.review.reject" $createdStr}} {{ctx.Locale.Tr "repo.issues.review.reject" $createdStr}}
{{else}} {{else}}
{{ctx.Locale.Tr "repo.issues.review.comment" $createdStr}} {{ctx.Locale.Tr "repo.issues.review.comment" $createdStr}}
{{end}} {{end}}
{{if .Review.Dismissed}} {{if and .Review .Review.Dismissed}}
<div class="ui small label">{{ctx.Locale.Tr "repo.issues.review.dismissed_label"}}</div> <div class="ui small label">{{ctx.Locale.Tr "repo.issues.review.dismissed_label"}}</div>
{{end}} {{end}}
</span> </span>
@ -451,7 +455,7 @@
</div> </div>
{{end}} {{end}}
{{if .Review.CodeComments}} {{if and .Review .Review.CodeComments}}
<div class="timeline-item event"> <div class="timeline-item event">
{{range $filename, $lines := .Review.CodeComments}} {{range $filename, $lines := .Review.CodeComments}}
{{range $line, $comms := $lines}} {{range $line, $comms := $lines}}
@ -607,10 +611,12 @@
<span class="text grey muted-links"> <span class="text grey muted-links">
{{template "shared/user/authorlink" .Poster}} {{template "shared/user/authorlink" .Poster}}
{{$reviewerName := ""}} {{$reviewerName := ""}}
{{if eq .Review.OriginalAuthor ""}} {{if .Review}}
{{$reviewerName = .Review.Reviewer.Name}} {{if eq .Review.OriginalAuthor ""}}
{{else}} {{$reviewerName = .Review.Reviewer.Name}}
{{$reviewerName = .Review.OriginalAuthor}} {{else}}
{{$reviewerName = .Review.OriginalAuthor}}
{{end}}
{{end}} {{end}}
{{ctx.Locale.Tr "repo.issues.review.dismissed" $reviewerName $createdStr}} {{ctx.Locale.Tr "repo.issues.review.dismissed" $reviewerName $createdStr}}
</span> </span>

@ -1,137 +1,143 @@
{{$invalid := (index .comments 0).Invalidated}} {{if len .comments}}
{{$resolved := (index .comments 0).IsResolved}} {{$comment := index .comments 0}}
{{$resolveDoer := (index .comments 0).ResolveDoer}} {{$invalid := $comment.Invalidated}}
{{$isNotPending := (not (eq (index .comments 0).Review.Type 0))}} {{$resolved := $comment.IsResolved}}
<div class="ui segments conversation-holder"> {{$resolveDoer := $comment.ResolveDoer}}
<div class="ui segment collapsible-comment-box gt-py-3 gt-df gt-ac gt-sb"> {{$hasReview := and $comment.Review}}
<div class="gt-df gt-ac"> {{$isReviewPending := and $hasReview (eq $comment.Review.Type 0)}}
<a href="{{(index .comments 0).CodeCommentLink ctx}}" class="file-comment gt-ml-3 gt-word-break">{{(index .comments 0).TreePath}}</a> <div class="ui segments conversation-holder">
{{if $invalid}} <div class="ui segment collapsible-comment-box gt-py-3 gt-df gt-ac gt-sb">
<span class="ui label basic small gt-ml-3" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.review.outdated_description"}}"> <div class="gt-df gt-ac">
{{ctx.Locale.Tr "repo.issues.review.outdated"}} <a href="{{$comment.CodeCommentLink ctx}}" class="file-comment gt-ml-3 gt-word-break">{{$comment.TreePath}}</a>
</span> {{if $invalid}}
{{end}} <span class="ui label basic small gt-ml-3" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.review.outdated_description"}}">
</div> {{ctx.Locale.Tr "repo.issues.review.outdated"}}
<div> </span>
{{if or $invalid $resolved}} {{end}}
<button id="show-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="{{if not $resolved}}gt-hidden {{end}}ui compact labeled button show-outdated gt-df gt-ac"> </div>
{{svg "octicon-unfold" 16 "gt-mr-3"}} <div>
{{if $resolved}} {{if or $invalid $resolved}}
{{ctx.Locale.Tr "repo.issues.review.show_resolved"}} <button id="show-outdated-{{$comment.ID}}" data-comment="{{$comment.ID}}" class="{{if not $resolved}}gt-hidden {{end}}ui compact labeled button show-outdated gt-df gt-ac">
{{else}} {{svg "octicon-unfold" 16 "gt-mr-3"}}
{{ctx.Locale.Tr "repo.issues.review.show_outdated"}} {{if $resolved}}
{{end}} {{ctx.Locale.Tr "repo.issues.review.show_resolved"}}
</button> {{else}}
<button id="hide-outdated-{{(index .comments 0).ID}}" data-comment="{{(index .comments 0).ID}}" class="{{if $resolved}}gt-hidden {{end}}ui compact labeled button hide-outdated gt-df gt-ac"> {{ctx.Locale.Tr "repo.issues.review.show_outdated"}}
{{svg "octicon-fold" 16 "gt-mr-3"}} {{end}}
{{if $resolved}} </button>
{{ctx.Locale.Tr "repo.issues.review.hide_resolved"}} <button id="hide-outdated-{{$comment.ID}}" data-comment="{{$comment.ID}}" class="{{if $resolved}}gt-hidden {{end}}ui compact labeled button hide-outdated gt-df gt-ac">
{{else}} {{svg "octicon-fold" 16 "gt-mr-3"}}
{{ctx.Locale.Tr "repo.issues.review.hide_outdated"}} {{if $resolved}}
{{end}} {{ctx.Locale.Tr "repo.issues.review.hide_resolved"}}
</button> {{else}}
{{end}} {{ctx.Locale.Tr "repo.issues.review.hide_outdated"}}
{{end}}
</button>
{{end}}
</div>
</div> </div>
</div> {{$diff := (CommentMustAsDiff ctx $comment)}}
{{$diff := (CommentMustAsDiff ctx (index .comments 0))}} {{if $diff}}
{{if $diff}} {{$file := (index $diff.Files 0)}}
{{$file := (index $diff.Files 0)}} <div id="code-preview-{{$comment.ID}}" class="ui table segment{{if $resolved}} gt-hidden{{end}}">
<div id="code-preview-{{(index .comments 0).ID}}" class="ui table segment{{if $resolved}} gt-hidden{{end}}"> <div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}}">
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}}"> <div class="file-body file-code code-view code-diff code-diff-unified unicode-escaped">
<div class="file-body file-code code-view code-diff code-diff-unified unicode-escaped"> <table>
<table> <tbody>
<tbody> {{template "repo/diff/section_unified" dict "file" $file "root" $}}
{{template "repo/diff/section_unified" dict "file" $file "root" $}} </tbody>
</tbody> </table>
</table> </div>
</div> </div>
</div> </div>
</div> {{end}}
{{end}} <div id="code-comments-{{$comment.ID}}" class="comment-code-cloud ui segment{{if $resolved}} gt-hidden{{end}}">
<div id="code-comments-{{(index .comments 0).ID}}" class="comment-code-cloud ui segment{{if $resolved}} gt-hidden{{end}}"> <div class="ui comments gt-mb-0">
<div class="ui comments gt-mb-0"> {{range .comments}}
{{range .comments}} {{$createdSubStr:= TimeSinceUnix .CreatedUnix ctx.Locale}}
{{$createdSubStr:= TimeSinceUnix .CreatedUnix ctx.Locale}} <div class="comment code-comment gt-pb-4" id="{{.HashTag}}">
<div class="comment code-comment gt-pb-4" id="{{.HashTag}}"> <div class="content">
<div class="content"> <div class="header comment-header">
<div class="header comment-header"> <div class="comment-header-left gt-df gt-ac">
<div class="comment-header-left gt-df gt-ac"> {{if not .OriginalAuthor}}
{{if not .OriginalAuthor}} <a class="avatar">
<a class="avatar"> {{ctx.AvatarUtils.Avatar .Poster 20}}
{{ctx.AvatarUtils.Avatar .Poster 20}} </a>
</a> {{end}}
{{end}} <span class="text grey muted-links">
<span class="text grey muted-links"> {{if .OriginalAuthor}}
{{if .OriginalAuthor}} <span class="text black">
<span class="text black"> {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
{{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}} {{.OriginalAuthor}}
{{.OriginalAuthor}} </span>
</span> {{if $.Repository.OriginalURL}}
{{if $.Repository.OriginalURL}} <span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname}})</span>
<span class="migrate">({{ctx.Locale.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname}})</span> {{end}}
{{else}}
{{template "shared/user/authorlink" .Poster}}
{{end}} {{end}}
{{else}} {{ctx.Locale.Tr "repo.issues.commented_at" .HashTag $createdSubStr}}
{{template "shared/user/authorlink" .Poster}} </span>
</div>
<div class="comment-header-right actions gt-df gt-ac">
{{template "repo/issue/view_content/show_role" dict "ShowRole" .ShowRole}}
{{if not $.Repository.IsArchived}}
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $ "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
{{template "repo/issue/view_content/context_menu" dict "ctxData" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
{{end}} {{end}}
{{ctx.Locale.Tr "repo.issues.commented_at" .HashTag $createdSubStr}} </div>
</span>
</div> </div>
<div class="comment-header-right actions gt-df gt-ac"> <div class="text comment-content">
{{template "repo/issue/view_content/show_role" dict "ShowRole" .ShowRole}} <div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}>
{{if not $.Repository.IsArchived}} {{if .RenderedContent}}
{{template "repo/issue/view_content/add_reaction" dict "ctxData" $ "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)}} {{.RenderedContent}}
{{template "repo/issue/view_content/context_menu" dict "ctxData" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}} {{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
</div>
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
{{template "repo/issue/view_content/attachments" dict "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}} {{end}}
</div> </div>
</div> {{$reactions := .Reactions.GroupByType}}
<div class="text comment-content"> {{if $reactions}}
<div class="render-content markup" {{if or $.Permission.IsAdmin $.HasIssuesOrPullsWritePermission (and $.IsSigned (eq $.SignedUserID .PosterID))}}data-can-edit="true"{{end}}> {{template "repo/issue/view_content/reactions" dict "ctxData" $ "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
{{if .RenderedContent}}
{{.RenderedContent}}
{{else}}
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
{{end}}
</div>
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
{{template "repo/issue/view_content/attachments" dict "Attachments" .Attachments "RenderedContent" .RenderedContent}}
{{end}} {{end}}
</div> </div>
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
{{template "repo/issue/view_content/reactions" dict "ctxData" $ "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
{{end}}
</div>
</div>
{{end}}
</div>
<div class="code-comment-buttons gt-df gt-ac gt-fw gt-mt-3 gt-mb-2 gt-mx-3">
<div class="gt-f1">
{{if $resolved}}
<div class="ui grey text">
{{svg "octicon-check" 16 "gt-mr-2"}}
<b>{{$resolveDoer.Name}}</b> {{ctx.Locale.Tr "repo.issues.review.resolved_by"}}
</div> </div>
{{end}} {{end}}
</div> </div>
<div class="code-comment-buttons-buttons"> <div class="code-comment-buttons gt-df gt-ac gt-fw gt-mt-3 gt-mb-2 gt-mx-3">
{{if and $.CanMarkConversation $isNotPending}} <div class="gt-f1">
<button class="ui tiny basic button resolve-conversation" data-origin="timeline" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index .comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation"> {{if $resolved}}
{{if $resolved}} <div class="ui grey text">
{{ctx.Locale.Tr "repo.issues.review.un_resolve_conversation"}} {{svg "octicon-check" 16 "gt-mr-2"}}
{{else}} <b>{{$resolveDoer.Name}}</b> {{ctx.Locale.Tr "repo.issues.review.resolved_by"}}
{{ctx.Locale.Tr "repo.issues.review.resolve_conversation"}} </div>
{{end}} {{end}}
</button> </div>
{{end}} <div class="code-comment-buttons-buttons">
{{if and $.SignedUserID (not $.Repository.IsArchived)}} {{if and $.CanMarkConversation $hasReview (not $isReviewPending)}}
<button class="comment-form-reply ui primary tiny labeled icon button gt-ml-2 gt-mr-0"> <button class="ui tiny basic button resolve-conversation" data-origin="timeline" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{$comment.ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation">
{{svg "octicon-reply" 16 "reply icon gt-mr-2"}}{{ctx.Locale.Tr "repo.diff.comment.reply"}} {{if $resolved}}
</button> {{ctx.Locale.Tr "repo.issues.review.un_resolve_conversation"}}
{{end}} {{else}}
{{ctx.Locale.Tr "repo.issues.review.resolve_conversation"}}
{{end}}
</button>
{{end}}
{{if and $.SignedUserID (not $.Repository.IsArchived)}}
<button class="comment-form-reply ui primary tiny labeled icon button gt-ml-2 gt-mr-0">
{{svg "octicon-reply" 16 "reply icon gt-mr-2"}}{{ctx.Locale.Tr "repo.diff.comment.reply"}}
</button>
{{end}}
</div>
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" $comment.ReviewID "root" $ "comment" $comment}}
</div> </div>
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index .comments 0).ReviewID "root" $ "comment" (index .comments 0)}}
</div> </div>
</div> {{else}}
{{template "repo/diff/conversation_outdated"}}
{{end}}

@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/test"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
@ -26,10 +27,19 @@ func TestPullView_ReviewerMissed(t *testing.T) {
session := loginUser(t, "user1") session := loginUser(t, "user1")
req := NewRequest(t, "GET", "/pulls") req := NewRequest(t, "GET", "/pulls")
session.MakeRequest(t, req, http.StatusOK) resp := session.MakeRequest(t, req, http.StatusOK)
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
req = NewRequest(t, "GET", "/user2/repo1/pulls/3") req = NewRequest(t, "GET", "/user2/repo1/pulls/3")
session.MakeRequest(t, req, http.StatusOK) resp = session.MakeRequest(t, req, http.StatusOK)
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
// if some reviews are missing, the page shouldn't fail
err := db.TruncateBeans(db.DefaultContext, &issues_model.Review{})
assert.NoError(t, err)
req = NewRequest(t, "GET", "/user2/repo1/pulls/2")
resp = session.MakeRequest(t, req, http.StatusOK)
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
} }
func TestPullView_CodeOwner(t *testing.T) { func TestPullView_CodeOwner(t *testing.T) {

Loading…
Cancel
Save