Skip to content

Commit 637788b

Browse files
committed
Reimplement delete comment for conversations
1 parent c55ca5d commit 637788b

File tree

11 files changed

+101
-25
lines changed

11 files changed

+101
-25
lines changed

models/conversations/conversation_update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ func DeleteConversationsByRepoID(ctx context.Context, repoID int64) (attachmentP
300300
return nil, err
301301
}
302302

303-
_, err = sess.In("conversation_id", conversationIDs).Delete(&Reaction{})
303+
_, err = sess.In("conversation_id", conversationIDs).Delete(&CommentReaction{})
304304
if err != nil {
305305
return nil, err
306306
}

models/conversations/reaction.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ func (err ErrReactionAlreadyExist) Unwrap() error {
5757
return util.ErrAlreadyExist
5858
}
5959

60-
// Reaction represents a reactions on conversations and comments.
61-
type Reaction struct {
60+
// CommentReaction represents a reactions on conversations and comments.
61+
type CommentReaction struct {
6262
ID int64 `xorm:"pk autoincr"`
6363
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
6464
ConversationID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
@@ -71,7 +71,7 @@ type Reaction struct {
7171
}
7272

7373
// LoadUser load user of reaction
74-
func (r *Reaction) LoadUser(ctx context.Context) (*user_model.User, error) {
74+
func (r *CommentReaction) LoadUser(ctx context.Context) (*user_model.User, error) {
7575
if r.User != nil {
7676
return r.User, nil
7777
}
@@ -84,24 +84,24 @@ func (r *Reaction) LoadUser(ctx context.Context) (*user_model.User, error) {
8484
}
8585

8686
// RemapExternalUser ExternalUserRemappable interface
87-
func (r *Reaction) RemapExternalUser(externalName string, externalID, userID int64) error {
87+
func (r *CommentReaction) RemapExternalUser(externalName string, externalID, userID int64) error {
8888
r.OriginalAuthor = externalName
8989
r.OriginalAuthorID = externalID
9090
r.UserID = userID
9191
return nil
9292
}
9393

9494
// GetUserID ExternalUserRemappable interface
95-
func (r *Reaction) GetUserID() int64 { return r.UserID }
95+
func (r *CommentReaction) GetUserID() int64 { return r.UserID }
9696

9797
// GetExternalName ExternalUserRemappable interface
98-
func (r *Reaction) GetExternalName() string { return r.OriginalAuthor }
98+
func (r *CommentReaction) GetExternalName() string { return r.OriginalAuthor }
9999

100100
// GetExternalID ExternalUserRemappable interface
101-
func (r *Reaction) GetExternalID() int64 { return r.OriginalAuthorID }
101+
func (r *CommentReaction) GetExternalID() int64 { return r.OriginalAuthorID }
102102

103103
func init() {
104-
db.RegisterModel(new(Reaction))
104+
db.RegisterModel(new(CommentReaction))
105105
}
106106

107107
// FindReactionsOptions describes the conditions to Find reactions
@@ -166,18 +166,18 @@ func FindReactions(ctx context.Context, opts FindReactionsOptions) (ReactionList
166166
if opts.Page != 0 {
167167
sess = db.SetSessionPagination(sess, &opts)
168168

169-
reactions := make([]*Reaction, 0, opts.PageSize)
169+
reactions := make([]*CommentReaction, 0, opts.PageSize)
170170
count, err := sess.FindAndCount(&reactions)
171171
return reactions, count, err
172172
}
173173

174-
reactions := make([]*Reaction, 0, 10)
174+
reactions := make([]*CommentReaction, 0, 10)
175175
count, err := sess.FindAndCount(&reactions)
176176
return reactions, count, err
177177
}
178178

179-
func createReaction(ctx context.Context, opts *ReactionOptions) (*Reaction, error) {
180-
reaction := &Reaction{
179+
func createReaction(ctx context.Context, opts *ReactionOptions) (*CommentReaction, error) {
180+
reaction := &CommentReaction{
181181
Type: opts.Type,
182182
UserID: opts.DoerID,
183183
ConversationID: opts.ConversationID,
@@ -218,7 +218,7 @@ type ReactionOptions struct {
218218
}
219219

220220
// CreateReaction creates reaction for conversation or comment.
221-
func CreateReaction(ctx context.Context, opts *ReactionOptions) (*Reaction, error) {
221+
func CreateReaction(ctx context.Context, opts *ReactionOptions) (*CommentReaction, error) {
222222
if !setting.UI.ReactionsLookup.Contains(opts.Type) {
223223
return nil, ErrForbiddenConversationReaction{opts.Type}
224224
}
@@ -242,7 +242,7 @@ func CreateReaction(ctx context.Context, opts *ReactionOptions) (*Reaction, erro
242242

243243
// DeleteReaction deletes reaction for conversation or comment.
244244
func DeleteReaction(ctx context.Context, opts *ReactionOptions) error {
245-
reaction := &Reaction{
245+
reaction := &CommentReaction{
246246
Type: opts.Type,
247247
UserID: opts.DoerID,
248248
ConversationID: opts.ConversationID,
@@ -280,7 +280,7 @@ func DeleteCommentReaction(ctx context.Context, doerID, conversationID, commentI
280280
}
281281

282282
// ReactionList represents list of reactions
283-
type ReactionList []*Reaction
283+
type ReactionList []*CommentReaction
284284

285285
// HasUser check if user has reacted
286286
func (list ReactionList) HasUser(userID int64) bool {
@@ -305,7 +305,7 @@ func (list ReactionList) GroupByType() map[string]ReactionList {
305305
}
306306

307307
func (list ReactionList) getUserIDs() []int64 {
308-
return container.FilterSlice(list, func(reaction *Reaction) (int64, bool) {
308+
return container.FilterSlice(list, func(reaction *CommentReaction) (int64, bool) {
309309
if reaction.OriginalAuthor != "" {
310310
return 0, false
311311
}

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,8 @@ pull.agit_documentation = Review documentation about AGit
19351935

19361936
comments.edit.already_changed = Unable to save changes to the comment. It appears the content has already been changed by another user. Please refresh the page and try editing again to avoid overwriting their changes
19371937

1938+
conversations.delete_comment_confirm = Are you sure you want to delete this comment?
1939+
19381940
milestones.new = New Milestone
19391941
milestones.closed = Closed %s
19401942
milestones.update_ago = Updated %s

routers/web/web.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,14 @@ func registerRoutes(m *web.Router) {
12811281
m.Group("/{index}", func() {
12821282
m.Combo("/comments").Post(repo.ConversationMustAllowUserComment, web.Bind(forms.CreateConversationCommentForm{}), repo.NewConversationComment)
12831283
}, context.RepoMustNotBeArchived())
1284+
1285+
m.Group("/comments/{id}", func() {
1286+
m.Post("", repo.UpdateConversationCommentContent)
1287+
m.Post("/delete", repo.DeleteConversationComment)
1288+
m.Post("/reactions/{action}", web.Bind(forms.ReactionForm{}), repo.ChangeConversationCommentReaction)
1289+
}, context.RepoMustNotBeArchived())
12841290
})
1291+
12851292
}, reqSignIn, context.RepoAssignment)
12861293

12871294
m.Group("/{username}/{reponame}", func() { // repo code

services/conversation/conversation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func deleteConversation(ctx context.Context, conversation *conversations_model.C
8686
&conversations_model.ConversationDependency{ConversationID: conversation.ID},
8787
&conversations_model.ConversationUser{ConversationID: conversation.ID},
8888
//&activities_model.Notification{ConversationID: conversation.ID},
89-
&conversations_model.Reaction{ConversationID: conversation.ID},
89+
&conversations_model.CommentReaction{ConversationID: conversation.ID},
9090
&repo_model.Attachment{ConversationID: conversation.ID},
9191
&conversations_model.Comment{ConversationID: conversation.ID},
9292
&conversations_model.ConversationDependency{DependencyID: conversation.ID},

services/conversation/reaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
// CreateCommentReaction creates a reaction on a comment.
14-
func CreateCommentReaction(ctx context.Context, doer *user_model.User, comment *conversations_model.Comment, content string) (*conversations_model.Reaction, error) {
14+
func CreateCommentReaction(ctx context.Context, doer *user_model.User, comment *conversations_model.Comment, content string) (*conversations_model.CommentReaction, error) {
1515
if err := comment.LoadConversation(ctx); err != nil {
1616
return nil, err
1717
}

templates/repo/commit_page.tmpl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,10 @@
280280
</div>
281281
{{end}}
282282
{{template "repo/diff/box" .}}
283-
{{template "repo/conversation/conversation" .}}
283+
284+
<div class="issue-content-left comment-list prevent-before-timeline">
285+
{{template "repo/conversation/conversation" .}}
286+
</div>
284287
</div>
285288
</div>
286289
{{template "base/footer" .}}

templates/repo/conversation/comments.tmpl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<!-- Provide Issue for any types other than type 0 -->
22
{{template "base/alert"}}
3+
{{$IsIssue:= .IsIssue}}
34
{{range .Comments}}
45
{{if call $.ShouldShowCommentType .Type}}
56
{{$createdStr:= TimeSinceUnix .CreatedUnix ctx.Locale}}
@@ -56,7 +57,7 @@
5657
{{if not $.Repository.IsArchived}}
5758
{{template "repo/issue/view_content/add_reaction" dict "ActionURL" (printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
5859
{{end}}
59-
{{template "repo/conversation/context_menu" dict "ctxData" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
60+
{{template "repo/conversation/context_menu" dict "ctxData" $ "item" . "delete" true "issue" $IsIssue "diff" false "IsIssue" $IsIssue "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
6061
</div>
6162
</div>
6263
<div class="ui attached segment comment-body" role="article">

templates/repo/conversation/context_menu.tmpl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{{if .issue}}
88
{{$referenceUrl = printf "%s#%s" .ctxData.Issue.Link .item.HashTag}}
99
{{else}}
10-
{{$referenceUrl = printf "%s/files#%s" .ctxData.Issue.Link .item.HashTag}}
10+
{{$referenceUrl = printf "%s/files#%s" .ctxData.Conversation.Link .item.HashTag}}
1111
{{end}}
1212
<div class="item context js-aria-clickable" data-clipboard-text-type="url" data-clipboard-text="{{$referenceUrl}}">{{ctx.Locale.Tr "repo.issues.context.copy_link"}}</div>
1313
{{if .ctxData.IsSigned}}
@@ -18,11 +18,15 @@
1818
{{if not ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled}}
1919
<div class="item context js-aria-clickable reference-issue" data-target="{{.item.HashTag}}-raw" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-poster-username="{{.item.Poster.Name}}" data-reference="{{$referenceUrl}}">{{ctx.Locale.Tr "repo.issues.context.reference_issue"}}</div>
2020
{{end}}
21-
{{if or .ctxData.Permission.IsAdmin .IsCommentPoster .ctxData.HasIssuesOrPullsWritePermission}}
21+
{{if or .ctxData.Permission.IsAdmin .IsCommentPoster .ctxData.HasIssuesOrPullsWritePermission .ctxData.HasConversationsWritePermission}}
2222
<div class="divider"></div>
2323
<div class="item context js-aria-clickable edit-content">{{ctx.Locale.Tr "repo.issues.context.edit"}}</div>
2424
{{if .delete}}
25-
<div class="item context js-aria-clickable delete-comment" data-comment-id={{.item.HashTag}} data-url="{{.ctxData.RepoLink}}/comments/{{.item.ID}}/delete" data-locale="{{ctx.Locale.Tr "repo.issues.delete_comment_confirm"}}">{{ctx.Locale.Tr "repo.issues.context.delete"}}</div>
25+
{{if .ctxData.IsIssue}}
26+
<div class="item context js-aria-clickable delete-comment" data-comment-id={{.item.HashTag}} data-url="{{.ctxData.RepoLink}}/comments/{{.item.ID}}/delete" data-locale="{{ctx.Locale.Tr "repo.issues.delete_comment_confirm"}}">{{ctx.Locale.Tr "repo.issues.context.delete"}}</div>
27+
{{else}}
28+
<div class="item context js-aria-clickable delete-comment" data-comment-id={{.item.HashTag}} data-url="{{.ctxData.RepoLink}}/conversations/comments/{{.item.ID}}/delete" data-locale="{{ctx.Locale.Tr "repo.conversations.delete_comment_confirm"}}">{{ctx.Locale.Tr "repo.conversations.context.delete"}}</div>
29+
{{end}}
2630
{{end}}
2731
{{end}}
2832
{{end}}

web_src/js/features/repo-commit.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {createTippy} from '../modules/tippy.ts';
22
import {toggleElem} from '../utils/dom.ts';
3+
import {GET, POST} from '../modules/fetch.ts';
34

45
export function initRepoEllipsisButton() {
56
for (const button of document.querySelectorAll('.js-toggle-commit-body')) {
@@ -25,3 +26,60 @@ export function initCommitStatuses() {
2526
});
2627
}
2728
}
29+
30+
export function initRepoConversationCommentDelete() {
31+
// Delete comment
32+
document.addEventListener('click', async (e) => {
33+
if (!e.target.matches('.delete-comment')) return;
34+
e.preventDefault();
35+
36+
const deleteButton = e.target;
37+
if (window.confirm(deleteButton.getAttribute('data-locale'))) {
38+
try {
39+
const response = await POST(deleteButton.getAttribute('data-url'));
40+
if (!response.ok) throw new Error('Failed to delete comment');
41+
42+
const conversationHolder = deleteButton.closest('.conversation-holder');
43+
const parentTimelineItem = deleteButton.closest('.timeline-item');
44+
const parentTimelineGroup = deleteButton.closest('.timeline-item-group');
45+
46+
// Check if this was a pending comment.
47+
if (conversationHolder?.querySelector('.pending-label')) {
48+
const counter = document.querySelector('#review-box .review-comments-counter');
49+
let num = parseInt(counter?.getAttribute('data-pending-comment-number')) - 1 || 0;
50+
num = Math.max(num, 0);
51+
counter.setAttribute('data-pending-comment-number', num);
52+
counter.textContent = String(num);
53+
}
54+
55+
document.querySelector(`#${deleteButton.getAttribute('data-comment-id')}`)?.remove();
56+
57+
if (conversationHolder && !conversationHolder.querySelector('.comment')) {
58+
const path = conversationHolder.getAttribute('data-path');
59+
const side = conversationHolder.getAttribute('data-side');
60+
const idx = conversationHolder.getAttribute('data-idx');
61+
const lineType = conversationHolder.closest('tr')?.getAttribute('data-line-type');
62+
63+
// the conversation holder could appear either on the "Conversation" page, or the "Files Changed" page
64+
// on the Conversation page, there is no parent "tr", so no need to do anything for "add-code-comment"
65+
if (lineType) {
66+
if (lineType === 'same') {
67+
document.querySelector(`[data-path="${path}"] .add-code-comment[data-idx="${idx}"]`).classList.remove('tw-invisible');
68+
} else {
69+
document.querySelector(`[data-path="${path}"] .add-code-comment[data-side="${side}"][data-idx="${idx}"]`).classList.remove('tw-invisible');
70+
}
71+
}
72+
conversationHolder.remove();
73+
}
74+
75+
// Check if there is no review content, move the time avatar upward to avoid overlapping the content below.
76+
if (!parentTimelineGroup?.querySelector('.timeline-item.comment') && !parentTimelineItem?.querySelector('.conversation-holder')) {
77+
const timelineAvatar = parentTimelineGroup?.querySelector('.timeline-avatar');
78+
timelineAvatar?.classList.remove('timeline-avatar-offset');
79+
}
80+
} catch (error) {
81+
console.error(error);
82+
}
83+
}
84+
});
85+
}

0 commit comments

Comments
 (0)