diff --git a/models/issues/comment_code.go b/models/issues/comment_code.go index b562aab500..28f9fd531d 100644 --- a/models/issues/comment_code.go +++ b/models/issues/comment_code.go @@ -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, showOutdatedComments bool) (CodeComments, error) { - return fetchCodeCommentsByReview(ctx, issue, currentUser, nil, showOutdatedComments) +func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User, showOutdatedComments bool, filePath *string) (CodeComments, error) { + return fetchCodeCommentsByReview(ctx, issue, currentUser, nil, showOutdatedComments, filePath) } -func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) (CodeComments, error) { +func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool, filePath *string) (CodeComments, error) { pathToLineToComment := make(CodeComments) if review == nil { review = &Review{ID: 0} @@ -33,6 +33,15 @@ func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *u ReviewID: review.ID, } + if filePath != nil { + opts = FindCommentsOptions{ + Type: CommentTypeCode, + IssueID: issue.ID, + ReviewID: review.ID, + TreePath: *filePath, + } + } + comments, err := findCodeComments(ctx, opts, issue, currentUser, review, showOutdatedComments) if err != nil { return nil, err diff --git a/models/issues/comment_test.go b/models/issues/comment_test.go index c08e3b970d..eb37be56e5 100644 --- a/models/issues/comment_test.go +++ b/models/issues/comment_test.go @@ -68,7 +68,7 @@ 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, false) + res, err := issues_model.FetchCodeComments(db.DefaultContext, issue, user, false, nil) assert.NoError(t, err) assert.Contains(t, res, "README.md") assert.Contains(t, res["README.md"], int64(4)) @@ -76,7 +76,7 @@ func TestFetchCodeComments(t *testing.T) { 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, false) + res, err = issues_model.FetchCodeComments(db.DefaultContext, issue, user2, false, nil) assert.NoError(t, err) assert.Len(t, res, 1) } diff --git a/models/issues/review.go b/models/issues/review.go index 2667bdaa7b..0f8f5e6cfd 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -159,7 +159,7 @@ func (r *Review) LoadCodeComments(ctx context.Context) (err error) { if err = r.LoadIssue(ctx); err != nil { return err } - r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r, false) + r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r, false, nil) return err } diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 2c36477e6a..b9d8f131fd 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -14,6 +14,7 @@ import ( "net/http" "net/url" "path/filepath" + "sort" "strings" "code.gitea.io/gitea/models/db" @@ -40,6 +41,7 @@ import ( "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context/upload" "code.gitea.io/gitea/services/gitdiff" + user_service "code.gitea.io/gitea/services/user" ) const ( @@ -876,6 +878,10 @@ func ExcerptBlob(ctx *context.Context) { direction := ctx.FormString("direction") filePath := ctx.FormString("path") gitRepo := ctx.Repo.GitRepo + if ctx.FormBool("pull") { + ctx.Data["PageIsPullFiles"] = true + } + if ctx.Data["PageIsWiki"] == true { var err error gitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo()) @@ -936,7 +942,9 @@ func ExcerptBlob(ctx *context.Context) { RightIdx: idxRight, LeftHunkSize: leftHunkSize, RightHunkSize: rightHunkSize, + HasComments: false, }, + Comments: nil, } switch direction { case "up": @@ -945,10 +953,69 @@ func ExcerptBlob(ctx *context.Context) { section.Lines = append(section.Lines, lineSection) } } + issueIndex := ctx.FormInt64("issue_index") + if ctx.FormBool("pull") && issueIndex > 0 { + issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, issueIndex) + if err != nil { + ctx.ServerError("GetIssueByIndex", err) + return + } + allComments, err := issues_model.FetchCodeComments(ctx, issue, ctx.Doer, false, &filePath) + if err != nil { + ctx.ServerError("FetchCodeComments", err) + return + } + lineCommits := allComments[filePath] + for index, line := range section.Lines { + if line.SectionInfo != nil && line.Type == 4 && !(line.SectionInfo.LastRightIdx == 0 && index+1 == len(section.Lines)) { + start := int64(line.SectionInfo.LastRightIdx + 1) + end := int64(line.SectionInfo.RightIdx - 1) + for start <= end { + if _, ok := lineCommits[start]; ok { + if !line.SectionInfo.HasComments { + line.SectionInfo.HasComments = true + break + } + } + start++ + } + } + if comments, ok := lineCommits[int64(line.LeftIdx*-1)]; ok { + line.Comments = append(line.Comments, comments...) + } + if comments, ok := lineCommits[int64(line.RightIdx)]; ok { + line.Comments = append(line.Comments, comments...) + } + + sort.SliceStable(line.Comments, func(i, j int) bool { + return line.Comments[i].CreatedUnix < line.Comments[j].CreatedUnix + }) + } + for _, line := range section.Lines { + for _, comment := range line.Comments { + if err := comment.LoadAttachments(ctx); err != nil { + ctx.ServerError("LoadAttachments", err) + return + } + } + } + ctx.Data["Issue"] = issue + ctx.Data["IssueIndex"] = issue.Index + } ctx.Data["section"] = section ctx.Data["FileNameHash"] = git.HashFilePathForWebUI(filePath) ctx.Data["AfterCommitID"] = commitID ctx.Data["Anchor"] = anchor + ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool { + return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee) + } + if ctx.Data["SignedUserID"] == nil { + ctx.Data["SignedUserID"] = ctx.Doer.ID + } + ctx.Data["SignedUser"] = ctx.Doer + ctx.Data["IsSigned"] = ctx.Doer != nil + ctx.Data["Repository"] = ctx.Repo.Repository + ctx.Data["Permission"] = &ctx.Repo.Permission ctx.HTML(http.StatusOK, tplBlobExcerpt) } @@ -977,6 +1044,7 @@ func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chu RightIdx: line + 1, Type: gitdiff.DiffLinePlain, Content: " " + lineText, + Comments: []*issues_model.Comment{}, } diffLines = append(diffLines, diffLine) } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index c72664f8e9..3bd7caf67c 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -127,6 +127,7 @@ func getPullInfo(ctx *context.Context) (issue *issues_model.Issue, ok bool) { } ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, emoji.ReplaceAliases(issue.Title)) ctx.Data["Issue"] = issue + ctx.Data["IssueIndex"] = issue.Index if !issue.IsPull { ctx.NotFound(nil) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 9ee86d9dfc..05eb3198ed 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -95,6 +95,7 @@ type DiffLineSectionInfo struct { RightIdx int LeftHunkSize int RightHunkSize int + HasComments bool } // DiffHTMLOperation is the HTML version of diffmatchpatch.Diff @@ -189,6 +190,7 @@ func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int RightIdx: rightLine, LeftHunkSize: leftHunk, RightHunkSize: righHunk, + HasComments: false, } } @@ -431,6 +433,7 @@ func (diffFile *DiffFile) GetTailSectionAndLimitedContent(leftCommit, rightCommi LastRightIdx: lastLine.RightIdx, LeftIdx: leftLineCount, RightIdx: rightLineCount, + HasComments: false, }, } tailSection := &DiffSection{FileName: diffFile.Name, Lines: []*DiffLine{tailDiffLine}} @@ -501,14 +504,28 @@ type Diff struct { // LoadComments loads comments into each line 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) + allComments, err := issues_model.FetchCodeComments(ctx, issue, currentUser, showOutdatedComments, nil) if err != nil { return err } + for _, file := range diff.Files { if lineCommits, ok := allComments[file.Name]; ok { for _, section := range file.Sections { - for _, line := range section.Lines { + for index, line := range section.Lines { + if line.SectionInfo != nil && line.Type == 4 && !(line.SectionInfo.LastRightIdx == 0 && index+1 == len(section.Lines)) { + start := int64(line.SectionInfo.LastRightIdx + 1) + end := int64(line.SectionInfo.RightIdx - 1) + for start <= end { + if _, ok := lineCommits[start]; ok { + if !line.SectionInfo.HasComments { + line.SectionInfo.HasComments = true + break + } + } + start++ + } + } if comments, ok := lineCommits[int64(line.LeftIdx*-1)]; ok { line.Comments = append(line.Comments, comments...) } diff --git a/services/repository/files/diff_test.go b/services/repository/files/diff_test.go index ae702e4189..fd1d7caebc 100644 --- a/services/repository/files/diff_test.go +++ b/services/repository/files/diff_test.go @@ -62,6 +62,7 @@ func TestGetDiffPreview(t *testing.T) { RightIdx: 1, LeftHunkSize: 3, RightHunkSize: 4, + HasComments: false, }, }, { diff --git a/templates/repo/diff/blob_excerpt.tmpl b/templates/repo/diff/blob_excerpt.tmpl index 4089d8fb33..941ac44ae2 100644 --- a/templates/repo/diff/blob_excerpt.tmpl +++ b/templates/repo/diff/blob_excerpt.tmpl @@ -1,10 +1,37 @@ {{$blobExcerptLink := print $.RepoLink (Iif $.PageIsWiki "/wiki" "") "/blob_excerpt/" (PathEscape $.AfterCommitID) (QueryBuild "?" "anchor" $.Anchor)}} {{if $.IsSplitStyle}} {{range $k, $line := $.section.Lines}} + {{$inlineDiff := $.section.GetComputedInlineDiffFor $line ctx.Locale}} <tr class="{{.GetHTMLDiffLineType}}-code nl-{{$k}} ol-{{$k}} line-expanded"> {{if eq .GetType 4}} {{$expandDirection := $line.GetExpandDirection}} <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"> + <div class="lines-comment"> + <div> + {{if $line.SectionInfo.HasComments}} + <button class="section-comment-icon"> + {{svg "octicon-comment-discussion"}} + </button> + {{end}} + </div> + <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> + {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=down&wiki={{$.PageIsWiki}}&pull={{$.PageIsPullFiles}}&anchor={{$.Anchor}}&issue_index={{$.IssueIndex}}"> + {{svg "octicon-fold-down"}} + </button> + {{end}} + {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=up&wiki={{$.PageIsWiki}}&pull={{$.PageIsPullFiles}}&anchor={{$.Anchor}}&issue_index={{$.IssueIndex}}"> + {{svg "octicon-fold-up"}} + </button> + {{end}} + {{if eq $expandDirection 2}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=&wiki={{$.PageIsWiki}}&pull={{$.PageIsPullFiles}}&anchor={{$.Anchor}}}&issue_index={{$.IssueIndex}}"> + {{svg "octicon-fold"}} + </button> + {{end}} + </div> + </div> <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=split&direction=down"> @@ -28,62 +55,104 @@ {{- template "repo/diff/section_code" dict "diff" $inlineDiff -}} </td> {{else}} - {{$inlineDiff := $.section.GetComputedInlineDiffFor $line ctx.Locale}} <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{$.FileNameHash}}L{{$line.LeftIdx}}{{end}}"></span></td> <td class="lines-escape lines-escape-old">{{if and $line.LeftIdx $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td> <td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="tw-font-mono" data-type-marker=""></span>{{end}}</td> - <td class="lines-code lines-code-old"> - {{- if $line.LeftIdx -}} - {{- template "repo/diff/section_code" dict "diff" $inlineDiff -}} - {{- else -}} - <code class="code-inner"></code> - {{- end -}} - </td> + <td class="lines-code lines-code-old">{{/* + */}}{{if and $.SignedUserID $.PageIsPullFiles}}{{/* + */}}<button type="button" aria-label="{{ctx.Locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} tw-invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{/* + */}}{{svg "octicon-plus"}}{{/* + */}}</button>{{/* + */}}{{end}}{{/* + */}}{{if $line.LeftIdx}}{{template "repo/diff/section_code" dict "diff" $inlineDiff}}{{else}}{{/* + */}}<code class="code-inner"></code>{{/* + */}}{{end}}{{/* + */}}</td> <td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{$.FileNameHash}}R{{$line.RightIdx}}{{end}}"></span></td> <td class="lines-escape lines-escape-new">{{if and $line.RightIdx $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td> <td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="tw-font-mono" data-type-marker=""></span>{{end}}</td> - <td class="lines-code lines-code-new"> - {{- if $line.RightIdx -}} - {{- template "repo/diff/section_code" dict "diff" $inlineDiff -}} - {{- else -}} - <code class="code-inner"></code> - {{- end -}} - </td> + <td class="lines-code lines-code-new">{{/* + */}}{{if and $.SignedUserID $.PageIsPullFiles}}{{/* + */}}<button type="button" aria-label="{{ctx.Locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} tw-invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{/* + */}}{{svg "octicon-plus"}}{{/* + */}}</button>{{/* + */}}{{end}}{{/* + */}}{{if $line.RightIdx}}{{template "repo/diff/section_code" dict "diff" $inlineDiff}}{{else}}{{/* + */}}<code class="code-inner"></code>{{/* + */}}{{end}}{{/* + */}}</td> {{end}} </tr> + {{if $line.Comments}} + <tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}"> + <td class="add-comment-right" colspan="5"> + {{template "repo/diff/conversation" dict "." $ "comments" $line.Comments}}} + </td> + </tr> + {{end}} {{end}} {{else}} {{range $k, $line := $.section.Lines}} + {{$inlineDiff := $.section.GetComputedInlineDiffFor $line ctx.Locale}} <tr class="{{.GetHTMLDiffLineType}}-code nl-{{$k}} ol-{{$k}} line-expanded"> {{if eq .GetType 4}} {{$expandDirection := $line.GetExpandDirection}} <td colspan="2" class="lines-num"> - <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> - {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=unified&direction=down"> - {{svg "octicon-fold-down"}} - </button> - {{end}} - {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=unified&direction=up"> - {{svg "octicon-fold-up"}} - </button> - {{end}} - {{if eq $expandDirection 2}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=unified"> - {{svg "octicon-fold"}} - </button> - {{end}} + <div class="lines-comment"> + <div> + {{if $line.SectionInfo.HasComments}} + <button class="section-comment-icon"> + {{svg "octicon-comment-discussion"}} + </button> + {{end}} + </div> + <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> + {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=down&wiki={{$.PageIsWiki}}&pull={{$.PageIsPullFiles}}&anchor={{$.Anchor}}}&issue_index={{$.IssueIndex}}"> + {{svg "octicon-fold-down"}} + </button> + {{end}} + {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=up&wiki={{$.PageIsWiki}}&pull={{$.PageIsPullFiles}}&anchor={{$.Anchor}}}&issue_index={{$.IssueIndex}}"> + {{svg "octicon-fold-up"}} + </button> + {{end}} + {{if eq $expandDirection 2}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=&wiki={{$.PageIsWiki}}&pull={{$.PageIsPullFiles}}&anchor={{$.Anchor}}}&issue_index={{$.IssueIndex}}"> + {{svg "octicon-fold"}} + </button> + {{end}} + </div> </div> </td> {{else}} <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{$.FileNameHash}}L{{$line.LeftIdx}}{{end}}"></span></td> <td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{$.FileNameHash}}R{{$line.RightIdx}}{{end}}"></span></td> {{end}} - {{$inlineDiff := $.section.GetComputedInlineDiffFor $line ctx.Locale}} <td class="lines-escape">{{if $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td> <td class="lines-type-marker"><span class="tw-font-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td> - <td class="lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}"><code {{if $inlineDiff.EscapeStatus.Escaped}}class="code-inner has-escaped" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"{{else}}class="code-inner"{{end}}>{{$inlineDiff.Content}}</code></td> + <td class="lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}"> + {{if and $.SignedUserID $.PageIsPullFiles}} + <button type="button" aria-label="{{ctx.Locale.Tr "repo.diff.comment.add_line_comment"}}" class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} tw-invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}"> + {{svg "octicon-plus"}} + </button> + {{end}} + <code {{if $inlineDiff.EscapeStatus.Escaped}}class="code-inner has-escaped" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"{{else}}class="code-inner"{{end}}>{{$inlineDiff.Content}}</code> + </td> </tr> + {{if $line.Comments}} + <tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}"> + <td class="add-comment-right" colspan="5"> + {{template "repo/diff/conversation" dict "." $ "comments" $line.Comments}} + </td> + </tr> + <button class="pull-request-diff-comments hidden"></button> + <script> + var $buttons = document.querySelector('button.pull-request-diff-comments'); + if ($buttons) { + $buttons.click(); + } + </script> + {{end}} {{end}} {{end}} diff --git a/templates/repo/diff/section_split.tmpl b/templates/repo/diff/section_split.tmpl index 9953db5eb2..a05ac8b836 100644 --- a/templates/repo/diff/section_split.tmpl +++ b/templates/repo/diff/section_split.tmpl @@ -1,4 +1,6 @@ {{$file := .file}} +{{$blobExcerptRepoLink := or ctx.RootData.CommitRepoLink ctx.RootData.RepoLink}} +{{$issueIndex := or ctx.RootData.IssueIndex $.root.IssueIndex}} {{$blobExcerptLink := print (or ctx.RootData.CommitRepoLink ctx.RootData.RepoLink) (Iif $.root.PageIsWiki "/wiki" "") "/blob_excerpt/" (PathEscape $.root.AfterCommitID) "?"}} <colgroup> <col width="50"> @@ -18,22 +20,31 @@ {{if eq .GetType 4}} {{$expandDirection := $line.GetExpandDirection}} <td class="lines-num lines-num-old"> - <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> - {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=split&direction=down&&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}"> - {{svg "octicon-fold-down"}} - </button> - {{end}} - {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=split&direction=up&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}"> - {{svg "octicon-fold-up"}} - </button> - {{end}} - {{if eq $expandDirection 2}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=split&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}"> - {{svg "octicon-fold"}} - </button> - {{end}} + <div class="lines-comment"> + <div> + {{if $line.SectionInfo.HasComments}} + <button class="section-comment-icon"> + {{svg "octicon-comment-discussion"}} + </button> + {{end}} + </div> + <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> + {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=down&wiki={{$.root.PageIsWiki}}&pull={{$.root.PageIsPullFiles}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}&issue_index={{$issueIndex}}"> + {{svg "octicon-fold-down"}} + </button> + {{end}} + {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=up&wiki={{$.root.PageIsWiki}}&pull={{$.root.PageIsPullFiles}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}&issue_index={{$issueIndex}}"> + {{svg "octicon-fold-up"}} + </button> + {{end}} + {{if eq $expandDirection 2}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=&wiki={{$.root.PageIsWiki}}&pull={{$.root.PageIsPullFiles}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}&issue_index={{$issueIndex}}"> + {{svg "octicon-fold"}} + </button> + {{end}} + </div> </div> </td>{{$inlineDiff := $section.GetComputedInlineDiffFor $line ctx.Locale}} <td class="lines-escape lines-escape-old">{{if $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td> diff --git a/templates/repo/diff/section_unified.tmpl b/templates/repo/diff/section_unified.tmpl index cb612bc27c..948c67f178 100644 --- a/templates/repo/diff/section_unified.tmpl +++ b/templates/repo/diff/section_unified.tmpl @@ -1,4 +1,6 @@ {{$file := .file}} +{{$blobExcerptRepoLink := or ctx.RootData.CommitRepoLink ctx.RootData.RepoLink}} +{{$issueIndex := or ctx.RootData.IssueIndex $.root.IssueIndex}} {{$repoLink := or ctx.RootData.CommitRepoLink ctx.RootData.RepoLink}} {{$afterCommitID := or $.root.AfterCommitID "no-after-commit-id"}}{{/* this tmpl is also used by the PR Conversation page, so the "AfterCommitID" may not exist */}} {{$blobExcerptLink := print $repoLink (Iif $.root.PageIsWiki "/wiki" "") "/blob_excerpt/" (PathEscape $afterCommitID) "?"}} @@ -16,22 +18,31 @@ {{if $.root.AfterCommitID}} {{$expandDirection := $line.GetExpandDirection}} <td colspan="2" class="lines-num"> - <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> - {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=unified&direction=down&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}"> - {{svg "octicon-fold-down"}} - </button> - {{end}} - {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=unified&direction=up&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}"> - {{svg "octicon-fold-up"}} - </button> - {{end}} - {{if eq $expandDirection 2}} - <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptLink}}&{{$line.GetBlobExcerptQuery}}&style=unified&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}"> - {{svg "octicon-fold"}} - </button> - {{end}} + <div class="lines-comment"> + <div> + {{if $line.SectionInfo.HasComments}} + <button class="section-comment-icon"> + {{svg "octicon-comment-discussion"}} + </button> + {{end}} + </div> + <div class="code-expander-buttons" data-expand-direction="{{$expandDirection}}"> + {{if or (eq $expandDirection 3) (eq $expandDirection 5)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=down&wiki={{$.root.PageIsWiki}}&pull={{$.root.PageIsPullFiles}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}&issue_index={{$issueIndex}}"> + {{svg "octicon-fold-down"}} + </button> + {{end}} + {{if or (eq $expandDirection 3) (eq $expandDirection 4)}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=up&wiki={{$.root.PageIsWiki}}&pull={{$.root.PageIsPullFiles}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}&issue_index={{$issueIndex}}"> + {{svg "octicon-fold-up"}} + </button> + {{end}} + {{if eq $expandDirection 2}} + <button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=&wiki={{$.root.PageIsWiki}}&pull={{$.root.PageIsPullFiles}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}&issue_index={{$issueIndex}}"> + {{svg "octicon-fold"}} + </button> + {{end}} + </div> </div> </td> {{else}} diff --git a/web_src/css/base.css b/web_src/css/base.css index 37ee7f5832..4b448aa822 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -907,6 +907,17 @@ overflow-menu .ui.label { font-family: var(--fonts-regular); } +.lines-comment { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1px; +} + +.section-comment-icon { + cursor: default; +} + .lines-commit .blame-info .blame-data .blame-message { flex-grow: 2; overflow: hidden; diff --git a/web_src/js/features/repo-diff.ts b/web_src/js/features/repo-diff.ts index ad1da5c2fa..d37c7e90a5 100644 --- a/web_src/js/features/repo-diff.ts +++ b/web_src/js/features/repo-diff.ts @@ -10,6 +10,7 @@ import {POST, GET} from '../modules/fetch.ts'; import {createTippy} from '../modules/tippy.ts'; import {invertFileFolding} from './file-fold.ts'; import {parseDom} from '../utils.ts'; +import {initGlobalDropdown} from './common-page.ts'; import {registerGlobalSelectorFunc} from '../modules/observer.ts'; const {i18n} = window.config; @@ -92,6 +93,12 @@ function initRepoDiffConversationForm() { } }); + addDelegatedEventListener(document, 'click', '.pull-request-diff-comments', async (el, e) => { + e.preventDefault(); + initGlobalDropdown(); + // Post initiation cleaning up the buttons and scripts + el.remove(); + }); addDelegatedEventListener(document, 'click', '.resolve-conversation', async (el, e) => { e.preventDefault(); const comment_id = el.getAttribute('data-comment-id');