Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 0bf5d88

Browse files
authored
Merge pull request #1701 from github/features/inline-comment-edit-and-delete
Adding Edit/Delete functions to inline comments
2 parents ad526b1 + 9aa2922 commit 0bf5d88

23 files changed

+519
-29
lines changed

src/GitHub.App/Api/ApiClient.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ public IObservable<PullRequestReviewComment> CreatePullRequestReviewComment(
110110
return gitHubClient.PullRequest.ReviewComment.CreateReply(owner, name, number, comment);
111111
}
112112

113+
public IObservable<PullRequestReviewComment> EditPullRequestReviewComment(
114+
string owner,
115+
string name,
116+
int number,
117+
string body)
118+
{
119+
var pullRequestReviewCommentEdit = new PullRequestReviewCommentEdit(body);
120+
return gitHubClient.PullRequest.ReviewComment.Edit(owner, name, number, pullRequestReviewCommentEdit);
121+
}
122+
123+
public IObservable<Unit> DeletePullRequestReviewComment(
124+
string owner,
125+
string name,
126+
int number)
127+
{
128+
return gitHubClient.PullRequest.ReviewComment.Delete(owner, name, number);
129+
}
130+
113131
public IObservable<Gist> CreateGist(NewGist newGist)
114132
{
115133
return gitHubClient.Gist.Create(newGist);

src/GitHub.Exports.Reactive/Api/IApiClient.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,30 @@ IObservable<PullRequestReviewComment> CreatePullRequestReviewComment(
9090
/// <returns></returns>
9191
IObservable<PullRequestReviewComment> CreatePullRequestReviewComment(string owner, string name, int number, string body, int inReplyTo);
9292

93+
/// <summary>
94+
/// Delete a PR review comment.
95+
/// </summary>
96+
/// <param name="owner">The repository owner.</param>
97+
/// <param name="name">The repository name.</param>
98+
/// <param name="number">The pull request comment number.</param>
99+
IObservable<Unit> DeletePullRequestReviewComment(
100+
string owner,
101+
string name,
102+
int number);
103+
104+
/// <summary>
105+
/// Edits a PR review comment.
106+
/// </summary>
107+
/// <param name="owner">The repository owner.</param>
108+
/// <param name="name">The repository name.</param>
109+
/// <param name="number">The pull request comment number.</param>
110+
/// <param name="body">The replacement comment body.</param>
111+
IObservable<PullRequestReviewComment> EditPullRequestReviewComment(
112+
string owner,
113+
string name,
114+
int number,
115+
string body);
116+
93117
IObservable<Branch> GetBranches(string owner, string repo);
94118
IObservable<Repository> GetRepositories();
95119
IObservable<Repository> GetRepository(string owner, string repo);

src/GitHub.Exports.Reactive/Services/IPullRequestSession.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Task<IPullRequestReviewCommentModel> PostReviewComment(
111111
/// <param name="body">The comment body.</param>
112112
/// <param name="inReplyTo">The REST ID of the comment to reply to.</param>
113113
/// <param name="inReplyToNodeId">The GraphQL ID of the comment to reply to.</param>
114-
/// <returns></returns>
114+
/// <returns>A comment model.</returns>
115115
Task<IPullRequestReviewCommentModel> PostReviewComment(
116116
string body,
117117
int inReplyTo,
@@ -134,7 +134,7 @@ Task<IPullRequestReviewCommentModel> PostReviewComment(
134134
/// Posts the currently pending review.
135135
/// </summary>
136136
/// <param name="body">The review body.</param>
137-
/// <param name="state">The review event.</param>
137+
/// <param name="e">The review event.</param>
138138
/// <returns>The review model.</returns>
139139
Task<IPullRequestReviewModel> PostReview(string body, PullRequestReviewEvent e);
140140

@@ -145,5 +145,20 @@ Task<IPullRequestReviewCommentModel> PostReviewComment(
145145
/// <param name="pullRequest">The new pull request model.</param>
146146
/// <returns>A task which completes when the session has completed updating.</returns>
147147
Task Update(IPullRequestModel pullRequest);
148+
149+
/// <summary>
150+
/// Deletes a pull request comment.
151+
/// </summary>
152+
/// <param name="number">The number of the pull request comment to delete</param>
153+
/// <returns>A task which completes when the session has completed updating.</returns>
154+
Task DeleteComment(int number);
155+
156+
/// <summary>
157+
/// Edit a PR review comment reply.
158+
/// </summary>
159+
/// <param name="commentNodeId">The node id of the pull request comment</param>
160+
/// <param name="body">The replacement comment body.</param>
161+
/// <returns>A comment model.</returns>
162+
Task<IPullRequestReviewCommentModel> EditComment(string commentNodeId, string body);
148163
}
149164
}

src/GitHub.Exports/Models/UsageModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public class MeasuresModel
6464
public int NumberOfPRDetailsOpenFileInSolution { get; set; }
6565
public int NumberOfPRReviewDiffViewInlineCommentOpen { get; set; }
6666
public int NumberOfPRReviewDiffViewInlineCommentPost { get; set; }
67+
public int NumberOfPRReviewDiffViewInlineCommentDelete { get; set; }
68+
public int NumberOfPRReviewDiffViewInlineCommentEdit { get; set; }
6769
public int NumberOfPRReviewDiffViewInlineCommentStartReview { get; set; }
6870
public int NumberOfPRReviewPosts { get; set; }
6971
public int NumberOfShowCurrentPullRequest { get; set; }

src/GitHub.InlineReviews/SampleData/CommentThreadViewModelDesigner.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class CommentThreadViewModelDesigner : ICommentThreadViewModel
1818
= new AccountDesigner { Login = "shana", IsUser = true };
1919

2020
public ReactiveCommand<ICommentModel> PostComment { get; }
21+
public ReactiveCommand<ICommentModel> EditComment { get; }
22+
public ReactiveCommand<object> DeleteComment { get; }
2123

2224
public Uri GetCommentUrl(int id)
2325
{

src/GitHub.InlineReviews/SampleData/CommentViewModelDesigner.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public CommentViewModelDesigner()
2424
public CommentEditState EditState { get; set; }
2525
public bool IsReadOnly { get; set; }
2626
public bool IsSubmitting { get; set; }
27+
public bool CanDelete { get; } = true;
2728
public ICommentThreadViewModel Thread { get; }
2829
public DateTimeOffset UpdatedAt => DateTime.Now.Subtract(TimeSpan.FromDays(3));
2930
public IAccount User { get; set; }
@@ -32,5 +33,6 @@ public CommentViewModelDesigner()
3233
public ReactiveCommand<object> CancelEdit { get; }
3334
public ReactiveCommand<Unit> CommitEdit { get; }
3435
public ReactiveCommand<object> OpenOnGitHub { get; }
36+
public ReactiveCommand<Unit> Delete { get; }
3537
}
3638
}

src/GitHub.InlineReviews/Services/IPullRequestSessionService.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ Task<bool> IsUnmodifiedAndPushed(
9090
/// Extracts a file at a specified commit from the repository.
9191
/// </summary>
9292
/// <param name="repository">The repository.</param>
93-
/// <param name="commitSha">The SHA of the commit.</param>
93+
/// <param name="pullRequestNumber">The pull request number</param>
94+
/// <param name="sha">The SHA of the commit.</param>
9495
/// <param name="relativePath">The path to the file, relative to the repository.</param>
9596
/// <returns>
9697
/// The contents of the file, or null if the file was not found at the specified commit.
@@ -146,7 +147,7 @@ Task<byte[]> ExtractFileFromGit(
146147
/// <summary>
147148
/// Gets the GraphQL ID for a pull request.
148149
/// </summary>
149-
/// <param name="repository">The local repository.</param>
150+
/// <param name="localRepository">The local repository.</param>
150151
/// <param name="repositoryOwner">The owner of the remote fork.</param>
151152
/// <param name="number">The pull request number.</param>
152153
/// <returns></returns>
@@ -184,6 +185,7 @@ Task<IPullRequestReviewModel> CreatePendingReview(
184185
/// <summary>
185186
/// Cancels a pending review on the server.
186187
/// </summary>
188+
/// <param name="localRepository">The local repository.</param>
187189
/// <param name="reviewId">The GraphQL ID of the review.</param>
188190
Task CancelPendingReview(
189191
ILocalRepositoryModel localRepository,
@@ -290,12 +292,41 @@ Task<IPullRequestReviewCommentModel> PostStandaloneReviewComment(
290292
/// <param name="body">The comment body.</param>
291293
/// <param name="inReplyTo">The comment ID to reply to.</param>
292294
/// <returns>A model representing the posted comment.</returns>
293-
Task<IPullRequestReviewCommentModel> PostStandaloneReviewCommentRepy(
295+
Task<IPullRequestReviewCommentModel> PostStandaloneReviewCommentReply(
294296
ILocalRepositoryModel localRepository,
295297
string remoteRepositoryOwner,
296298
IAccount user,
297299
int number,
298300
string body,
299301
int inReplyTo);
302+
303+
/// <summary>
304+
/// Delete a PR review comment.
305+
/// </summary>
306+
/// <param name="localRepository">The local repository.</param>
307+
/// <param name="remoteRepositoryOwner">The owner of the repository fork to delete from.</param>
308+
/// <param name="user">The user deleting the comment.</param>
309+
/// <param name="number">The pull request comment number.</param>
310+
/// <returns></returns>
311+
Task DeleteComment(
312+
ILocalRepositoryModel localRepository,
313+
string remoteRepositoryOwner,
314+
IAccount user,
315+
int number);
316+
317+
/// <summary>
318+
/// Edit a PR review comment.
319+
/// </summary>
320+
/// <param name="localRepository">The local repository.</param>
321+
/// <param name="remoteRepositoryOwner">The owner of the repository fork to delete from.</param>
322+
/// <param name="user">The user deleting the comment.</param>
323+
/// <param name="commentNodeId">The pull request comment node id.</param>
324+
/// <param name="body">The replacement comment body.</param>
325+
/// <returns>A model representing the edited comment.</returns>
326+
Task<PullRequestReviewCommentModel> EditComment(ILocalRepositoryModel localRepository,
327+
string remoteRepositoryOwner,
328+
IAccount user,
329+
string commentNodeId,
330+
string body);
300331
}
301332
}

src/GitHub.InlineReviews/Services/PullRequestSession.cs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,33 @@ public async Task<IPullRequestReviewCommentModel> PostReviewComment(
164164
return model;
165165
}
166166

167+
/// <inheritdoc/>
168+
public async Task DeleteComment(
169+
int number)
170+
{
171+
await service.DeleteComment(
172+
LocalRepository,
173+
RepositoryOwner,
174+
User,
175+
number);
176+
177+
await RemoveComment(number);
178+
}
179+
180+
/// <inheritdoc/>
181+
public async Task<IPullRequestReviewCommentModel> EditComment(string commentNodeId, string body)
182+
{
183+
var model = await service.EditComment(
184+
LocalRepository,
185+
RepositoryOwner,
186+
User,
187+
commentNodeId,
188+
body);
189+
190+
await ReplaceComment(model);
191+
return model;
192+
}
193+
167194
/// <inheritdoc/>
168195
public async Task<IPullRequestReviewCommentModel> PostReviewComment(
169196
string body,
@@ -174,7 +201,7 @@ public async Task<IPullRequestReviewCommentModel> PostReviewComment(
174201

175202
if (!HasPendingReview)
176203
{
177-
model = await service.PostStandaloneReviewCommentRepy(
204+
model = await service.PostStandaloneReviewCommentReply(
178205
LocalRepository,
179206
RepositoryOwner,
180207
User,
@@ -286,6 +313,24 @@ async Task AddComment(IPullRequestReviewCommentModel comment)
286313
await Update(PullRequest);
287314
}
288315

316+
async Task ReplaceComment(IPullRequestReviewCommentModel comment)
317+
{
318+
PullRequest.ReviewComments = PullRequest.ReviewComments
319+
.Select(model => model.Id == comment.Id ? comment: model)
320+
.ToList();
321+
322+
await Update(PullRequest);
323+
}
324+
325+
async Task RemoveComment(int commentId)
326+
{
327+
PullRequest.ReviewComments = PullRequest.ReviewComments
328+
.Where(model => model.Id != commentId)
329+
.ToList();
330+
331+
await Update(PullRequest);
332+
}
333+
289334
async Task AddReview(IPullRequestReviewModel review)
290335
{
291336
PullRequest.Reviews = PullRequest.Reviews

src/GitHub.InlineReviews/Services/PullRequestSessionService.cs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Microsoft.VisualStudio.Text;
1919
using Microsoft.VisualStudio.Text.Projection;
2020
using Octokit.GraphQL;
21+
using Octokit.GraphQL.Core;
2122
using Octokit.GraphQL.Model;
2223
using ReactiveUI;
2324
using Serilog;
@@ -565,7 +566,7 @@ public async Task<IPullRequestReviewCommentModel> PostStandaloneReviewComment(
565566
}
566567

567568
/// <inheritdoc/>
568-
public async Task<IPullRequestReviewCommentModel> PostStandaloneReviewCommentRepy(
569+
public async Task<IPullRequestReviewCommentModel> PostStandaloneReviewCommentReply(
569570
ILocalRepositoryModel localRepository,
570571
string remoteRepositoryOwner,
571572
IAccount user,
@@ -600,6 +601,63 @@ public async Task<IPullRequestReviewCommentModel> PostStandaloneReviewCommentRep
600601
};
601602
}
602603

604+
/// <inheritdoc/>
605+
public async Task DeleteComment(
606+
ILocalRepositoryModel localRepository,
607+
string remoteRepositoryOwner,
608+
IAccount user,
609+
int number)
610+
{
611+
var address = HostAddress.Create(localRepository.CloneUrl.Host);
612+
var apiClient = await apiClientFactory.Create(address);
613+
614+
await apiClient.DeletePullRequestReviewComment(
615+
remoteRepositoryOwner,
616+
localRepository.Name,
617+
number);
618+
619+
await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentDelete);
620+
}
621+
622+
/// <inheritdoc/>
623+
public async Task<PullRequestReviewCommentModel> EditComment(ILocalRepositoryModel localRepository,
624+
string remoteRepositoryOwner,
625+
IAccount user,
626+
string commentNodeId,
627+
string body)
628+
{
629+
var address = HostAddress.Create(localRepository.CloneUrl.Host);
630+
var graphql = await graphqlFactory.CreateConnection(address);
631+
632+
var updatePullRequestReviewCommentInput = new UpdatePullRequestReviewCommentInput
633+
{
634+
Body = body,
635+
PullRequestReviewCommentId = commentNodeId
636+
};
637+
638+
var editComment = new Mutation().UpdatePullRequestReviewComment(updatePullRequestReviewCommentInput)
639+
.Select(x => new PullRequestReviewCommentModel
640+
{
641+
Id = x.PullRequestReviewComment.DatabaseId.Value,
642+
NodeId = x.PullRequestReviewComment.Id,
643+
Body = x.PullRequestReviewComment.Body,
644+
CommitId = x.PullRequestReviewComment.Commit.Oid,
645+
Path = x.PullRequestReviewComment.Path,
646+
Position = x.PullRequestReviewComment.Position,
647+
CreatedAt = x.PullRequestReviewComment.CreatedAt.Value,
648+
DiffHunk = x.PullRequestReviewComment.DiffHunk,
649+
OriginalPosition = x.PullRequestReviewComment.OriginalPosition,
650+
OriginalCommitId = x.PullRequestReviewComment.OriginalCommit.Oid,
651+
PullRequestReviewId = x.PullRequestReviewComment.PullRequestReview.DatabaseId.Value,
652+
User = user,
653+
IsPending = !x.PullRequestReviewComment.PublishedAt.HasValue,
654+
});
655+
656+
var result = await graphql.Run(editComment);
657+
await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentPost);
658+
return result;
659+
}
660+
603661
int GetUpdatedLineNumber(IInlineCommentThreadModel thread, IEnumerable<DiffChunk> diff)
604662
{
605663
var line = DiffUtilities.Match(diff, thread.DiffMatch);

0 commit comments

Comments
 (0)