* Add a way to mark Conversation (code comment) resolved mark Conversation is a way to mark a Conversation is stale or be solved. when it's marked as stale, will be hided like stale. all Pull Request writer , Offical Reviewers and poster can add or remove Conversation resolved mark. Signed-off-by: a1012112796 <1012112796@qq.com> * fix lint * Apply suggestions from code review * Add ResolveDoer * fix ui Co-Authored-By: Lauris BH <lauris@nix.lv> Co-Authored-By: 6543 <6543@obermui.de> * change IsResolved to an function Add permission check in UpdateResolveConversation * Apply suggestions from code review * change return error for permisson check * add default message for deleted user * get issue message from comment * add migration for ``ResolveDoerID`` column another change: * block mark pending review as resolved because it's not necessary Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> * change button color * resolve button size * fix code style * remove unusefull code Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>tags/v1.21.12.1
| @@ -122,6 +122,8 @@ type Comment struct { | |||
| AssigneeID int64 | |||
| RemovedAssignee bool | |||
| Assignee *User `xorm:"-"` | |||
| ResolveDoerID int64 | |||
| ResolveDoer *User `xorm:"-"` | |||
| OldTitle string | |||
| NewTitle string | |||
| OldRef string | |||
| @@ -420,6 +422,26 @@ func (c *Comment) LoadAssigneeUser() error { | |||
| return nil | |||
| } | |||
| // LoadResolveDoer if comment.Type is CommentTypeCode and ResolveDoerID not zero, then load resolveDoer | |||
| func (c *Comment) LoadResolveDoer() (err error) { | |||
| if c.ResolveDoerID == 0 || c.Type != CommentTypeCode { | |||
| return nil | |||
| } | |||
| c.ResolveDoer, err = getUserByID(x, c.ResolveDoerID) | |||
| if err != nil { | |||
| if IsErrUserNotExist(err) { | |||
| c.ResolveDoer = NewGhostUser() | |||
| err = nil | |||
| } | |||
| } | |||
| return | |||
| } | |||
| // IsResolved check if an code comment is resolved | |||
| func (c *Comment) IsResolved() bool { | |||
| return c.ResolveDoerID != 0 && c.Type == CommentTypeCode | |||
| } | |||
| // LoadDepIssueDetails loads Dependent Issue Details | |||
| func (c *Comment) LoadDepIssueDetails() (err error) { | |||
| if c.DependentIssueID <= 0 || c.DependentIssue != nil { | |||
| @@ -943,7 +965,12 @@ func fetchCodeCommentsByReview(e Engine, issue *Issue, currentUser *User, review | |||
| if err := e.In("id", ids).Find(&reviews); err != nil { | |||
| return nil, err | |||
| } | |||
| for _, comment := range comments { | |||
| if err := comment.LoadResolveDoer(); err != nil { | |||
| 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 { | |||
| @@ -208,6 +208,8 @@ var migrations = []Migration{ | |||
| NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", addCommitDivergenceToPulls), | |||
| // v137 -> v138 | |||
| NewMigration("Add Branch Protection Block Outdated Branch", addBlockOnOutdatedBranch), | |||
| // v138 -> v139 | |||
| NewMigration("Add ResolveDoerID to Comment table", addResolveDoerIDCommentColumn), | |||
| } | |||
| // GetCurrentDBVersion returns the current db version | |||
| @@ -0,0 +1,22 @@ | |||
| // Copyright 2020 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package migrations | |||
| import ( | |||
| "fmt" | |||
| "xorm.io/xorm" | |||
| ) | |||
| func addResolveDoerIDCommentColumn(x *xorm.Engine) error { | |||
| type Comment struct { | |||
| ResolveDoerID int64 | |||
| } | |||
| if err := x.Sync2(new(Comment)); err != nil { | |||
| return fmt.Errorf("Sync2: %v", err) | |||
| } | |||
| return nil | |||
| } | |||
| @@ -5,6 +5,7 @@ | |||
| package models | |||
| import ( | |||
| "fmt" | |||
| "strings" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| @@ -594,3 +595,62 @@ func RemoveRewiewRequest(issue *Issue, reviewer *User, doer *User) (comment *Com | |||
| return comment, sess.Commit() | |||
| } | |||
| // MarkConversation Add or remove Conversation mark for a code comment | |||
| func MarkConversation(comment *Comment, doer *User, isResolve bool) (err error) { | |||
| if comment.Type != CommentTypeCode { | |||
| return nil | |||
| } | |||
| if isResolve { | |||
| if comment.ResolveDoerID != 0 { | |||
| return nil | |||
| } | |||
| if _, err = x.Exec("UPDATE `comment` SET resolve_doer_id=? WHERE id=?", doer.ID, comment.ID); err != nil { | |||
| return err | |||
| } | |||
| } else { | |||
| if comment.ResolveDoerID == 0 { | |||
| return nil | |||
| } | |||
| if _, err = x.Exec("UPDATE `comment` SET resolve_doer_id=? WHERE id=?", 0, comment.ID); err != nil { | |||
| return err | |||
| } | |||
| } | |||
| return nil | |||
| } | |||
| // CanMarkConversation Add or remove Conversation mark for a code comment permission check | |||
| // the PR writer , offfcial reviewer and poster can do it | |||
| func CanMarkConversation(issue *Issue, doer *User) (permResult bool, err error) { | |||
| if doer == nil || issue == nil { | |||
| return false, fmt.Errorf("issue or doer is nil") | |||
| } | |||
| if doer.ID != issue.PosterID { | |||
| if err = issue.LoadRepo(); err != nil { | |||
| return false, err | |||
| } | |||
| perm, err := GetUserRepoPermission(issue.Repo, doer) | |||
| if err != nil { | |||
| return false, err | |||
| } | |||
| permResult = perm.CanAccess(AccessModeWrite, UnitTypePullRequests) | |||
| if !permResult { | |||
| if permResult, err = IsOfficialReviewer(issue, doer); err != nil { | |||
| return false, err | |||
| } | |||
| } | |||
| if !permResult { | |||
| return false, nil | |||
| } | |||
| } | |||
| return true, nil | |||
| } | |||
| @@ -1067,6 +1067,11 @@ issues.review.review = Review | |||
| issues.review.reviewers = Reviewers | |||
| issues.review.show_outdated = Show outdated | |||
| issues.review.hide_outdated = Hide outdated | |||
| issues.review.show_resolved = Show resolved | |||
| issues.review.hide_resolved = Hide resolved | |||
| issues.review.resolve_conversation = Resolve conversation | |||
| issues.review.un_resolve_conversation = Unresolve conversation | |||
| issues.review.resolved_by = marked this conversation as resolved | |||
| issues.assignee.error = Not all assignees was added due to an unexpected error. | |||
| pulls.desc = Enable pull requests and code reviews. | |||
| @@ -990,6 +990,11 @@ func ViewIssue(ctx *context.Context) { | |||
| ctx.ServerError("Review.LoadCodeComments", err) | |||
| return | |||
| } | |||
| if err = comment.LoadResolveDoer(); err != nil { | |||
| ctx.ServerError("LoadResolveDoer", err) | |||
| return | |||
| } | |||
| } | |||
| } | |||
| @@ -1033,6 +1038,11 @@ func ViewIssue(ctx *context.Context) { | |||
| ctx.ServerError("IsUserAllowedToMerge", err) | |||
| return | |||
| } | |||
| if ctx.Data["CanMarkConversation"], err = models.CanMarkConversation(issue, ctx.User); err != nil { | |||
| ctx.ServerError("CanMarkConversation", err) | |||
| return | |||
| } | |||
| } | |||
| prUnit, err := repo.GetUnit(models.UnitTypePullRequests) | |||
| @@ -624,6 +624,13 @@ func ViewPullFiles(ctx *context.Context) { | |||
| return | |||
| } | |||
| if ctx.IsSigned && ctx.User != nil { | |||
| if ctx.Data["CanMarkConversation"], err = models.CanMarkConversation(issue, ctx.User); err != nil { | |||
| ctx.ServerError("CanMarkConversation", err) | |||
| return | |||
| } | |||
| } | |||
| setImageCompareContext(ctx, baseCommit, commit) | |||
| setPathsCompareContext(ctx, baseCommit, commit, headTarget) | |||
| @@ -61,6 +61,53 @@ func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) { | |||
| ctx.Redirect(comment.HTMLURL()) | |||
| } | |||
| // UpdateResolveConversation add or remove an Conversation resolved mark | |||
| func UpdateResolveConversation(ctx *context.Context) { | |||
| action := ctx.Query("action") | |||
| commentID := ctx.QueryInt64("comment_id") | |||
| comment, err := models.GetCommentByID(commentID) | |||
| if err != nil { | |||
| ctx.ServerError("GetIssueByID", err) | |||
| return | |||
| } | |||
| if err = comment.LoadIssue(); err != nil { | |||
| ctx.ServerError("comment.LoadIssue", err) | |||
| return | |||
| } | |||
| var permResult bool | |||
| if permResult, err = models.CanMarkConversation(comment.Issue, ctx.User); err != nil { | |||
| ctx.ServerError("CanMarkConversation", err) | |||
| return | |||
| } | |||
| if !permResult { | |||
| ctx.Error(403) | |||
| return | |||
| } | |||
| if !comment.Issue.IsPull { | |||
| ctx.Error(400) | |||
| return | |||
| } | |||
| if action == "Resolve" || action == "UnResolve" { | |||
| err = models.MarkConversation(comment, ctx.User, action == "Resolve") | |||
| if err != nil { | |||
| ctx.ServerError("MarkConversation", err) | |||
| return | |||
| } | |||
| } else { | |||
| ctx.Error(400) | |||
| return | |||
| } | |||
| ctx.JSON(200, map[string]interface{}{ | |||
| "ok": true, | |||
| }) | |||
| } | |||
| // 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) | |||
| @@ -739,6 +739,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/assignee", reqRepoIssuesOrPullsWriter, repo.UpdateIssueAssignee) | |||
| m.Post("/request_review", reqRepoIssuesOrPullsReader, repo.UpdatePullReviewRequest) | |||
| m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus) | |||
| m.Post("/resolve_conversation", reqRepoIssuesOrPullsReader, repo.UpdateResolveConversation) | |||
| }, context.RepoMustNotBeArchived()) | |||
| m.Group("/comments/:id", func() { | |||
| m.Post("", repo.UpdateCommentContent) | |||
| @@ -147,32 +147,79 @@ | |||
| {{end}} | |||
| </tr> | |||
| {{if gt (len $line.Comments) 0}} | |||
| {{$resolved := (index $line.Comments 0).IsResolved}} | |||
| {{$resolveDoer := (index $line.Comments 0).ResolveDoer}} | |||
| {{$isNotPending := (not (eq (index $line.Comments 0).Review.Type 0))}} | |||
| <tr class="add-code-comment"> | |||
| <td class="lines-num"></td> | |||
| <td class="lines-type-marker"></td> | |||
| <td class="add-comment-left"> | |||
| {{if and $resolved (eq $line.GetCommentSide "previous")}} | |||
| <div class="ui top attached header"> | |||
| <span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span> | |||
| <button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated"> | |||
| {{svg "octicon-unfold" 16}} | |||
| {{$.i18n.Tr "repo.issues.review.show_resolved"}} | |||
| </button> | |||
| <button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated"> | |||
| {{svg "octicon-fold" 16}} | |||
| {{$.i18n.Tr "repo.issues.review.hide_resolved"}} | |||
| </button> | |||
| </div> | |||
| {{end}} | |||
| {{if eq $line.GetCommentSide "previous"}} | |||
| <div class="field comment-code-cloud"> | |||
| <div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}"> | |||
| <div class="comment-list"> | |||
| <ui class="ui comments"> | |||
| {{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}} | |||
| </ui> | |||
| </div> | |||
| {{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.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 $line.Comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" > | |||
| {{if $resolved}} | |||
| {{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "repo.issues.review.resolve_conversation"}} | |||
| {{end}} | |||
| </button> | |||
| {{end}} | |||
| </div> | |||
| {{end}} | |||
| </td> | |||
| <td class="lines-num"></td> | |||
| <td class="lines-type-marker"></td> | |||
| <td class="add-comment-right"> | |||
| {{if and $resolved (eq $line.GetCommentSide "proposed")}} | |||
| <div class="ui top attached header"> | |||
| <span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span> | |||
| <button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated"> | |||
| {{svg "octicon-unfold" 16}} | |||
| {{$.i18n.Tr "repo.issues.review.show_resolved"}} | |||
| </button> | |||
| <button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated"> | |||
| {{svg "octicon-fold" 16}} | |||
| {{$.i18n.Tr "repo.issues.review.hide_resolved"}} | |||
| </button> | |||
| </div> | |||
| {{end}} | |||
| {{if eq $line.GetCommentSide "proposed"}} | |||
| <div class="field comment-code-cloud"> | |||
| <div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}"> | |||
| <div class="comment-list"> | |||
| <ui class="ui comments"> | |||
| {{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}} | |||
| </ui> | |||
| </div> | |||
| {{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.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 $line.Comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" > | |||
| {{if $resolved}} | |||
| {{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "repo.issues.review.resolve_conversation"}} | |||
| {{end}} | |||
| </button> | |||
| {{end}} | |||
| </div> | |||
| {{end}} | |||
| </td> | |||
| @@ -23,17 +23,42 @@ | |||
| <td class="lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{if and $.root.SignedUserID $line.CanComment $.root.PageIsPullFiles}}<a class="ui green 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}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</span></td> | |||
| </tr> | |||
| {{if gt (len $line.Comments) 0}} | |||
| {{$resolved := (index $line.Comments 0).IsResolved}} | |||
| {{$resolveDoer := (index $line.Comments 0).ResolveDoer}} | |||
| {{$isNotPending := (not (eq (index $line.Comments 0).Review.Type 0))}} | |||
| <tr> | |||
| <td colspan="2" class="lines-num"></td> | |||
| <td class="lines-type-marker"></td> | |||
| <td class="add-comment-left add-comment-right"> | |||
| <div class="field comment-code-cloud"> | |||
| {{if $resolved}} | |||
| <div class = "ui attached header"> | |||
| <span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.root.i18n.Tr "repo.issues.review.resolved_by"}}</span> | |||
| <button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated"> | |||
| {{svg "octicon-unfold" 16}} | |||
| {{$.root.i18n.Tr "repo.issues.review.show_resolved"}} | |||
| </button> | |||
| <button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated"> | |||
| {{svg "octicon-fold" 16}} | |||
| {{$.root.i18n.Tr "repo.issues.review.hide_resolved"}} | |||
| </button> | |||
| </div> | |||
| {{end}} | |||
| <div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}"> | |||
| <div class="comment-list"> | |||
| <ui class="ui comments"> | |||
| {{ template "repo/diff/comments" dict "root" $.root "comments" $line.Comments}} | |||
| </ui> | |||
| </div> | |||
| {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $line.Comments 0).ReviewID "root" $.root "comment" (index $line.Comments 0)}} | |||
| {{if and $.root.CanMarkConversation $isNotPending}} | |||
| <button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.root.RepoLink}}/issues/resolve_conversation" > | |||
| {{if $resolved}} | |||
| {{$.root.i18n.Tr "repo.issues.review.un_resolve_conversation"}} | |||
| {{else}} | |||
| {{$.root.i18n.Tr "repo.issues.review.resolve_conversation"}} | |||
| {{end}} | |||
| </button> | |||
| {{end}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -381,6 +381,7 @@ | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| {{if .Review.CodeComments}} | |||
| <div class="timeline-item event"> | |||
| {{ range $filename, $lines := .Review.CodeComments}} | |||
| @@ -388,14 +389,25 @@ | |||
| <div class="ui segments"> | |||
| <div class="ui segment"> | |||
| {{$invalid := (index $comms 0).Invalidated}} | |||
| {{if $invalid}} | |||
| {{$resolved := (index $comms 0).IsResolved}} | |||
| {{$resolveDoer := (index $comms 0).ResolveDoer}} | |||
| {{$isNotPending := (not (eq (index $comms 0).Review.Type 0))}} | |||
| {{if or $invalid $resolved}} | |||
| <button id="show-outdated-{{(index $comms 0).ID}}" data-comment="{{(index $comms 0).ID}}" class="ui compact right labeled button show-outdated"> | |||
| {{svg "octicon-fold" 16}} | |||
| {{$.i18n.Tr "repo.issues.review.show_outdated"}} | |||
| {{svg "octicon-unfold" 16}} | |||
| {{if $invalid }} | |||
| {{$.i18n.Tr "repo.issues.review.show_outdated"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "repo.issues.review.show_resolved"}} | |||
| {{end}} | |||
| </button> | |||
| <button id="hide-outdated-{{(index $comms 0).ID}}" data-comment="{{(index $comms 0).ID}}" class="hide ui compact right labeled button hide-outdated"> | |||
| {{svg "octicon-fold" 16}} | |||
| {{$.i18n.Tr "repo.issues.review.hide_outdated"}} | |||
| {{if $invalid}} | |||
| {{$.i18n.Tr "repo.issues.review.hide_outdated"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "repo.issues.review.hide_resolved"}} | |||
| {{end}} | |||
| </button> | |||
| {{end}} | |||
| <a href="{{(index $comms 0).CodeCommentURL}}" class="file-comment">{{$filename}}</a> | |||
| @@ -403,7 +415,7 @@ | |||
| {{$diff := (CommentMustAsDiff (index $comms 0))}} | |||
| {{if $diff}} | |||
| {{$file := (index $diff.Files 0)}} | |||
| <div id="code-preview-{{(index $comms 0).ID}}" class="ui table segment{{if $invalid}} hide{{end}}"> | |||
| <div id="code-preview-{{(index $comms 0).ID}}" class="ui table segment{{if or $invalid $resolved}} hide{{end}}"> | |||
| <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"> | |||
| <table> | |||
| @@ -415,7 +427,7 @@ | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| <div id="code-comments-{{(index $comms 0).ID}}" class="ui segment{{if $invalid}} hide{{end}}"> | |||
| <div id="code-comments-{{(index $comms 0).ID}}" class="ui segment{{if or $invalid $resolved}} hide{{end}}"> | |||
| <div class="ui comments"> | |||
| {{range $comms}} | |||
| {{ $createdSubStr:= TimeSinceUnix .CreatedUnix $.Lang }} | |||
| @@ -445,6 +457,20 @@ | |||
| {{end}} | |||
| </div> | |||
| {{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" > | |||
| {{if $resolved}} | |||
| {{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "repo.issues.review.resolve_conversation"}} | |||
| {{end}} | |||
| </button> | |||
| {{end}} | |||
| {{if $resolved}} | |||
| <span class="ui grey text"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| @@ -2566,6 +2566,19 @@ $(document).ready(async () => { | |||
| $(e).click(); | |||
| }); | |||
| $('.resolve-conversation').on('click', function (e) { | |||
| e.preventDefault(); | |||
| const id = $(this).data('comment-id'); | |||
| const action = $(this).data('action'); | |||
| const url = $(this).data('update-url'); | |||
| $.post(url, { | |||
| _csrf: csrf, | |||
| action, | |||
| comment_id: id, | |||
| }).then(reload); | |||
| }); | |||
| buttonsClickOnEnter(); | |||
| searchUsers(); | |||
| searchTeams(); | |||