Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show outdated comments in files changed tab (#24936) #25428

Merged
merged 2 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions models/issues/comment_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import (
type CodeComments map[string]map[int64][]*Comment

// FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line
func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) {
return fetchCodeCommentsByReview(ctx, issue, currentUser, nil)
func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User, showOutdatedComments bool) (CodeComments, error) {
return fetchCodeCommentsByReview(ctx, issue, currentUser, nil, showOutdatedComments)
}

func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review) (CodeComments, error) {
func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) (CodeComments, error) {
pathToLineToComment := make(CodeComments)
if review == nil {
review = &Review{ID: 0}
Expand All @@ -33,7 +33,7 @@ func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *u
ReviewID: review.ID,
}

comments, err := findCodeComments(ctx, opts, issue, currentUser, review)
comments, err := findCodeComments(ctx, opts, issue, currentUser, review, showOutdatedComments)
if err != nil {
return nil, err
}
Expand All @@ -47,15 +47,17 @@ func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *u
return pathToLineToComment, nil
}

func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) {
func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) ([]*Comment, error) {
var comments CommentList
if review == nil {
review = &Review{ID: 0}
}
conds := opts.ToConds()
if review.ID == 0 {

if !showOutdatedComments && review.ID == 0 {
conds = conds.And(builder.Eq{"invalidated": false})
}

e := db.GetEngine(ctx)
if err := e.Where(conds).
Asc("comment.created_unix").
Expand Down Expand Up @@ -118,12 +120,12 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
}

// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) {
func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64, showOutdatedComments bool) ([]*Comment, error) {
opts := FindCommentsOptions{
Type: CommentTypeCode,
IssueID: issue.ID,
TreePath: treePath,
Line: line,
}
return findCodeComments(ctx, opts, issue, currentUser, nil)
return findCodeComments(ctx, opts, issue, currentUser, nil, showOutdatedComments)
}
4 changes: 2 additions & 2 deletions models/issues/comment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ func TestFetchCodeComments(t *testing.T) {

issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
res, err := issues_model.FetchCodeComments(db.DefaultContext, issue, user)
res, err := issues_model.FetchCodeComments(db.DefaultContext, issue, user, false)
assert.NoError(t, err)
assert.Contains(t, res, "README.md")
assert.Contains(t, res["README.md"], int64(4))
assert.Len(t, res["README.md"][4], 1)
assert.Equal(t, int64(4), res["README.md"][4][0].ID)

user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
res, err = issues_model.FetchCodeComments(db.DefaultContext, issue, user2)
res, err = issues_model.FetchCodeComments(db.DefaultContext, issue, user2, false)
assert.NoError(t, err)
assert.Len(t, res, 1)
}
Expand Down
2 changes: 1 addition & 1 deletion models/issues/review.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (r *Review) LoadCodeComments(ctx context.Context) (err error) {
if err = r.loadIssue(ctx); err != nil {
return
}
r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r)
r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r, false)
return err
}

Expand Down
2 changes: 2 additions & 0 deletions models/user/setting_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const (
SettingsKeyHiddenCommentTypes = "issue.hidden_comment_types"
// SettingsKeyDiffWhitespaceBehavior is the setting key for whitespace behavior of diff
SettingsKeyDiffWhitespaceBehavior = "diff.whitespace_behaviour"
// SettingsKeyShowOutdatedComments is the setting key wether or not to show outdated comments in PRs
SettingsKeyShowOutdatedComments = "comment_code.show_outdated"
// UserActivityPubPrivPem is user's private key
UserActivityPubPrivPem = "activitypub.priv_pem"
// UserActivityPubPubPem is user's public key
Expand Down
3 changes: 3 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,9 @@ issues.review.pending.tooltip = This comment is not currently visible to other u
issues.review.review = Review
issues.review.reviewers = Reviewers
issues.review.outdated = Outdated
issues.review.outdated_description = Content has changed since this comment was made
issues.review.option.show_outdated_comments = Show outdated comments
issues.review.option.hide_outdated_comments = Hide outdated comments
issues.review.show_outdated = Show outdated
issues.review.hide_outdated = Hide outdated
issues.review.show_resolved = Show resolved
Expand Down
25 changes: 25 additions & 0 deletions routers/web/repo/middlewares.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package repo

import (
"fmt"
"strconv"

system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
Expand Down Expand Up @@ -88,3 +89,27 @@ func SetWhitespaceBehavior(ctx *context.Context) {
ctx.Data["WhitespaceBehavior"] = whitespaceBehavior
}
}

// SetShowOutdatedComments set the show outdated comments option as context variable
func SetShowOutdatedComments(ctx *context.Context) {
showOutdatedCommentsValue := ctx.FormString("show-outdated")
// var showOutdatedCommentsValue string

if showOutdatedCommentsValue != "true" && showOutdatedCommentsValue != "false" {
// invalid or no value for this form string -> use default or stored user setting
if ctx.IsSigned {
showOutdatedCommentsValue, _ = user_model.GetUserSetting(ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, "false")
} else {
// not logged in user -> use the default value
showOutdatedCommentsValue = "false"
}
} else {
// valid value -> update user setting if user is logged in
if ctx.IsSigned {
_ = user_model.SetUserSetting(ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, showOutdatedCommentsValue)
}
}

showOutdatedComments, _ := strconv.ParseBool(showOutdatedCommentsValue)
ctx.Data["ShowOutdatedComments"] = showOutdatedComments
}
2 changes: 1 addition & 1 deletion routers/web/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ func ViewPullFiles(ctx *context.Context) {
"numberOfViewedFiles": diff.NumViewedFiles,
}

if err = diff.LoadComments(ctx, issue, ctx.Doer); err != nil {
if err = diff.LoadComments(ctx, issue, ctx.Doer, ctx.Data["ShowOutdatedComments"].(bool)); err != nil {
ctx.ServerError("LoadComments", err)
return
}
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/pull_review.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func UpdateResolveConversation(ctx *context.Context) {
}

func renderConversation(ctx *context.Context, comment *issues_model.Comment) {
comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line)
comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line, ctx.Data["ShowOutdatedComments"].(bool))
if err != nil {
ctx.ServerError("FetchCodeCommentsByLine", err)
return
Expand Down
6 changes: 3 additions & 3 deletions routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,7 @@ func registerRoutes(m *web.Route) {
m.Post("/request_review", reqRepoIssuesOrPullsReader, repo.UpdatePullReviewRequest)
m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview)
m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus)
m.Post("/resolve_conversation", reqRepoIssuesOrPullsReader, repo.UpdateResolveConversation)
m.Post("/resolve_conversation", reqRepoIssuesOrPullsReader, repo.SetShowOutdatedComments, repo.UpdateResolveConversation)
m.Post("/attachments", repo.UploadIssueAttachment)
m.Post("/attachments/remove", repo.DeleteAttachment)
m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin)
Expand Down Expand Up @@ -1277,10 +1277,10 @@ func registerRoutes(m *web.Route) {
m.Post("/set_allow_maintainer_edit", web.Bind(forms.UpdateAllowEditsForm{}), repo.SetAllowEdits)
m.Post("/cleanup", context.RepoMustNotBeArchived(), context.RepoRef(), repo.CleanUpPullRequest)
m.Group("/files", func() {
m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.ViewPullFiles)
m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFiles)
m.Group("/reviews", func() {
m.Get("/new_comment", repo.RenderNewCodeCommentForm)
m.Post("/comments", web.Bind(forms.CodeCommentForm{}), repo.CreateCodeComment)
m.Post("/comments", web.Bind(forms.CodeCommentForm{}), repo.SetShowOutdatedComments, repo.CreateCodeComment)
m.Post("/submit", web.Bind(forms.SubmitReviewForm{}), repo.SubmitReview)
}, context.RepoMustNotBeArchived())
})
Expand Down
4 changes: 2 additions & 2 deletions services/gitdiff/gitdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ type Diff struct {
}

// LoadComments loads comments into each line
func (diff *Diff) LoadComments(ctx context.Context, issue *issues_model.Issue, currentUser *user_model.User) error {
allComments, err := issues_model.FetchCodeComments(ctx, issue, currentUser)
func (diff *Diff) LoadComments(ctx context.Context, issue *issues_model.Issue, currentUser *user_model.User, showOutdatedComments bool) error {
allComments, err := issues_model.FetchCodeComments(ctx, issue, currentUser, showOutdatedComments)
if err != nil {
return err
}
Expand Down
14 changes: 12 additions & 2 deletions services/gitdiff/gitdiff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,16 +594,26 @@ func setupDefaultDiff() *Diff {
}
}

func TestDiff_LoadComments(t *testing.T) {
func TestDiff_LoadCommentsNoOutdated(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
diff := setupDefaultDiff()
assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user))
assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, false))
assert.Len(t, diff.Files[0].Sections[0].Lines[0].Comments, 2)
}

func TestDiff_LoadCommentsWithOutdated(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
diff := setupDefaultDiff()
assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, true))
assert.Len(t, diff.Files[0].Sections[0].Lines[0].Comments, 3)
}

func TestDiffLine_CanComment(t *testing.T) {
assert.False(t, (&DiffLine{Type: DiffLineSection}).CanComment())
assert.False(t, (&DiffLine{Type: DiffLineAdd, Comments: []*issues_model.Comment{{Content: "bla"}}}).CanComment())
Expand Down
6 changes: 6 additions & 0 deletions templates/repo/diff/comments.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
{{end}}
</div>
<div class="comment-header-right actions gt-df gt-ac">
{{if .Invalidated}}
{{$referenceUrl := printf "%s#%s" $.root.Issue.Link .HashTag}}
<a href="{{AppSubUrl}}{{$referenceUrl}}" class="ui label basic small" data-tooltip-content="{{$.root.locale.Tr "repo.issues.review.outdated_description"}}">
{{$.root.locale.Tr "repo.issues.review.outdated"}}
</a>
{{end}}
{{if and .Review}}
{{if eq .Review.Type 0}}
<div class="ui label basic small yellow pending-label" data-tooltip-content="{{$.root.locale.Tr "repo.issues.review.pending.tooltip" ($.root.locale.Tr "repo.diff.review") ($.root.locale.Tr "repo.diff.review.approve") ($.root.locale.Tr "repo.diff.review.comment") ($.root.locale.Tr "repo.diff.review.reject")}}">
Expand Down
15 changes: 13 additions & 2 deletions templates/repo/diff/conversation.tmpl
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
{{$resolved := (index .comments 0).IsResolved}}
{{$invalid := (index .comments 0).Invalidated}}
{{$resolveDoer := (index .comments 0).ResolveDoer}}
{{$isNotPending := (not (eq (index .comments 0).Review.Type 0))}}
{{$referenceUrl := printf "%s#%s" $.Issue.Link (index .comments 0).HashTag}}
<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}}">
{{if $resolved}}
<div class="ui attached header resolved-placeholder gt-df gt-ac gt-sb">
<div class="ui grey text">
<div class="ui grey text gt-df gt-ac gt-fw gt-gap-2">
{{svg "octicon-check" 16 "icon gt-mr-2"}}
<b>{{$resolveDoer.Name}}</b> {{$.locale.Tr "repo.issues.review.resolved_by"}}
{{if $invalid}}
<!--
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).
The case $resolved=false and $invalid=true is handled in repo/diff/comments.tmpl
-->
<a href="{{AppSubUrl}}{{$referenceUrl}}" class="ui label basic small gt-ml-3" data-tooltip-content="{{$.locale.Tr "repo.issues.review.outdated_description"}}">
{{$.locale.Tr "repo.issues.review.outdated"}}
</a>
{{end}}
</div>
<div>
<div class="gt-df gt-ac gt-gap-3">
<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">
{{svg "octicon-unfold" 16 "gt-mr-3"}}
{{$.locale.Tr "repo.issues.review.show_resolved"}}
Expand Down
15 changes: 15 additions & 0 deletions templates/repo/diff/options_dropdown.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,20 @@
{{end}}
<a id="expand-files-btn" class="item">{{.locale.Tr "repo.pulls.expand_files"}}</a>
<a id="collapse-files-btn"class="item">{{.locale.Tr "repo.pulls.collapse_files"}}</a>
{{if .Issue.Index}}
{{if .ShowOutdatedComments}}
<a class="item" href="?style={{if $.IsSplitStyle}}split{{else}}unified{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated=false">
<label class="gt-pointer-events-none">
{{.locale.Tr "repo.issues.review.option.hide_outdated_comments"}}
</label>
</a>
{{else}}
<a class="item" href="?style={{if $.IsSplitStyle}}split{{else}}unified{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated=true">
<label class="gt-pointer-events-none">
{{.locale.Tr "repo.issues.review.option.show_outdated_comments"}}
</label>
</a>
{{end}}
{{end}}
</div>
</div>
10 changes: 5 additions & 5 deletions templates/repo/diff/whitespace_dropdown.tmpl
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
<div class="ui dropdown tiny basic button" data-tooltip-content="{{.locale.Tr "repo.diff.whitespace_button"}}">
{{svg "gitea-whitespace"}}
<div class="menu">
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=show-all">
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=show-all&show-outdated={{$.ShowOutdatedComments}}">
<label class="gt-pointer-events-none">
<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "show-all"}} checked{{end}}>
{{.locale.Tr "repo.diff.whitespace_show_everything"}}
</label>
</a>
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-all">
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-all&show-outdated={{$.ShowOutdatedComments}}">
<label class="gt-pointer-events-none">
<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "ignore-all"}} checked{{end}}>
{{.locale.Tr "repo.diff.whitespace_ignore_all_whitespace"}}
<label>
</a>
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-change">
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-change&show-outdated={{$.ShowOutdatedComments}}">
<label class="gt-pointer-events-none">
<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "ignore-change"}} checked{{end}}>
{{.locale.Tr "repo.diff.whitespace_ignore_amount_changes"}}
</label>
</a>
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-eol">
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-eol&show-outdated={{$.ShowOutdatedComments}}">
<label class="gt-pointer-events-none">
<input class="gt-mr-3 gt-pointer-events-none" type="radio"{{if eq .WhitespaceBehavior "ignore-eol"}} checked{{end}}>
{{.locale.Tr "repo.diff.whitespace_ignore_at_eol"}}
</label>
</a>
</div>
</div>
<a class="ui tiny basic button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}" data-tooltip-content="{{if .IsSplitStyle}}{{.locale.Tr "repo.diff.show_unified_view"}}{{else}}{{.locale.Tr "repo.diff.show_split_view"}}{{end}}">{{if .IsSplitStyle}}{{svg "gitea-join"}}{{else}}{{svg "gitea-split"}}{{end}}</a>
<a class="ui tiny basic button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated={{$.ShowOutdatedComments}}" data-tooltip-content="{{if .IsSplitStyle}}{{.locale.Tr "repo.diff.show_unified_view"}}{{else}}{{.locale.Tr "repo.diff.show_split_view"}}{{end}}">{{if .IsSplitStyle}}{{svg "gitea-join"}}{{else}}{{svg "gitea-split"}}{{end}}</a>
2 changes: 1 addition & 1 deletion templates/repo/issue/view_content/comments.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@
<div class="gt-df gt-ac">
<a href="{{(index $comms 0).CodeCommentLink}}" class="file-comment gt-ml-3 gt-word-break">{{$filename}}</a>
{{if $invalid}}
<span class="ui label basic small gt-ml-3">
<span class="ui label basic small gt-ml-3" data-tooltip-content="{{$.locale.Tr "repo.issues.review.outdated_description"}}">
{{$.locale.Tr "repo.issues.review.outdated"}}
</span>
{{end}}
Expand Down
21 changes: 12 additions & 9 deletions web_src/css/repo.css
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,10 @@
.repository .diff-box .resolved-placeholder {
display: flex;
align-items: center;
font-size: 14px !important;
height: 36px;
padding-top: 0;
padding-bottom: 0;
}

.repository .diff-box .resolved-placeholder .button {
Expand All @@ -1728,10 +1732,6 @@
text-align: center;
}

.repository .diff-file-box .code-diff {
font-size: 12px;
}

.repository .diff-file-box .code-diff td {
padding: 0 0 0 10px !important;
border-top: 0;
Expand Down Expand Up @@ -2500,14 +2500,17 @@
left: 7px;
}

.comment-header .actions a {
margin-right: 0 !important;
.comment-header .actions a:not(.label) {
padding: 0.5rem !important;
}

.comment-header-left > * + *,
.comment-header-right > * + * {
margin-left: 0.25rem;
.comment-header .actions .label {
margin: 0 !important;
}

.comment-header-left,
.comment-header-right {
gap: 4px;
}

.comment-body {
Expand Down
2 changes: 1 addition & 1 deletion web_src/css/review.css
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
}

.comment-code-cloud .attached.header {
padding: 0.1rem 1rem;
padding: 1px 8px 1px 12px;
}

.comment-code-cloud .attached.header .text {
Expand Down