diff options
-rw-r--r-- | models/issue_comment.go | 65 | ||||
-rw-r--r-- | modules/auth/repo_form.go | 1 | ||||
-rw-r--r-- | routers/repo/pull_review.go | 62 | ||||
-rw-r--r-- | routers/routes/macaron.go | 1 | ||||
-rw-r--r-- | templates/repo/diff/box.tmpl | 37 | ||||
-rw-r--r-- | templates/repo/diff/comment_form.tmpl | 3 | ||||
-rw-r--r-- | templates/repo/diff/conversation.tmpl | 4 | ||||
-rw-r--r-- | templates/repo/diff/new_comment.tmpl | 6 | ||||
-rw-r--r-- | templates/repo/diff/section_split.tmpl | 8 | ||||
-rw-r--r-- | templates/repo/diff/section_unified.tmpl | 6 | ||||
-rw-r--r-- | templates/repo/issue/view_content/comments.tmpl | 2 | ||||
-rw-r--r-- | web_src/js/index.js | 102 |
12 files changed, 205 insertions, 92 deletions
diff --git a/models/issue_comment.go b/models/issue_comment.go index a5cb91ac75..dd979edcda 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -979,7 +979,7 @@ func (opts *FindCommentsOptions) toConds() builder.Cond { if opts.Type != CommentTypeUnknown { cond = cond.And(builder.Eq{"comment.type": opts.Type}) } - if opts.Line > 0 { + if opts.Line != 0 { cond = cond.And(builder.Eq{"comment.line": opts.Line}) } if len(opts.TreePath) > 0 { @@ -1078,18 +1078,35 @@ func fetchCodeCommentsByReview(e Engine, issue *Issue, currentUser *User, review if review == nil { review = &Review{ID: 0} } - //Find comments opts := FindCommentsOptions{ Type: CommentTypeCode, IssueID: issue.ID, ReviewID: review.ID, } + + comments, err := findCodeComments(e, opts, issue, currentUser, review) + if err != nil { + return nil, err + } + + for _, comment := range comments { + if pathToLineToComment[comment.TreePath] == nil { + pathToLineToComment[comment.TreePath] = make(map[int64][]*Comment) + } + pathToLineToComment[comment.TreePath][comment.Line] = append(pathToLineToComment[comment.TreePath][comment.Line], comment) + } + return pathToLineToComment, nil +} + +func findCodeComments(e Engine, opts FindCommentsOptions, issue *Issue, currentUser *User, review *Review) ([]*Comment, error) { + var comments []*Comment + if review == nil { + review = &Review{ID: 0} + } conds := opts.toConds() if review.ID == 0 { conds = conds.And(builder.Eq{"invalidated": false}) } - - var comments []*Comment if err := e.Where(conds). Asc("comment.created_unix"). Asc("comment.id"). @@ -1117,7 +1134,19 @@ func fetchCodeCommentsByReview(e Engine, issue *Issue, currentUser *User, review return nil, err } + n := 0 for _, comment := range comments { + if re, ok := reviews[comment.ReviewID]; ok && re != nil { + // If the review is pending only the author can see the comments (except if the review is set) + if review.ID == 0 && re.Type == ReviewTypePending && + (currentUser == nil || currentUser.ID != re.ReviewerID) { + continue + } + comment.Review = re + } + comments[n] = comment + n++ + if err := comment.LoadResolveDoer(); err != nil { return nil, err } @@ -1126,25 +1155,21 @@ func fetchCodeCommentsByReview(e Engine, issue *Issue, currentUser *User, review return nil, err } - if re, ok := reviews[comment.ReviewID]; ok && re != nil { - // If the review is pending only the author can see the comments (except the review is set) - if review.ID == 0 { - if re.Type == ReviewTypePending && - (currentUser == nil || currentUser.ID != re.ReviewerID) { - continue - } - } - comment.Review = re - } - comment.RenderedContent = string(markdown.Render([]byte(comment.Content), issue.Repo.Link(), issue.Repo.ComposeMetas())) - if pathToLineToComment[comment.TreePath] == nil { - pathToLineToComment[comment.TreePath] = make(map[int64][]*Comment) - } - pathToLineToComment[comment.TreePath][comment.Line] = append(pathToLineToComment[comment.TreePath][comment.Line], comment) } - return pathToLineToComment, nil + return comments[:n], nil +} + +// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number +func FetchCodeCommentsByLine(issue *Issue, currentUser *User, treePath string, line int64) ([]*Comment, error) { + opts := FindCommentsOptions{ + Type: CommentTypeCode, + IssueID: issue.ID, + TreePath: treePath, + Line: line, + } + return findCodeComments(x, opts, issue, currentUser, nil) } // FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index 87f2a53510..78b2197a2d 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -548,6 +548,7 @@ func (f *MergePullRequestForm) Validate(ctx *macaron.Context, errs binding.Error // CodeCommentForm form for adding code comments for PRs type CodeCommentForm struct { + Origin string `binding:"Required;In(timeline,diff)"` Content string `binding:"Required"` Side string `binding:"Required;In(previous,proposed)"` Line int64 diff --git a/routers/repo/pull_review.go b/routers/repo/pull_review.go index 730074b7f3..0bacc68232 100644 --- a/routers/repo/pull_review.go +++ b/routers/repo/pull_review.go @@ -9,11 +9,40 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" + "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" pull_service "code.gitea.io/gitea/services/pull" ) +const ( + tplConversation base.TplName = "repo/diff/conversation" + tplNewComment base.TplName = "repo/diff/new_comment" +) + +// RenderNewCodeCommentForm will render the form for creating a new review comment +func RenderNewCodeCommentForm(ctx *context.Context) { + issue := GetActionIssue(ctx) + if !issue.IsPull { + return + } + currentReview, err := models.GetCurrentReview(ctx.User, issue) + if err != nil && !models.IsErrReviewNotExist(err) { + ctx.ServerError("GetCurrentReview", err) + return + } + ctx.Data["PageIsPullFiles"] = true + ctx.Data["Issue"] = issue + ctx.Data["CurrentReview"] = currentReview + pullHeadCommitID, err := ctx.Repo.GitRepo.GetRefCommitID(issue.PullRequest.GetGitRefName()) + if err != nil { + ctx.ServerError("GetRefCommitID", err) + return + } + ctx.Data["AfterCommitID"] = pullHeadCommitID + ctx.HTML(200, tplNewComment) +} + // CreateCodeComment will create a code comment including an pending review if required func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) { issue := GetActionIssue(ctx) @@ -58,11 +87,17 @@ func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) { } log.Trace("Comment created: %-v #%d[%d] Comment[%d]", ctx.Repo.Repository, issue.Index, issue.ID, comment.ID) + + if form.Origin == "diff" { + renderConversation(ctx, comment) + return + } ctx.Redirect(comment.HTMLURL()) } // UpdateResolveConversation add or remove an Conversation resolved mark func UpdateResolveConversation(ctx *context.Context) { + origin := ctx.Query("origin") action := ctx.Query("action") commentID := ctx.QueryInt64("comment_id") @@ -103,11 +138,38 @@ func UpdateResolveConversation(ctx *context.Context) { return } + if origin == "diff" { + renderConversation(ctx, comment) + return + } ctx.JSON(200, map[string]interface{}{ "ok": true, }) } +func renderConversation(ctx *context.Context, comment *models.Comment) { + comments, err := models.FetchCodeCommentsByLine(comment.Issue, ctx.User, comment.TreePath, comment.Line) + if err != nil { + ctx.ServerError("FetchCodeCommentsByLine", err) + return + } + ctx.Data["PageIsPullFiles"] = true + ctx.Data["comments"] = comments + ctx.Data["CanMarkConversation"] = true + ctx.Data["Issue"] = comment.Issue + if err = comment.Issue.LoadPullRequest(); err != nil { + ctx.ServerError("comment.Issue.LoadPullRequest", err) + return + } + pullHeadCommitID, err := ctx.Repo.GitRepo.GetRefCommitID(comment.Issue.PullRequest.GetGitRefName()) + if err != nil { + ctx.ServerError("GetRefCommitID", err) + return + } + ctx.Data["AfterCommitID"] = pullHeadCommitID + ctx.HTML(200, tplConversation) +} + // SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist func SubmitReview(ctx *context.Context, form auth.SubmitReviewForm) { issue := GetActionIssue(ctx) diff --git a/routers/routes/macaron.go b/routers/routes/macaron.go index ca3599b7a0..d54cd580d3 100644 --- a/routers/routes/macaron.go +++ b/routers/routes/macaron.go @@ -856,6 +856,7 @@ func RegisterMacaronRoutes(m *macaron.Macaron) { m.Group("/files", func() { m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.ViewPullFiles) m.Group("/reviews", func() { + m.Get("/new_comment", repo.RenderNewCodeCommentForm) m.Post("/comments", bindIgnErr(auth.CodeCommentForm{}), repo.CreateCodeComment) m.Post("/submit", bindIgnErr(auth.SubmitReviewForm{}), repo.SubmitReview) }, context.RepoMustNotBeArchived()) diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index ef152fa58b..8533f9b910 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -144,28 +144,25 @@ {{end}} {{if not $.Repository.IsArchived}} - <div id="pull_review_add_comment" class="hide"> - {{template "repo/diff/new_comment" dict "root" .}} + <div class="hide" id="edit-content-form"> + <div class="ui comment form"> + <div class="ui top attached tabular menu"> + <a class="active write item">{{$.i18n.Tr "write"}}</a> + <a class="preview item" data-url="{{$.Repository.APIURL}}/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a> </div> - <div class="hide" id="edit-content-form"> - <div class="ui comment form"> - <div class="ui top attached tabular menu"> - <a class="active write item">{{$.i18n.Tr "write"}}</a> - <a class="preview item" data-url="{{$.Repository.APIURL}}/markdown" data-context="{{$.RepoLink}}">{{$.i18n.Tr "preview"}}</a> - </div> - <div class="ui bottom attached active write tab segment"> - <textarea class="review-textarea" tabindex="1" name="content"></textarea> - </div> - <div class="ui bottom attached tab preview segment markdown"> - {{$.i18n.Tr "loading"}} - </div> - <div class="text right edit buttons"> - <div class="ui basic blue cancel button" tabindex="3">{{.i18n.Tr "repo.issues.cancel"}}</div> - <div class="ui green save button" tabindex="2">{{.i18n.Tr "repo.issues.save"}}</div> - </div> - </div> + <div class="ui bottom attached active write tab segment"> + <textarea class="review-textarea" tabindex="1" name="content"></textarea> + </div> + <div class="ui bottom attached tab preview segment markdown"> + {{$.i18n.Tr "loading"}} + </div> + <div class="text right edit buttons"> + <div class="ui basic blue cancel button" tabindex="3">{{.i18n.Tr "repo.issues.cancel"}}</div> + <div class="ui green save button" tabindex="2">{{.i18n.Tr "repo.issues.save"}}</div> </div> - {{end}} + </div> + </div> + {{end}} {{if .IsSplitStyle}} <script> diff --git a/templates/repo/diff/comment_form.tmpl b/templates/repo/diff/comment_form.tmpl index 33626f31d3..b12beeab82 100644 --- a/templates/repo/diff/comment_form.tmpl +++ b/templates/repo/diff/comment_form.tmpl @@ -6,6 +6,7 @@ {{end}} <form class="ui form {{if $.hidden}}hide comment-form comment-form-reply{{end}}" action="{{$.root.Issue.HTMLURL}}/files/reviews/comments" method="post"> {{$.root.CsrfTokenHtml}} + <input type="hidden" name="origin" value="{{if $.root.PageIsPullFiles}}diff{{else}}timeline{{end}}"> <input type="hidden" name="latest_commit_id" value="{{$.root.AfterCommitID}}"/> <input type="hidden" name="side" value="{{if $.Side}}{{$.Side}}{{end}}"> <input type="hidden" name="line" value="{{if $.Line}}{{$.Line}}{{end}}"> @@ -29,7 +30,7 @@ <span class="markdown-info">{{svg "octicon-markdown"}} {{$.root.i18n.Tr "repo.diff.comment.markdown_info"}}</span> <div class="ui right"> {{if $.reply}} - <button class="ui submit green tiny button btn-reply" onclick="window.submitReply(this);">{{$.root.i18n.Tr "repo.diff.comment.reply"}}</button> + <button class="ui submit green tiny button btn-reply" type="submit">{{$.root.i18n.Tr "repo.diff.comment.reply"}}</button> <input type="hidden" name="reply" value="{{$.reply}}"> {{else}} {{if $.root.CurrentReview}} diff --git a/templates/repo/diff/conversation.tmpl b/templates/repo/diff/conversation.tmpl index 98898eee60..4dd7de0fc1 100644 --- a/templates/repo/diff/conversation.tmpl +++ b/templates/repo/diff/conversation.tmpl @@ -1,7 +1,7 @@ {{$resolved := (index .comments 0).IsResolved}} {{$resolveDoer := (index .comments 0).ResolveDoer}} {{$isNotPending := (not (eq (index .comments 0).Review.Type 0))}} -<div class="conversation-holder"> +<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"> <span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span> @@ -23,7 +23,7 @@ </div> {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index .comments 0).ReviewID "root" $ "comment" (index .comments 0)}} {{if and $.CanMarkConversation $isNotPending}} - <button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index .comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" > + <button class="ui icon tiny 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}} {{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}} {{else}} diff --git a/templates/repo/diff/new_comment.tmpl b/templates/repo/diff/new_comment.tmpl index d8b6ccb9dd..6a71539ab0 100644 --- a/templates/repo/diff/new_comment.tmpl +++ b/templates/repo/diff/new_comment.tmpl @@ -1,3 +1,5 @@ -<div class="field comment-code-cloud"> - {{template "repo/diff/comment_form_datahandler" .}} +<div class="conversation-holder"> + <div class="field comment-code-cloud"> + {{template "repo/diff/comment_form_datahandler" .}} + </div> </div> diff --git a/templates/repo/diff/section_split.tmpl b/templates/repo/diff/section_split.tmpl index 7e62bf3e1a..2f959ac2da 100644 --- a/templates/repo/diff/section_split.tmpl +++ b/templates/repo/diff/section_split.tmpl @@ -1,7 +1,7 @@ {{$file := .file}} {{range $j, $section := $file.Sections}} {{range $k, $line := $section.Lines}} - <tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}"> + <tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}" data-line-type="{{DiffLineTypeToStr .GetType}}"> {{if eq .GetType 4}} <td class="lines-num lines-num-old"> {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }} @@ -24,14 +24,14 @@ {{else}} <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td> <td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td> - <td class="lines-code lines-code-old halfwidth">{{if and $.root.SignedUserID $line.CanComment $.root.PageIsPullFiles (not (eq .GetType 2))}}<a class="ui primary button add-code-comment add-code-comment-left" data-path="{{$file.Name}}" data-side="left" data-idx="{{$line.LeftIdx}}">{{svg "octicon-plus"}}</a>{{end}}<code class="code-inner">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</code></td> + <td class="lines-code lines-code-old halfwidth">{{if and $.root.SignedUserID $.root.PageIsPullFiles (not (eq .GetType 2))}}<a class="ui primary button add-code-comment add-code-comment-left{{if (not $line.CanComment)}} invisible{{end}}" data-path="{{$file.Name}}" data-side="left" data-idx="{{$line.LeftIdx}}" data-new-comment-url="{{$.root.Issue.HTMLURL}}/files/reviews/new_comment">{{svg "octicon-plus"}}</a>{{end}}<code class="code-inner">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</code></td> <td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td> <td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td> - <td class="lines-code lines-code-new halfwidth">{{if and $.root.SignedUserID $line.CanComment $.root.PageIsPullFiles (not (eq .GetType 3))}}<a class="ui primary button add-code-comment add-code-comment-right" data-path="{{$file.Name}}" data-side="right" data-idx="{{$line.RightIdx}}">{{svg "octicon-plus"}}</a>{{end}}<code class="code-inner">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</code></td> + <td class="lines-code lines-code-new halfwidth">{{if and $.root.SignedUserID $.root.PageIsPullFiles (not (eq .GetType 3))}}<a class="ui primary button add-code-comment add-code-comment-right{{if (not $line.CanComment)}} invisible{{end}}" data-path="{{$file.Name}}" data-side="right" data-idx="{{$line.RightIdx}}" data-new-comment-url="{{$.root.Issue.HTMLURL}}/files/reviews/new_comment">{{svg "octicon-plus"}}</a>{{end}}<code class="code-inner">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</code></td> {{end}} </tr> {{if gt (len $line.Comments) 0}} - <tr class="add-code-comment"> + <tr class="add-comment" data-line-type="{{DiffLineTypeToStr .GetType}}"> <td class="lines-num"></td> <td class="lines-type-marker"></td> <td class="add-comment-left"> diff --git a/templates/repo/diff/section_unified.tmpl b/templates/repo/diff/section_unified.tmpl index 5376e77630..96e193df73 100644 --- a/templates/repo/diff/section_unified.tmpl +++ b/templates/repo/diff/section_unified.tmpl @@ -2,7 +2,7 @@ {{range $j, $section := $file.Sections}} {{range $k, $line := $section.Lines}} {{if or $.root.AfterCommitID (ne .GetType 4)}} - <tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}"> + <tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}" data-line-type="{{DiffLineTypeToStr .GetType}}"> {{if eq .GetType 4}} <td colspan="2" class="lines-num"> {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }} @@ -29,11 +29,11 @@ {{if eq .GetType 4}} <td class="chroma lines-code blob-hunk"><code class="code-inner">{{$section.GetComputedInlineDiffFor $line}}</code></td> {{else}} - <td class="chroma lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{if and $.root.SignedUserID $line.CanComment $.root.PageIsPullFiles}}<a class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}" data-path="{{$file.Name}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{svg "octicon-plus"}}</a>{{end}}<code class="code-inner">{{$section.GetComputedInlineDiffFor $line}}</code></td> + <td class="chroma lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{if and $.root.SignedUserID $.root.PageIsPullFiles}}<a class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} invisible{{end}}" data-path="{{$file.Name}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}" data-new-comment-url="{{$.root.Issue.HTMLURL}}/files/reviews/new_comment">{{svg "octicon-plus"}}</a>{{end}}<code class="code-inner">{{$section.GetComputedInlineDiffFor $line}}</code></td> {{end}} </tr> {{if gt (len $line.Comments) 0}} - <tr> + <tr class="add-comment" data-line-type="{{DiffLineTypeToStr .GetType}}"> <td colspan="2" class="lines-num"></td> <td class="add-comment-left add-comment-right" colspan="2"> {{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index bc5d7dde12..8f5426b83e 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -530,7 +530,7 @@ {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $comms 0).ReviewID "root" $ "comment" (index $comms 0)}} {{if and $.CanMarkConversation $isNotPending}} - <button class="ui tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $comms 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" > + <button class="ui tiny button resolve-conversation" data-origin="timeline" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $comms 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" > {{if $resolved}} {{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}} {{else}} diff --git a/web_src/js/index.js b/web_src/js/index.js index ef674ad6a6..37c31538af 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -907,7 +907,7 @@ async function initRepository() { }); // Quote reply - $('.quote-reply').on('click', function (event) { + $(document).on('click', '.quote-reply', function (event) { $(this).closest('.dropdown').find('.menu').toggle('visible'); const target = $(this).data('target'); const quote = $(`#comment-${target}`).text().replace(/\n/g, '\n> '); @@ -933,7 +933,7 @@ async function initRepository() { }); // Edit issue or comment content - $('.edit-content').on('click', async function (event) { + $(document).on('click', '.edit-content', async function (event) { $(this).closest('.dropdown').find('.menu').toggle('visible'); const $segment = $(this).closest('.header').next(); const $editContentZone = $segment.find('.edit-content-zone'); @@ -1096,7 +1096,7 @@ async function initRepository() { }); // Delete comment - $('.delete-comment').on('click', function () { + $(document).on('click', '.delete-comment', function () { const $this = $(this); if (window.confirm($this.data('locale'))) { $.post($this.data('url'), { @@ -1105,6 +1105,15 @@ async function initRepository() { const $conversationHolder = $this.closest('.conversation-holder'); $(`#${$this.data('comment-id')}`).remove(); if ($conversationHolder.length && !$conversationHolder.find('.comment').length) { + const path = $conversationHolder.data('path'); + const side = $conversationHolder.data('side'); + const idx = $conversationHolder.data('idx'); + const lineType = $conversationHolder.closest('tr').data('line-type'); + if (lineType === 'same') { + $(`a.add-code-comment[data-path="${path}"][data-idx="${idx}"]`).removeClass('invisible'); + } else { + $(`a.add-code-comment[data-path="${path}"][data-side="${side}"][data-idx="${idx}"]`).removeClass('invisible'); + } $conversationHolder.remove(); } }); @@ -1235,7 +1244,7 @@ function initPullRequestReview() { } } - $('.show-outdated').on('click', function (e) { + $(document).on('click', '.show-outdated', function (e) { e.preventDefault(); const id = $(this).data('comment'); $(this).addClass('hide'); @@ -1244,7 +1253,7 @@ function initPullRequestReview() { $(`#hide-outdated-${id}`).removeClass('hide'); }); - $('.hide-outdated').on('click', function (e) { + $(document).on('click', '.hide-outdated', function (e) { e.preventDefault(); const id = $(this).data('comment'); $(this).addClass('hide'); @@ -1253,7 +1262,7 @@ function initPullRequestReview() { $(`#show-outdated-${id}`).removeClass('hide'); }); - $('button.comment-form-reply').on('click', function (e) { + $(document).on('click', 'button.comment-form-reply', function (e) { e.preventDefault(); $(this).hide(); const form = $(this).parent().find('.comment-form'); @@ -1284,7 +1293,7 @@ function initPullRequestReview() { $(this).closest('.menu').toggle('visible'); }); - $('.add-code-comment').on('click', function (e) { + $('a.add-code-comment').on('click', async function (e) { if ($(e.target).hasClass('btn-add-single')) return; // https://github.com/go-gitea/gitea/issues/4745 e.preventDefault(); @@ -1292,18 +1301,13 @@ function initPullRequestReview() { const side = $(this).data('side'); const idx = $(this).data('idx'); const path = $(this).data('path'); - const form = $('#pull_review_add_comment').html(); const tr = $(this).closest('tr'); - - const oldLineNum = tr.find('.lines-num-old').data('line-num'); - const newLineNum = tr.find('.lines-num-new').data('line-num'); - const addCommentKey = `${oldLineNum}|${newLineNum}`; - if (document.querySelector(`[data-add-comment-key="${addCommentKey}"]`)) return; // don't add same comment box twice + const lineType = tr.data('line-type'); let ntr = tr.next(); if (!ntr.hasClass('add-comment')) { ntr = $(` - <tr class="add-comment" data-add-comment-key="${addCommentKey}"> + <tr class="add-comment" data-line-type="${lineType}"> ${isSplit ? ` <td class="lines-num"></td> <td class="lines-type-marker"></td> @@ -1312,8 +1316,7 @@ function initPullRequestReview() { <td class="lines-type-marker"></td> <td class="add-comment-right"></td> ` : ` - <td class="lines-num"></td> - <td class="lines-num"></td> + <td colspan="2" class="lines-num"></td> <td class="add-comment-left add-comment-right" colspan="2"></td> `} </tr>`); @@ -1322,21 +1325,20 @@ function initPullRequestReview() { const td = ntr.find(`.add-comment-${side}`); let commentCloud = td.find('.comment-code-cloud'); - if (commentCloud.length === 0) { - td.html(form); + if (commentCloud.length === 0 && !ntr.find('button[name="is_review"]').length) { + const data = await $.get($(this).data('new-comment-url')); + td.html(data); commentCloud = td.find('.comment-code-cloud'); assingMenuAttributes(commentCloud.find('.menu')); - td.find("input[name='line']").val(idx); td.find("input[name='side']").val(side === 'left' ? 'previous' : 'proposed'); td.find("input[name='path']").val(path); + const $textarea = commentCloud.find('textarea'); + attachTribute($textarea.get(), {mentions: true, emoji: true}); + const $simplemde = setCommentSimpleMDE($textarea); + $textarea.focus(); + $simplemde.codemirror.focus(); } - const $textarea = commentCloud.find('textarea'); - attachTribute($textarea.get(), {mentions: true, emoji: true}); - - const $simplemde = setCommentSimpleMDE($textarea); - $textarea.focus(); - $simplemde.codemirror.focus(); }); } @@ -2497,17 +2499,24 @@ $(document).ready(async () => { $(e).trigger('click'); }); - $('.resolve-conversation').on('click', function (e) { + $(document).on('click', '.resolve-conversation', async function (e) { e.preventDefault(); - const id = $(this).data('comment-id'); + const comment_id = $(this).data('comment-id'); + const origin = $(this).data('origin'); const action = $(this).data('action'); const url = $(this).data('update-url'); - $.post(url, { - _csrf: csrf, - action, - comment_id: id, - }).then(reload); + const data = await $.post(url, {_csrf: csrf, origin, action, comment_id}); + + if ($(this).closest('.conversation-holder').length) { + const conversation = $(data); + $(this).closest('.conversation-holder').replaceWith(conversation); + conversation.find('.dropdown').dropdown(); + initReactionSelector(conversation); + initClipboard(); + } else { + reload(); + } }); buttonsClickOnEnter(); @@ -3626,6 +3635,28 @@ function initIssueList() { } }); } + +$(document).on('click', 'button[name="is_review"]', (e) => { + $(e.target).closest('form').append('<input type="hidden" name="is_review" value="true">'); +}); + +$(document).on('submit', '.conversation-holder form', async (e) => { + e.preventDefault(); + const form = $(e.target); + const newConversationHolder = $(await $.post(form.attr('action'), form.serialize())); + const {path, side, idx} = newConversationHolder.data(); + + form.closest('.conversation-holder').replaceWith(newConversationHolder); + if (form.closest('tr').data('line-type') === 'same') { + $(`a.add-code-comment[data-path="${path}"][data-idx="${idx}"]`).addClass('invisible'); + } else { + $(`a.add-code-comment[data-path="${path}"][data-side="${side}"][data-idx="${idx}"]`).addClass('invisible'); + } + newConversationHolder.find('.dropdown').dropdown(); + initReactionSelector(newConversationHolder); + initClipboard(); +}); + window.cancelCodeComment = function (btn) { const form = $(btn).closest('form'); if (form.length > 0 && form.hasClass('comment-form')) { @@ -3636,13 +3667,6 @@ window.cancelCodeComment = function (btn) { } }; -window.submitReply = function (btn) { - const form = $(btn).closest('form'); - if (form.length > 0 && form.hasClass('comment-form')) { - form.trigger('submit'); - } -}; - window.onOAuthLoginClick = function () { const oauthLoader = $('#oauth2-login-loader'); const oauthNav = $('#oauth2-login-navigator'); |