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

Commit 13e9fc8

Browse files
Merge branch 'master' into xml-doc-comments
2 parents 72fd428 + 0e69faa commit 13e9fc8

29 files changed

+536
-47
lines changed

src/GitHub.App/GitHub.App.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@
257257
<Compile Include="ViewModels\GitHubPane\LoggedOutViewModel.cs" />
258258
<Compile Include="ViewModels\GitHubPane\NavigationViewModel.cs" />
259259
<Compile Include="ViewModels\GitHubPane\GitHubPaneViewModel.cs" />
260+
<Compile Include="SampleData\PullRequestCheckViewModelDesigner.cs" />
260261
<Compile Include="ViewModels\GitHubPane\PullRequestFilesViewModel.cs" />
261262
<Compile Include="ViewModels\GitHubPane\PullRequestListItemViewModel.cs" />
262263
<Compile Include="ViewModels\GitHubPane\PullRequestListViewModel.cs" />
@@ -267,6 +268,7 @@
267268
<Compile Include="ViewModels\GitHubPane\NotAGitRepositoryViewModel.cs" />
268269
<Compile Include="ViewModels\GitHubPane\PullRequestReviewAuthoringViewModel.cs" />
269270
<Compile Include="ViewModels\GitHubPane\PullRequestReviewCommentViewModel.cs" />
271+
<Compile Include="ViewModels\GitHubPane\PullRequestCheckViewModel.cs" />
270272
<Compile Include="ViewModels\GitHubPane\PullRequestReviewSummaryViewModel.cs" />
271273
<Compile Include="ViewModels\GitHubPane\PullRequestReviewViewModel.cs" />
272274
<Compile Include="ViewModels\GitHubPane\PullRequestUserReviewsViewModel.cs" />
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Windows.Media.Imaging;
3+
using GitHub.ViewModels;
4+
using GitHub.ViewModels.GitHubPane;
5+
using ReactiveUI;
6+
7+
namespace GitHub.SampleData
8+
{
9+
public sealed class PullRequestCheckViewModelDesigner : ViewModelBase, IPullRequestCheckViewModel
10+
{
11+
public string Title { get; set; } = "continuous-integration/appveyor/pr";
12+
13+
public string Description { get; set; } = "AppVeyor build failed";
14+
15+
public PullRequestCheckStatus Status { get; set; } = PullRequestCheckStatus.Failure;
16+
17+
public Uri DetailsUrl { get; set; } = new Uri("http://github.com");
18+
19+
public string AvatarUrl { get; set; } = "https://avatars1.githubusercontent.com/u/417571?s=88&v=4";
20+
21+
public BitmapImage Avatar { get; set; } = null;
22+
23+
public ReactiveCommand<object> OpenDetailsUrl { get; set; } = null;
24+
}
25+
}

src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Diagnostics.CodeAnalysis;
4-
using System.Reactive;
5-
using System.Text;
6-
using System.Threading.Tasks;
71
using GitHub.Models;
82
using GitHub.Services;
93
using GitHub.ViewModels;
104
using GitHub.ViewModels.GitHubPane;
115
using ReactiveUI;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Diagnostics.CodeAnalysis;
9+
using System.Reactive;
10+
using System.Threading.Tasks;
11+
using GitHub.SampleData;
1212

1313
namespace GitHub.SampleData
1414
{
@@ -95,6 +95,8 @@ public PullRequestDetailViewModelDesigner()
9595
};
9696

9797
Files = new PullRequestFilesViewModelDesigner();
98+
99+
Checks = new PullRequestCheckViewModelDesigner[0];
98100
}
99101

100102
public PullRequestDetailModel Model { get; }
@@ -123,6 +125,8 @@ public PullRequestDetailViewModelDesigner()
123125
public ReactiveCommand<object> OpenOnGitHub { get; }
124126
public ReactiveCommand<object> ShowReview { get; }
125127

128+
public IReadOnlyList<IPullRequestCheckViewModel> Checks { get; }
129+
126130
public Task InitializeAsync(ILocalRepositoryModel localRepository, IConnection connection, string owner, string repo, int number) => Task.CompletedTask;
127131

128132
public string GetLocalFilePath(IPullRequestFileNode file)

src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics.CodeAnalysis;
4+
using GitHub.Models;
45
using GitHub.ViewModels;
56
using GitHub.ViewModels.GitHubPane;
67

@@ -16,5 +17,6 @@ public class PullRequestListItemViewModelDesigner : ViewModelBase, IPullRequestL
1617
public int Number { get; set; }
1718
public string Title { get; set; }
1819
public DateTimeOffset UpdatedAt { get; set; }
20+
public PullRequestChecksState Checks { get; set; }
1921
}
2022
}

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using Rothko;
2323
using static System.FormattableString;
2424
using static Octokit.GraphQL.Variable;
25+
using StatusState = GitHub.Models.StatusState;
2526

2627
namespace GitHub.Services
2728
{
@@ -93,6 +94,17 @@ public async Task<Page<PullRequestListItemModel>> ReadPullRequests(
9394
Items = page.Nodes.Select(pr => new ListItemAdapter
9495
{
9596
Id = pr.Id.Value,
97+
LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit =>
98+
new LastCommitSummaryModel
99+
{
100+
Statuses = commit.Commit.Status
101+
.Select(context =>
102+
context.Contexts.Select(statusContext => new StatusSummaryModel
103+
{
104+
State = (StatusState)statusContext.State,
105+
}).ToList()
106+
).SingleOrDefault()
107+
}).ToList().FirstOrDefault(),
96108
Author = new ActorModel
97109
{
98110
Login = pr.Author.Login,
@@ -123,10 +135,46 @@ public async Task<Page<PullRequestListItemModel>> ReadPullRequests(
123135

124136
var result = await graphql.Run(readPullRequests, vars);
125137

126-
foreach (ListItemAdapter item in result.Items)
138+
foreach (var item in result.Items.Cast<ListItemAdapter>())
127139
{
128140
item.CommentCount += item.Reviews.Sum(x => x.Count);
129141
item.Reviews = null;
142+
143+
var hasStatuses = item.LastCommit.Statuses != null
144+
&& item.LastCommit.Statuses.Any();
145+
146+
if (!hasStatuses)
147+
{
148+
item.Checks = PullRequestChecksState.None;
149+
}
150+
else
151+
{
152+
var statusHasFailure = item.LastCommit
153+
.Statuses
154+
.Any(status => status.State == StatusState.Failure);
155+
156+
var statusHasCompleteSuccess = true;
157+
if (!statusHasFailure)
158+
{
159+
statusHasCompleteSuccess =
160+
item.LastCommit.Statuses.All(status => status.State == StatusState.Success);
161+
}
162+
163+
if (statusHasFailure)
164+
{
165+
item.Checks = PullRequestChecksState.Failure;
166+
}
167+
else if (statusHasCompleteSuccess)
168+
{
169+
item.Checks = PullRequestChecksState.Success;
170+
}
171+
else
172+
{
173+
item.Checks = PullRequestChecksState.Pending;
174+
}
175+
}
176+
177+
item.LastCommit = null;
130178
}
131179

132180
return result;
@@ -840,6 +888,8 @@ static Tuple<string, int> ParseGHfVSConfigKeyValue(string value)
840888
class ListItemAdapter : PullRequestListItemModel
841889
{
842890
public IList<ReviewAdapter> Reviews { get; set; }
891+
892+
public LastCommitSummaryModel LastCommit { get; set; }
843893
}
844894

845895
class ReviewAdapter
@@ -848,5 +898,15 @@ class ReviewAdapter
848898
public int CommentCount { get; set; }
849899
public int Count => CommentCount + (!string.IsNullOrWhiteSpace(Body) ? 1 : 0);
850900
}
901+
902+
class StatusSummaryModel
903+
{
904+
public StatusState State { get; set; }
905+
}
906+
907+
class LastCommitSummaryModel
908+
{
909+
public List<StatusSummaryModel> Statuses { get; set; }
910+
}
851911
}
852912
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.Composition;
4+
using System.Linq;
5+
using System.Reactive;
6+
using System.Reactive.Linq;
7+
using System.Windows.Media.Imaging;
8+
using GitHub.Extensions;
9+
using GitHub.Factories;
10+
using GitHub.Models;
11+
using GitHub.Services;
12+
using ReactiveUI;
13+
14+
namespace GitHub.ViewModels.GitHubPane
15+
{
16+
[Export(typeof(IPullRequestCheckViewModel))]
17+
[PartCreationPolicy(CreationPolicy.NonShared)]
18+
public class PullRequestCheckViewModel: ViewModelBase, IPullRequestCheckViewModel
19+
{
20+
private readonly IUsageTracker usageTracker;
21+
const string DefaultAvatar = "pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png";
22+
23+
public static IEnumerable<IPullRequestCheckViewModel> Build(IViewViewModelFactory viewViewModelFactory, PullRequestDetailModel pullRequest)
24+
{
25+
return pullRequest.Statuses?.Select(model =>
26+
{
27+
PullRequestCheckStatus checkStatus;
28+
switch (model.State)
29+
{
30+
case StatusState.Expected:
31+
case StatusState.Error:
32+
case StatusState.Failure:
33+
checkStatus = PullRequestCheckStatus.Failure;
34+
break;
35+
case StatusState.Pending:
36+
checkStatus = PullRequestCheckStatus.Pending;
37+
break;
38+
case StatusState.Success:
39+
checkStatus = PullRequestCheckStatus.Success;
40+
break;
41+
default:
42+
throw new InvalidOperationException("Unkown PullRequestCheckStatusEnum");
43+
}
44+
45+
var pullRequestCheckViewModel = (PullRequestCheckViewModel) viewViewModelFactory.CreateViewModel<IPullRequestCheckViewModel>();
46+
pullRequestCheckViewModel.Title = model.Context;
47+
pullRequestCheckViewModel.Description = model.Description;
48+
pullRequestCheckViewModel.Status = checkStatus;
49+
pullRequestCheckViewModel.DetailsUrl = new Uri(model.TargetUrl);
50+
pullRequestCheckViewModel.AvatarUrl = model.AvatarUrl ?? DefaultAvatar;
51+
pullRequestCheckViewModel.Avatar = model.AvatarUrl != null
52+
? new BitmapImage(new Uri(model.AvatarUrl))
53+
: AvatarProvider.CreateBitmapImage(DefaultAvatar);
54+
55+
return pullRequestCheckViewModel;
56+
57+
}) ?? new PullRequestCheckViewModel[0];
58+
}
59+
60+
[ImportingConstructor]
61+
public PullRequestCheckViewModel(IUsageTracker usageTracker)
62+
{
63+
this.usageTracker = usageTracker;
64+
OpenDetailsUrl = ReactiveCommand.Create().OnExecuteCompleted(DoOpenDetailsUrl);
65+
}
66+
67+
private void DoOpenDetailsUrl(object obj)
68+
{
69+
usageTracker.IncrementCounter(x => x.NumberOfPRCheckStatusesOpenInGitHub).Forget();
70+
}
71+
72+
public string Title { get; private set; }
73+
74+
public string Description { get; private set; }
75+
76+
public PullRequestCheckStatus Status{ get; private set; }
77+
78+
public Uri DetailsUrl { get; private set; }
79+
80+
public string AvatarUrl { get; private set; }
81+
82+
public BitmapImage Avatar { get; private set; }
83+
84+
public ReactiveCommand<object> OpenDetailsUrl { get; }
85+
}
86+
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullReq
3838
readonly IUsageTracker usageTracker;
3939
readonly ITeamExplorerContext teamExplorerContext;
4040
readonly ISyncSubmodulesCommand syncSubmodulesCommand;
41+
readonly IViewViewModelFactory viewViewModelFactory;
4142
IModelService modelService;
4243
PullRequestDetailModel model;
4344
IActorViewModel author;
@@ -55,6 +56,7 @@ public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullReq
5556
bool refreshOnActivate;
5657
Uri webUrl;
5758
IDisposable sessionSubscription;
59+
IReadOnlyList<IPullRequestCheckViewModel> checks;
5860

5961
/// <summary>
6062
/// Initializes a new instance of the <see cref="PullRequestDetailViewModel"/> class.
@@ -74,21 +76,24 @@ public PullRequestDetailViewModel(
7476
IUsageTracker usageTracker,
7577
ITeamExplorerContext teamExplorerContext,
7678
IPullRequestFilesViewModel files,
77-
ISyncSubmodulesCommand syncSubmodulesCommand)
79+
ISyncSubmodulesCommand syncSubmodulesCommand,
80+
IViewViewModelFactory viewViewModelFactory)
7881
{
7982
Guard.ArgumentNotNull(pullRequestsService, nameof(pullRequestsService));
8083
Guard.ArgumentNotNull(sessionManager, nameof(sessionManager));
8184
Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory));
8285
Guard.ArgumentNotNull(usageTracker, nameof(usageTracker));
8386
Guard.ArgumentNotNull(teamExplorerContext, nameof(teamExplorerContext));
8487
Guard.ArgumentNotNull(syncSubmodulesCommand, nameof(syncSubmodulesCommand));
88+
Guard.ArgumentNotNull(viewViewModelFactory, nameof(viewViewModelFactory));
8589

8690
this.pullRequestsService = pullRequestsService;
8791
this.sessionManager = sessionManager;
8892
this.modelServiceFactory = modelServiceFactory;
8993
this.usageTracker = usageTracker;
9094
this.teamExplorerContext = teamExplorerContext;
9195
this.syncSubmodulesCommand = syncSubmodulesCommand;
96+
this.viewViewModelFactory = viewViewModelFactory;
9297
Files = files;
9398

9499
Checkout = ReactiveCommand.CreateAsyncObservable(
@@ -304,6 +309,12 @@ public Uri WebUrl
304309
/// </summary>
305310
public ReactiveCommand<object> ShowReview { get; }
306311

312+
public IReadOnlyList<IPullRequestCheckViewModel> Checks
313+
{
314+
get { return checks; }
315+
private set { this.RaiseAndSetIfChanged(ref checks, value); }
316+
}
317+
307318
/// <summary>
308319
/// Initializes the view model.
309320
/// </summary>
@@ -379,6 +390,8 @@ public async Task Load(PullRequestDetailModel pullRequest)
379390
Body = !string.IsNullOrWhiteSpace(pullRequest.Body) ? pullRequest.Body : Resources.NoDescriptionProvidedMarkdown;
380391
Reviews = PullRequestReviewSummaryViewModel.BuildByUser(Session.User, pullRequest).ToList();
381392

393+
Checks = PullRequestCheckViewModel.Build(viewViewModelFactory, pullRequest)?.ToList();
394+
382395
await Files.InitializeAsync(Session);
383396

384397
var localBranches = await pullRequestsService.GetLocalBranches(LocalRepository, pullRequest).ToList();

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,24 @@ public PullRequestListItemViewModel(PullRequestListItemModel model)
1919
{
2020
Id = model.Id;
2121
Author = new ActorViewModel(model.Author);
22+
Checks = model.Checks;
2223
CommentCount = model.CommentCount;
2324
Number = model.Number;
2425
Title = model.Title;
2526
UpdatedAt = model.UpdatedAt;
2627
}
2728

2829
/// <inheritdoc/>
29-
public string Id { get; protected set; }
30+
public string Id { get; }
3031

3132
/// <inheritdoc/>
32-
public IActorViewModel Author { get; protected set; }
33+
public IActorViewModel Author { get; }
3334

3435
/// <inheritdoc/>
35-
public int CommentCount { get; protected set; }
36+
public PullRequestChecksState Checks { get; }
37+
38+
/// <inheritdoc/>
39+
public int CommentCount { get; }
3640

3741
/// <inheritdoc/>
3842
public bool IsCurrent
@@ -42,12 +46,12 @@ public bool IsCurrent
4246
}
4347

4448
/// <inheritdoc/>
45-
public int Number { get; protected set; }
49+
public int Number { get; }
4650

4751
/// <inheritdoc/>
48-
public string Title { get; protected set; }
52+
public string Title { get; }
4953

5054
/// <inheritdoc/>
51-
public DateTimeOffset UpdatedAt { get; protected set; }
55+
public DateTimeOffset UpdatedAt { get; }
5256
}
5357
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public PullRequestReviewAuthoringViewModel(
6868
_ => DoSubmit(Octokit.PullRequestReviewEvent.RequestChanges));
6969
Cancel = ReactiveCommand.CreateAsyncTask(DoCancel);
7070
NavigateToPullRequest = ReactiveCommand.Create().OnExecuteCompleted(_ =>
71-
NavigateTo(Invariant($"{LocalRepository.Owner}/{LocalRepository.Name}/pull/{PullRequestModel.Number}")));
71+
NavigateTo(Invariant($"{RemoteRepositoryOwner}/{LocalRepository.Name}/pull/{PullRequestModel.Number}")));
7272
}
7373

7474
/// <inheritdoc/>

0 commit comments

Comments
 (0)