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

Commit 6451937

Browse files
Starting to add an edit and delete button to inline comments
1 parent 9a3db00 commit 6451937

File tree

7 files changed

+165
-13
lines changed

7 files changed

+165
-13
lines changed

src/GitHub.InlineReviews/SampleData/CommentViewModelDesigner.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ public CommentViewModelDesigner()
3232
public ReactiveCommand<object> CancelEdit { get; }
3333
public ReactiveCommand<Unit> CommitEdit { get; }
3434
public ReactiveCommand<object> OpenOnGitHub { get; }
35+
public ReactiveCommand<object> Delete { get; }
3536
}
3637
}

src/GitHub.InlineReviews/ViewModels/CommentViewModel.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,32 @@ protected CommentViewModel(
6060
User = user;
6161
UpdatedAt = updatedAt;
6262

63+
var canDelete = this.WhenAnyValue(
64+
x => x.EditState,
65+
x =>
66+
{
67+
var sameUser = user.Equals(currentUser);
68+
var result = x == CommentEditState.None && sameUser;
69+
70+
log.Debug("CanDelete CommentEditState: {CommentEditState} SameUser: {SameUser} CanDelete:{CanDelete}", x, sameUser, result);
71+
72+
return result;
73+
});
74+
75+
Delete = ReactiveCommand.Create(canDelete);
76+
6377
var canEdit = this.WhenAnyValue(
6478
x => x.EditState,
65-
x => x == CommentEditState.Placeholder || (x == CommentEditState.None && user.Equals(currentUser)));
79+
x =>
80+
{
81+
var sameUser = user.Equals(currentUser);
82+
var result = x == CommentEditState.Placeholder ||
83+
(x == CommentEditState.None && sameUser);
84+
85+
log.Debug("CanEdit CommentEditState: {CommentEditState} SameUser: {SameUser} CanEdit:{CanEdit}", x, sameUser, result);
86+
87+
return result;
88+
});
6689

6790
BeginEdit = ReactiveCommand.Create(canEdit);
6891
BeginEdit.Subscribe(DoBeginEdit);
@@ -216,5 +239,8 @@ public DateTimeOffset UpdatedAt
216239

217240
/// <inheritdoc/>
218241
public ReactiveCommand<object> OpenOnGitHub { get; }
242+
243+
/// <inheritdoc/>
244+
public ReactiveCommand<object> Delete { get; }
219245
}
220246
}

src/GitHub.InlineReviews/ViewModels/ICommentViewModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,10 @@ public interface ICommentViewModel : IViewModel
8888
/// Gets a command to open the comment in a browser.
8989
/// </summary>
9090
ReactiveCommand<object> OpenOnGitHub { get; }
91+
92+
/// <summary>
93+
/// Deletes a comment.
94+
/// </summary>
95+
ReactiveCommand<object> Delete { get; }
9196
}
9297
}

src/GitHub.InlineReviews/ViewModels/InlineCommentThreadViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class InlineCommentThreadViewModel : CommentThreadViewModel
2020
/// <summary>
2121
/// Initializes a new instance of the <see cref="InlineCommentThreadViewModel"/> class.
2222
/// </summary>
23-
/// <param name="apiClient">The API client to use to post/update comments.</param>
2423
/// <param name="session">The current PR review session.</param>
24+
/// <param name="comments">The comments to display in this inline review.</param>
2525
public InlineCommentThreadViewModel(
2626
IPullRequestSession session,
2727
IEnumerable<IPullRequestReviewCommentModel> comments)

src/GitHub.InlineReviews/Views/CommentThreadView.xaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
<d:DesignProperties.DataContext>
1010
<x:Array Type="{x:Type sample:CommentThreadViewModelDesigner}">
1111
<sample:CommentThreadViewModelDesigner>
12-
<!-- <sample:CommentThreadViewModelDesigner.Comments>
12+
<sample:CommentThreadViewModelDesigner.Comments>
1313
<sample:CommentViewModelDesigner>
14+
<sample:CommentViewModelDesigner.EditState>Placeholder
15+
</sample:CommentViewModelDesigner.EditState>
1416
<sample:CommentViewModelDesigner.Body>
1517
I assume this doesn't do anything if our message isn't showing?
1618
</sample:CommentViewModelDesigner.Body>
@@ -25,7 +27,7 @@
2527
Reply...
2628
</sample:CommentViewModelDesigner.Body>
2729
</sample:CommentViewModelDesigner>
28-
</sample:CommentThreadViewModelDesigner.Comments> -->
30+
</sample:CommentThreadViewModelDesigner.Comments>
2931
</sample:CommentThreadViewModelDesigner>
3032
</x:Array>
3133
</d:DesignProperties.DataContext>

src/GitHub.InlineReviews/Views/CommentView.xaml

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
xmlns:views="clr-namespace:GitHub.InlineReviews.Views"
1313
mc:Ignorable="d" d:DesignWidth="300">
1414
<d:DesignProperties.DataContext>
15-
<sample:CommentViewModelDesigner EditState="Editing">
15+
<sample:CommentViewModelDesigner EditState="None">
1616
<sample:CommentViewModelDesigner.Body>
1717
You can use a `CompositeDisposable` type here, it's designed to handle disposables in an optimal way (you can just call `Dispose()` on it and it will handle disposing everything it holds).
1818
</sample:CommentViewModelDesigner.Body>
@@ -50,25 +50,41 @@
5050
</Style>
5151
</StackPanel.Style>
5252

53-
<StackPanel Orientation="Horizontal">
53+
<DockPanel>
5454
<controls:AccountAvatar Width="16"
5555
Height="16"
56-
Account="{Binding User}"/>
56+
Account="{Binding User}"
57+
DockPanel.Dock="Left" />
5758

58-
<TextBlock Foreground="{DynamicResource GitHubVsToolWindowText}" FontWeight="Bold" Text="{Binding User.Login}" Margin="4 0"/>
59+
<TextBlock Foreground="{DynamicResource GitHubVsToolWindowText}" FontWeight="Bold" Text="{Binding User.Login}" Margin="4 0"
60+
DockPanel.Dock="Left" />
5961
<ui:GitHubActionLink Content="{Binding UpdatedAt, Converter={ui:DurationToStringConverter}}"
6062
Command="{Binding OpenOnGitHub}"
6163
Foreground="{DynamicResource GitHubVsToolWindowText}"
62-
Opacity="0.75" />
64+
Opacity="0.75"
65+
DockPanel.Dock="Left" />
6366
<Border Background="{DynamicResource VsBrush.InfoBackground}"
6467
BorderBrush="{DynamicResource VsBrush.AccentPale}"
6568
BorderThickness="1"
6669
CornerRadius="3"
6770
Padding="2 1"
71+
DockPanel.Dock="Left"
6872
Visibility="{Binding IsPending, Converter={ui:BooleanToVisibilityConverter}, FallbackValue=Collapsed}">
6973
<TextBlock FontSize="10">Pending</TextBlock>
7074
</Border>
71-
</StackPanel>
75+
<ui:GitHubActionLink Content="Delete"
76+
Command="{Binding Delete}"
77+
Foreground="{DynamicResource GitHubVsToolWindowText}"
78+
Opacity="0.75"
79+
HorizontalAlignment="Right"
80+
DockPanel.Dock="Right"/>
81+
<ui:GitHubActionLink Content="Edit"
82+
Command="{Binding BeginEdit}"
83+
Foreground="{DynamicResource GitHubVsToolWindowText}"
84+
Opacity="0.75"
85+
HorizontalAlignment="Right"
86+
DockPanel.Dock="Right" />
87+
</DockPanel>
7288

7389

7490
<markdig:MarkdownViewer Grid.Column="1" Grid.Row="1"

test/GitHub.InlineReviews.UnitTests/ViewModels/PullRequestReviewCommentViewModelTests.cs

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,102 @@ public void IsTrueWhenSessionHasNoPendingReview()
3232
}
3333
}
3434

35+
public class TheBeginEditProperty
36+
{
37+
[Test]
38+
public void CanBeExecutedForPlaceholders()
39+
{
40+
var session = CreateSession();
41+
var thread = CreateThread();
42+
var currentUser = Substitute.For<IAccount>();
43+
var target = PullRequestReviewCommentViewModel.CreatePlaceholder(session, thread, currentUser);
44+
Assert.That(target.BeginEdit.CanExecute(new object()), Is.True);
45+
}
46+
47+
[Test]
48+
public void CanBeExecutedForCommentsByTheSameAuthor()
49+
{
50+
var session = CreateSession();
51+
var thread = CreateThread();
52+
53+
var currentUser = Substitute.For<IAccount>();
54+
55+
var pullRequestReviewCommentModel = Substitute.For<IPullRequestReviewCommentModel>();
56+
pullRequestReviewCommentModel.User.Returns(currentUser);
57+
58+
currentUser.Equals(Arg.Is(currentUser)).Returns(true);
59+
60+
var target = CreateTarget(session, thread, currentUser, pullRequestReviewCommentModel);
61+
Assert.That(target.BeginEdit.CanExecute(new object()), Is.True);
62+
}
63+
64+
[Test]
65+
public void CannotBeExecutedForCommentsByAnotherAuthor()
66+
{
67+
var session = CreateSession();
68+
var thread = CreateThread();
69+
70+
var currentUser = Substitute.For<IAccount>();
71+
var otherUser = Substitute.For<IAccount>();
72+
73+
var pullRequestReviewCommentModel = Substitute.For<IPullRequestReviewCommentModel>();
74+
pullRequestReviewCommentModel.User.Returns(otherUser);
75+
76+
currentUser.Equals(Arg.Is(otherUser)).Returns(false);
77+
78+
var target = CreateTarget(session, thread, currentUser, pullRequestReviewCommentModel);
79+
Assert.That(target.BeginEdit.CanExecute(new object()), Is.False);
80+
}
81+
}
82+
83+
public class TheDeleteProperty
84+
{
85+
[Test]
86+
public void CannotBeExecutedForPlaceholders()
87+
{
88+
var session = CreateSession();
89+
var thread = CreateThread();
90+
var currentUser = Substitute.For<IAccount>();
91+
var target = PullRequestReviewCommentViewModel.CreatePlaceholder(session, thread, currentUser);
92+
Assert.That(target.Delete.CanExecute(new object()), Is.False);
93+
}
94+
95+
[Test]
96+
public void CanBeExecutedForCommentsByTheSameAuthor()
97+
{
98+
var session = CreateSession();
99+
var thread = CreateThread();
100+
101+
var currentUser = Substitute.For<IAccount>();
102+
103+
var pullRequestReviewCommentModel = Substitute.For<IPullRequestReviewCommentModel>();
104+
pullRequestReviewCommentModel.User.Returns(currentUser);
105+
106+
currentUser.Equals(Arg.Is(currentUser)).Returns(true);
107+
108+
var target = CreateTarget(session, thread, currentUser, pullRequestReviewCommentModel);
109+
Assert.That(target.Delete.CanExecute(new object()), Is.True);
110+
}
111+
112+
[Test]
113+
public void CannotBeExecutedForCommentsByAnotherAuthor()
114+
{
115+
var session = CreateSession();
116+
var thread = CreateThread();
117+
118+
var currentUser = Substitute.For<IAccount>();
119+
var otherUser = Substitute.For<IAccount>();
120+
121+
var pullRequestReviewCommentModel = Substitute.For<IPullRequestReviewCommentModel>();
122+
pullRequestReviewCommentModel.User.Returns(otherUser);
123+
124+
currentUser.Equals(Arg.Is(otherUser)).Returns(false);
125+
126+
var target = CreateTarget(session, thread, currentUser, pullRequestReviewCommentModel);
127+
Assert.That(target.Delete.CanExecute(new object()), Is.False);
128+
}
129+
}
130+
35131
public class TheCommitCaptionProperty
36132
{
37133
[Test]
@@ -99,16 +195,22 @@ public void CallsSessionStartReview()
99195

100196
static PullRequestReviewCommentViewModel CreateTarget(
101197
IPullRequestSession session = null,
102-
ICommentThreadViewModel thread = null)
198+
ICommentThreadViewModel thread = null,
199+
IAccount currentUser = null,
200+
IPullRequestReviewCommentModel pullRequestReviewCommentModel = null
201+
)
103202
{
104203
session = session ?? CreateSession();
105204
thread = thread ?? CreateThread();
106205

206+
currentUser = currentUser ?? Substitute.For<IAccount>();
207+
pullRequestReviewCommentModel = pullRequestReviewCommentModel ?? Substitute.For<IPullRequestReviewCommentModel>();
208+
107209
return new PullRequestReviewCommentViewModel(
108210
session,
109211
thread,
110-
Substitute.For<IAccount>(),
111-
Substitute.For<IPullRequestReviewCommentModel>());
212+
currentUser,
213+
pullRequestReviewCommentModel);
112214
}
113215

114216
static IPullRequestSession CreateSession(

0 commit comments

Comments
 (0)