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

Commit bb8d412

Browse files
authored
Merge pull request #1562 from github/feature/pr-review-authoring
Start PR Reviews from Inline Comments
2 parents 94205d8 + 3ef2f07 commit bb8d412

File tree

46 files changed

+2499
-120
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2499
-120
lines changed

src/GitHub.App/Api/ApiClient.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,27 @@ public IObservable<Repository> CreateRepository(NewRepository repository, string
4848
return (isUser ? client.Create(repository) : client.Create(login, repository));
4949
}
5050

51+
public IObservable<PullRequestReview> PostPullRequestReview(
52+
string owner,
53+
string name,
54+
int number,
55+
string commitId,
56+
string body,
57+
PullRequestReviewEvent e)
58+
{
59+
Guard.ArgumentNotEmptyString(owner, nameof(owner));
60+
Guard.ArgumentNotEmptyString(name, nameof(name));
61+
62+
var review = new PullRequestReviewCreate
63+
{
64+
Body = body,
65+
CommitId = commitId,
66+
Event = e,
67+
};
68+
69+
return gitHubClient.PullRequest.Review.Create(owner, name, number, review);
70+
}
71+
5172
public IObservable<PullRequestReviewComment> CreatePullRequestReviewComment(
5273
string owner,
5374
string name,

src/GitHub.App/GitHub.App.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
<Compile Include="Models\PullRequestDetailArgument.cs" />
213213
<Compile Include="Models\PullRequestReviewModel.cs" />
214214
<Compile Include="SampleData\PullRequestFilesViewModelDesigner.cs" />
215+
<Compile Include="SampleData\PullRequestReviewAuthoringViewModelDesigner.cs" />
215216
<Compile Include="SampleData\PullRequestReviewFileCommentViewModelDesigner.cs" />
216217
<Compile Include="SampleData\PullRequestReviewViewModelDesigner.cs" />
217218
<Compile Include="SampleData\PullRequestUserReviewsViewModelDesigner.cs" />
@@ -243,6 +244,7 @@
243244
<Compile Include="ViewModels\GitHubPane\PullRequestCreationViewModel.cs" />
244245
<Compile Include="ViewModels\GitHubPane\NotAGitHubRepositoryViewModel.cs" />
245246
<Compile Include="ViewModels\GitHubPane\NotAGitRepositoryViewModel.cs" />
247+
<Compile Include="ViewModels\GitHubPane\PullRequestReviewAuthoringViewModel.cs" />
246248
<Compile Include="ViewModels\GitHubPane\PullRequestReviewFileCommentViewModel.cs" />
247249
<Compile Include="ViewModels\GitHubPane\PullRequestReviewSummaryViewModel.cs" />
248250
<Compile Include="ViewModels\GitHubPane\PullRequestReviewViewModel.cs" />
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reactive;
4+
using System.Threading.Tasks;
5+
using GitHub.Models;
6+
using GitHub.ViewModels.GitHubPane;
7+
using ReactiveUI;
8+
9+
namespace GitHub.SampleData
10+
{
11+
public class PullRequestReviewAuthoringViewModelDesigner : PanePageViewModelBase, IPullRequestReviewAuthoringViewModel
12+
{
13+
public PullRequestReviewAuthoringViewModelDesigner()
14+
{
15+
PullRequestModel = new PullRequestModel(
16+
419,
17+
"Fix a ton of potential crashers, odd code and redundant calls in ModelService",
18+
new AccountDesigner { Login = "Haacked", IsUser = true },
19+
DateTimeOffset.Now - TimeSpan.FromDays(2));
20+
21+
Files = new PullRequestFilesViewModelDesigner();
22+
23+
FileComments = new[]
24+
{
25+
new PullRequestReviewFileCommentViewModelDesigner
26+
{
27+
Body = @"These should probably be properties. Most likely they should be readonly properties. I know that makes creating instances of these not look as nice as using property initializers when constructing an instance, but if these properties should never be mutated after construction, then it guides future consumers to the right behavior.
28+
29+
However, if you're two-way binding these properties to a UI, then ignore the readonly part and make them properties. But in that case they should probably be reactive properties (or implement INPC).",
30+
RelativePath = "src/GitHub.Exports.Reactive/ViewModels/IPullRequestListViewModel.cs",
31+
},
32+
new PullRequestReviewFileCommentViewModelDesigner
33+
{
34+
Body = "While I have no problems with naming a variable ass I think we should probably avoid swear words in case Microsoft runs their Policheck tool against this code.",
35+
RelativePath = "src/GitHub.App/ViewModels/PullRequestListViewModel.cs",
36+
},
37+
};
38+
}
39+
40+
public string Body { get; set; }
41+
public bool CanApproveRequestChanges { get; set; }
42+
public IReadOnlyList<IPullRequestReviewFileCommentViewModel> FileComments { get; }
43+
public IPullRequestFilesViewModel Files { get; }
44+
public ILocalRepositoryModel LocalRepository { get; set; }
45+
public IPullRequestReviewModel Model { get; set; }
46+
public ReactiveCommand<object> NavigateToPullRequest { get; }
47+
public string OperationError { get; set; }
48+
public IPullRequestModel PullRequestModel { get; set; }
49+
public string RemoteRepositoryOwner { get; set; }
50+
public ReactiveCommand<Unit> Submit { get; }
51+
52+
public Task InitializeAsync(
53+
ILocalRepositoryModel localRepository,
54+
IConnection connection,
55+
string owner,
56+
string repo,
57+
int pullRequestNumber)
58+
{
59+
throw new NotImplementedException();
60+
}
61+
}
62+
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public sealed class GitHubPaneViewModel : ViewModelBase, IGitHubPaneViewModel, I
3333
{
3434
static readonly ILogger log = LogManager.ForContext<GitHubPaneViewModel>();
3535
static readonly Regex pullUri = CreateRoute("/:owner/:repo/pull/:number");
36+
static readonly Regex pullNewReviewUri = CreateRoute("/:owner/:repo/pull/:number/review/new");
3637
static readonly Regex pullUserReviewsUri = CreateRoute("/:owner/:repo/pull/:number/reviews/:login");
3738

3839
readonly IViewViewModelFactory viewModelFactory;
@@ -244,6 +245,13 @@ public async Task NavigateTo(Uri uri)
244245
var number = int.Parse(match.Groups["number"].Value);
245246
await ShowPullRequest(owner, repo, number);
246247
}
248+
else if ((match = pullNewReviewUri.Match(uri.AbsolutePath))?.Success == true)
249+
{
250+
var owner = match.Groups["owner"].Value;
251+
var repo = match.Groups["repo"].Value;
252+
var number = int.Parse(match.Groups["number"].Value);
253+
await ShowPullRequestReviewAuthoring(owner, repo, number);
254+
}
247255
else if ((match = pullUserReviewsUri.Match(uri.AbsolutePath))?.Success == true)
248256
{
249257
var owner = match.Groups["owner"].Value;
@@ -305,6 +313,19 @@ public Task ShowPullRequestReviews(string owner, string repo, int number, string
305313
x.User.Login == login);
306314
}
307315

316+
/// <inheritdoc/>
317+
public Task ShowPullRequestReviewAuthoring(string owner, string repo, int number)
318+
{
319+
Guard.ArgumentNotNull(owner, nameof(owner));
320+
Guard.ArgumentNotNull(repo, nameof(repo));
321+
322+
return NavigateTo<IPullRequestReviewAuthoringViewModel>(
323+
x => x.InitializeAsync(LocalRepository, Connection, owner, repo, number),
324+
x => x.RemoteRepositoryOwner == owner &&
325+
x.LocalRepository.Name == repo &&
326+
x.PullRequestModel.Number == number);
327+
}
328+
308329
async Task CreateInitializeTask(IServiceProvider paneServiceProvider)
309330
{
310331
await UpdateContent(teamExplorerContext.ActiveRepository);

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullReq
5353
bool active;
5454
bool refreshOnActivate;
5555
Uri webUrl;
56+
IDisposable sessionSubscription;
5657

5758
/// <summary>
5859
/// Initializes a new instance of the <see cref="PullRequestDetailViewModel"/> class.
@@ -441,6 +442,11 @@ public async Task Load(IPullRequestModel pullRequest)
441442
UpdateState = null;
442443
}
443444

445+
sessionSubscription?.Dispose();
446+
sessionSubscription = Session.WhenAnyValue(x => x.HasPendingReview)
447+
.Skip(1)
448+
.Subscribe(x => Reviews = PullRequestReviewSummaryViewModel.BuildByUser(Session.User, Session.PullRequest).ToList());
449+
444450
if (firstLoad)
445451
{
446452
usageTracker.IncrementCounter(x => x.NumberOfPullRequestsOpened).Forget();
@@ -620,7 +626,7 @@ void DoShowReview(object item)
620626

621627
if (review.State == PullRequestReviewState.Pending)
622628
{
623-
throw new NotImplementedException();
629+
NavigateTo(Invariant($"{RemoteRepositoryOwner}/{LocalRepository.Name}/pull/{Number}/review/new"));
624630
}
625631
else
626632
{

0 commit comments

Comments
 (0)