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

Commit d296739

Browse files
committed
Implement posting PR comments.
1 parent b724525 commit d296739

File tree

11 files changed

+149
-16
lines changed

11 files changed

+149
-16
lines changed

src/GitHub.App/SampleData/Documents/PullRequestPageViewModelDesigner.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Depends on #1993
8484
};
8585
}
8686

87+
public string Id { get; set; }
8788
public PullRequestState State { get; set; } = PullRequestState.Open;
8889
public IReadOnlyList<IViewModel> Timeline { get; }
8990
public string SourceBranchDisplayName { get; set; } = "feature/save-drafts";
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading.Tasks;
4+
using GitHub.Api;
5+
using GitHub.Models;
6+
using GitHub.Primitives;
7+
using Octokit.GraphQL;
8+
using Octokit.GraphQL.Model;
9+
using static Octokit.GraphQL.Variable;
10+
11+
namespace GitHub.Services
12+
{
13+
public abstract class IssueishService : IIssueishService
14+
{
15+
static ICompiledQuery<CommentModel> postComment;
16+
readonly IGraphQLClientFactory graphqlFactory;
17+
18+
public IssueishService(IGraphQLClientFactory graphqlFactory)
19+
{
20+
this.graphqlFactory = graphqlFactory;
21+
}
22+
23+
public async Task<CommentModel> PostComment(HostAddress address, string issueishId, string body)
24+
{
25+
var input = new AddCommentInput
26+
{
27+
Body = body,
28+
SubjectId = new ID(issueishId),
29+
};
30+
31+
if (postComment == null)
32+
{
33+
postComment = new Mutation()
34+
.AddComment(Var(nameof(input)))
35+
.CommentEdge
36+
.Node
37+
.Select(comment => new CommentModel
38+
{
39+
Author = new ActorModel
40+
{
41+
Login = comment.Author.Login,
42+
AvatarUrl = comment.Author.AvatarUrl(null),
43+
},
44+
Body = comment.Body,
45+
CreatedAt = comment.CreatedAt,
46+
DatabaseId = comment.DatabaseId.Value,
47+
Id = comment.Id.Value,
48+
Url = comment.Url,
49+
}).Compile();
50+
}
51+
52+
var vars = new Dictionary<string, object>
53+
{
54+
{ nameof(input), input },
55+
};
56+
57+
var graphql = await graphqlFactory.CreateConnection(address).ConfigureAwait(false);
58+
return await graphql.Run(postComment, vars).ConfigureAwait(false);
59+
}
60+
}
61+
}

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace GitHub.Services
3232
{
3333
[Export(typeof(IPullRequestService))]
3434
[PartCreationPolicy(CreationPolicy.Shared)]
35-
public class PullRequestService : IPullRequestService
35+
public class PullRequestService : IssueishService, IPullRequestService
3636
{
3737
const string SettingCreatedByGHfVS = "created-by-ghfvs";
3838
const string SettingGHfVSPullRequest = "ghfvs-pr-owner-number";
@@ -66,6 +66,7 @@ public PullRequestService(
6666
IGraphQLClientFactory graphqlFactory,
6767
IOperatingSystem os,
6868
IUsageTracker usageTracker)
69+
: base(graphqlFactory)
6970
{
7071
this.gitClient = gitClient;
7172
this.gitService = gitService;

src/GitHub.App/ViewModels/Documents/PullRequestPageViewModel.cs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using GitHub.Extensions;
77
using GitHub.Factories;
88
using GitHub.Models;
9-
using GitHub.SampleData;
9+
using GitHub.Primitives;
1010
using GitHub.Services;
1111
using ReactiveUI;
1212

@@ -23,6 +23,8 @@ public class PullRequestPageViewModel : PullRequestViewModelBase, IPullRequestPa
2323
readonly IPullRequestService service;
2424
readonly IPullRequestSessionManager sessionManager;
2525
readonly ITeamExplorerServices teServices;
26+
ActorModel currentUserModel;
27+
ReactiveList<IViewModel> timeline;
2628

2729
/// <summary>
2830
/// Initializes a new instance of the <see cref="PullRequestPageViewModel"/> class.
@@ -52,7 +54,7 @@ public PullRequestPageViewModel(
5254
public IActorViewModel CurrentUser { get; private set; }
5355

5456
/// <inheritdoc/>
55-
public IReadOnlyList<IViewModel> Timeline { get; private set; }
57+
public IReadOnlyList<IViewModel> Timeline => timeline;
5658

5759
/// <inheritdoc/>
5860
public ReactiveCommand<string, Unit> ShowCommit { get; }
@@ -69,9 +71,10 @@ public async Task InitializeAsync(
6971
{
7072
await base.InitializeAsync(repository, localRepository, model).ConfigureAwait(true);
7173

74+
currentUserModel = currentUser;
7275
CurrentUser = new ActorViewModel(currentUser);
76+
timeline = new ReactiveList<IViewModel>();
7377

74-
var timeline = new ReactiveList<IViewModel>();
7578
var commits = new List<CommitSummaryViewModel>();
7679

7780
foreach (var i in model.Timeline)
@@ -88,11 +91,7 @@ public async Task InitializeAsync(
8891
commits.Add(new CommitSummaryViewModel(commit));
8992
break;
9093
case CommentModel comment:
91-
{
92-
var vm = factory.CreateViewModel<IIssueishCommentViewModel>();
93-
await vm.InitializeAsync(this, currentUser, comment, null).ConfigureAwait(true);
94-
timeline.Add(vm);
95-
}
94+
await AddComment(comment).ConfigureAwait(true);
9695
break;
9796
}
9897
}
@@ -109,8 +108,15 @@ await placeholder.InitializeAsync(
109108
null,
110109
Resources.ClosePullRequest).ConfigureAwait(true);
111110
timeline.Add(placeholder);
111+
}
112112

113-
Timeline = timeline;
113+
/// <inheritdoc/>
114+
public async Task PostComment(string body)
115+
{
116+
var address = HostAddress.Create(Repository.CloneUrl);
117+
var comment = await service.PostComment(address, Id, body).ConfigureAwait(true);
118+
await AddComment(comment).ConfigureAwait(true);
119+
ClearPlaceholder();
114120
}
115121

116122
Task ICommentThreadViewModel.DeleteComment(int pullRequestId, int commentId)
@@ -123,9 +129,41 @@ Task ICommentThreadViewModel.EditComment(string id, string body)
123129
throw new NotImplementedException();
124130
}
125131

126-
Task ICommentThreadViewModel.PostComment(string body)
132+
async Task AddComment(CommentModel comment)
127133
{
128-
throw new NotImplementedException();
134+
var vm = factory.CreateViewModel<IIssueishCommentViewModel>();
135+
await vm.InitializeAsync(this, currentUserModel, comment, null).ConfigureAwait(true);
136+
137+
if (GetPlaceholder() == null)
138+
{
139+
timeline.Add(vm);
140+
}
141+
else
142+
{
143+
timeline.Insert(timeline.Count - 1, vm);
144+
}
145+
}
146+
147+
void ClearPlaceholder()
148+
{
149+
var placeholder = GetPlaceholder();
150+
151+
if (placeholder != null)
152+
{
153+
placeholder.Body = null;
154+
}
155+
}
156+
157+
ICommentViewModel GetPlaceholder()
158+
{
159+
if (timeline.Count > 0 &&
160+
timeline[timeline.Count - 1] is ICommentViewModel comment &&
161+
comment.Id == null)
162+
{
163+
return comment;
164+
}
165+
166+
return null;
129167
}
130168

131169
async Task DoShowCommit(string oid)

src/GitHub.App/ViewModels/GitHubPane/PullRequestUserReviewsViewModel.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ async Task Load(PullRequestDetailModel pullRequest)
144144

145145
try
146146
{
147-
await Task.Delay(0);
148147
PullRequestTitle = pullRequest.Title;
149148

150149
var reviews = new List<IPullRequestReviewViewModel>();

src/GitHub.App/ViewModels/IssueishViewModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public IssueishViewModel()
3232
/// <inheritdoc/>
3333
public IRemoteRepositoryModel Repository { get; private set; }
3434

35+
/// <inheritdoc/>
36+
public string Id { get; private set; }
37+
3538
/// <inheritdoc/>
3639
public int Number { get; private set; }
3740

@@ -71,6 +74,7 @@ protected Task InitializeAsync(
7174
IssueishDetailModel model)
7275
{
7376
Repository = repository;
77+
Id = model.Id;
7478
Author = new ActorViewModel(model.Author);
7579
Body = model.Body;
7680
Number = model.Number;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using GitHub.Models;
4+
using GitHub.Primitives;
5+
6+
namespace GitHub.Services
7+
{
8+
/// <summary>
9+
/// Services for issues and pull requests.
10+
/// </summary>
11+
public interface IIssueishService
12+
{
13+
/// <summary>
14+
/// Posts an issue or pull request comment.
15+
/// </summary>
16+
/// <param name="address">The address of the server.</param>
17+
/// <param name="issueishId">The GraphQL ID of the issue or pull request.</param>
18+
/// <param name="body">The comment body.</param>
19+
/// <returns>The model for the comment that was added.</returns>
20+
Task<CommentModel> PostComment(
21+
HostAddress address,
22+
string issueishId,
23+
string body);
24+
}
25+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace GitHub.Services
1111
{
12-
public interface IPullRequestService
12+
public interface IPullRequestService : IIssueishService
1313
{
1414
/// <summary>
1515
/// Reads a page of pull request items.

src/GitHub.Exports.Reactive/ViewModels/IIssueishViewModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ namespace GitHub.ViewModels
1010
/// </summary>
1111
public interface IIssueishViewModel : IViewModel
1212
{
13+
/// <summary>
14+
/// Gets the GraphQL ID for the issue or pull request.
15+
/// </summary>
16+
string Id { get; }
17+
1318
/// <summary>
1419
/// Gets the issue or pull request author.
1520
/// </summary>

src/GitHub.InlineReviews/Services/PullRequestSession.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,6 @@ async Task AddComment(PullRequestReviewCommentModel comment)
304304

305305
async Task UpdateFile(PullRequestSessionFile file)
306306
{
307-
await Task.Delay(0);
308307
var mergeBaseSha = await GetMergeBase();
309308
file.BaseSha = PullRequest.BaseRefSha;
310309
file.CommitSha = file.IsTrackingHead ? PullRequest.HeadRefSha : file.CommitSha;

0 commit comments

Comments
 (0)