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

Commit 695dd35

Browse files
Starting to add functionality to handle the edit/delete
1 parent 1058cd5 commit 695dd35

File tree

9 files changed

+170
-9
lines changed

9 files changed

+170
-9
lines changed

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<ICommentModel> DeleteComment { get; }
2123

2224
public Uri GetCommentUrl(int id)
2325
{

src/GitHub.InlineReviews/SampleData/CommentViewModelDesigner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ public CommentViewModelDesigner()
3535
public ReactiveCommand<object> CancelEdit { get; }
3636
public ReactiveCommand<Unit> CommitEdit { get; }
3737
public ReactiveCommand<object> OpenOnGitHub { get; }
38-
public ReactiveCommand<object> Delete { get; }
38+
public ReactiveCommand<Unit> Delete { get; }
3939
}
4040
}

src/GitHub.InlineReviews/ViewModels/CommentThreadViewModel.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ namespace GitHub.InlineReviews.ViewModels
1212
public abstract class CommentThreadViewModel : ReactiveObject, ICommentThreadViewModel
1313
{
1414
ReactiveCommand<ICommentModel> postComment;
15+
private ReactiveCommand<ICommentModel> editComment;
16+
private ReactiveCommand<ICommentModel> deleteComment;
1517

1618
/// <summary>
1719
/// Intializes a new instance of the <see cref="CommentThreadViewModel"/> class.
1820
/// </summary>
1921
/// <param name="currentUser">The current user.</param>
20-
/// <param name="commentModels">The thread comments.</param>
2122
protected CommentThreadViewModel(IAccount currentUser)
2223
{
2324
Guard.ArgumentNotNull(currentUser, nameof(currentUser));
@@ -44,6 +45,30 @@ public ReactiveCommand<ICommentModel> PostComment
4445
}
4546
}
4647

48+
public ReactiveCommand<ICommentModel> EditComment
49+
{
50+
get { return editComment; }
51+
set
52+
{
53+
Guard.ArgumentNotNull(value, nameof(value));
54+
editComment = value;
55+
56+
value.ThrownExceptions.Subscribe(_ => { });
57+
}
58+
}
59+
60+
public ReactiveCommand<ICommentModel> DeleteComment
61+
{
62+
get { return deleteComment; }
63+
set
64+
{
65+
Guard.ArgumentNotNull(value, nameof(value));
66+
deleteComment = value;
67+
68+
value.ThrownExceptions.Subscribe(_ => { });
69+
}
70+
}
71+
4772
/// <inheritdoc/>
4873
public IAccount CurrentUser { get; }
4974

src/GitHub.InlineReviews/ViewModels/CommentViewModel.cs

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,15 @@ protected CommentViewModel(
6464
x => x.EditState,
6565
x => x == CommentEditState.None && user.Login.Equals(currentUser.Login));
6666

67-
Delete = ReactiveCommand.Create(canDelete);
67+
Delete = ReactiveCommand.CreateAsyncTask(canDelete, DoDelete);
6868

6969
var canEdit = this.WhenAnyValue(
7070
x => x.EditState,
7171
x => x == CommentEditState.None && user.Login.Equals(currentUser.Login));
7272

7373
BeginEdit = ReactiveCommand.Create(canEdit);
7474
BeginEdit.Subscribe(DoBeginEdit);
75+
AddErrorHandler(BeginEdit);
7576

7677
var canCreate = this.WhenAnyValue(
7778
x => x.EditState,
@@ -91,10 +92,23 @@ protected CommentViewModel(
9192
DoCommitCreate);
9293
AddErrorHandler(CommitCreate);
9394

95+
CommitEdit = ReactiveCommand.CreateAsyncTask(
96+
Observable.CombineLatest(
97+
this.WhenAnyValue(x => x.IsReadOnly),
98+
this.WhenAnyValue(x => x.Body, x => !string.IsNullOrWhiteSpace(x)),
99+
this.WhenAnyObservable(x => x.Thread.EditComment.CanExecuteObservable),
100+
(readOnly, hasBody, canPost) => !readOnly && hasBody && canPost),
101+
DoCommitEdit);
102+
AddErrorHandler(CommitEdit);
103+
94104
CancelCreate = ReactiveCommand.Create(CommitCreate.IsExecuting.Select(x => !x));
95105
CancelCreate.Subscribe(DoCancelCreate);
96106
AddErrorHandler(CancelCreate);
97107

108+
CancelEdit = ReactiveCommand.Create(CommitEdit.IsExecuting.Select(x => !x));
109+
CancelEdit.Subscribe(DoCancelEdit);
110+
AddErrorHandler(CancelEdit);
111+
98112
OpenOnGitHub = ReactiveCommand.Create(this.WhenAnyValue(x => x.Id, x => x != 0));
99113
}
100114

@@ -117,6 +131,27 @@ protected void AddErrorHandler<T>(ReactiveCommand<T> command)
117131
command.ThrownExceptions.Subscribe(x => ErrorMessage = x.Message);
118132
}
119133

134+
async Task DoDelete(object unused)
135+
{
136+
try
137+
{
138+
ErrorMessage = null;
139+
IsSubmitting = true;
140+
141+
await Thread.DeleteComment.ExecuteAsyncTask(Body);
142+
}
143+
catch (Exception e)
144+
{
145+
var message = e.Message;
146+
ErrorMessage = message;
147+
log.Error(e, "Error Deleting comment");
148+
}
149+
finally
150+
{
151+
IsSubmitting = false;
152+
}
153+
}
154+
120155
void DoBeginEdit(object unused)
121156
{
122157
if (state != CommentEditState.Editing)
@@ -135,6 +170,17 @@ void DoBeginCreate(object unused)
135170
}
136171
}
137172

173+
void DoCancelEdit(object unused)
174+
{
175+
if (EditState == CommentEditState.Editing)
176+
{
177+
EditState = string.IsNullOrWhiteSpace(undoBody) ? CommentEditState.Placeholder : CommentEditState.None;
178+
Body = undoBody;
179+
ErrorMessage = null;
180+
undoBody = null;
181+
}
182+
}
183+
138184
void DoCancelCreate(object unused)
139185
{
140186
if (EditState == CommentEditState.Creating)
@@ -171,6 +217,31 @@ async Task DoCommitCreate(object unused)
171217
}
172218
}
173219

220+
async Task DoCommitEdit(object unused)
221+
{
222+
try
223+
{
224+
ErrorMessage = null;
225+
IsSubmitting = true;
226+
227+
var model = await Thread.EditComment.ExecuteAsyncTask(Body);
228+
Id = model.Id;
229+
NodeId = model.NodeId;
230+
EditState = CommentEditState.None;
231+
UpdatedAt = DateTimeOffset.Now;
232+
}
233+
catch (Exception e)
234+
{
235+
var message = e.Message;
236+
ErrorMessage = message;
237+
log.Error(e, "Error editing comment");
238+
}
239+
finally
240+
{
241+
IsSubmitting = false;
242+
}
243+
}
244+
174245
/// <inheritdoc/>
175246
public int Id { get; private set; }
176247

@@ -250,6 +321,6 @@ public DateTimeOffset UpdatedAt
250321
public ReactiveCommand<object> OpenOnGitHub { get; }
251322

252323
/// <inheritdoc/>
253-
public ReactiveCommand<object> Delete { get; }
324+
public ReactiveCommand<Unit> Delete { get; }
254325
}
255326
}

src/GitHub.InlineReviews/ViewModels/ICommentThreadViewModel.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,15 @@ public interface ICommentThreadViewModel
3131
/// Called by a comment in the thread to post itself as a new comment to the API.
3232
/// </summary>
3333
ReactiveCommand<ICommentModel> PostComment { get; }
34+
35+
/// <summary>
36+
/// Called by a comment in the thread to post itself as an edit to a comment to the API.
37+
/// </summary>
38+
ReactiveCommand<ICommentModel> EditComment { get; }
39+
40+
/// <summary>
41+
/// Called by a comment in the thread to send a delete of the comment to the API.
42+
/// </summary>
43+
ReactiveCommand<ICommentModel> DeleteComment { get; }
3444
}
3545
}

src/GitHub.InlineReviews/ViewModels/ICommentViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,6 @@ public interface ICommentViewModel : IViewModel
108108
/// <summary>
109109
/// Deletes a comment.
110110
/// </summary>
111-
ReactiveCommand<object> Delete { get; }
111+
ReactiveCommand<Unit> Delete { get; }
112112
}
113113
}

src/GitHub.InlineReviews/ViewModels/InlineCommentThreadViewModel.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ public InlineCommentThreadViewModel(
3535
Observable.Return(true),
3636
DoPostComment);
3737

38+
EditComment = ReactiveCommand.CreateAsyncTask(
39+
Observable.Return(true),
40+
DoEditComment);
41+
42+
DeleteComment = ReactiveCommand.CreateAsyncTask(
43+
Observable.Return(true),
44+
DoDeleteComment);
45+
3846
foreach (var comment in comments)
3947
{
4048
Comments.Add(new PullRequestReviewCommentViewModel(session, this, CurrentUser, comment));
@@ -68,5 +76,23 @@ async Task<ICommentModel> DoPostComment(object parameter)
6876
var nodeId = Comments[0].NodeId;
6977
return await Session.PostReviewComment(body, replyId, nodeId);
7078
}
79+
80+
Task<ICommentModel> DoEditComment(object parameter)
81+
{
82+
Guard.ArgumentNotNull(parameter, nameof(parameter));
83+
84+
var body = (string)parameter;
85+
var replyId = Comments[0].Id;
86+
var nodeId = Comments[0].NodeId;
87+
88+
throw new NotImplementedException();
89+
}
90+
91+
Task<ICommentModel> DoDeleteComment(object parameter)
92+
{
93+
Guard.ArgumentNotNull(parameter, nameof(parameter));
94+
95+
throw new NotImplementedException();
96+
}
7197
}
7298
}

src/GitHub.InlineReviews/Views/CommentView.xaml

Lines changed: 29 additions & 2 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="Creating">
15+
<sample:CommentViewModelDesigner EditState="Editing">
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>
@@ -105,6 +105,9 @@
105105
<DataTrigger Binding="{Binding EditState}" Value="Creating">
106106
<Setter Property="Visibility" Value="Visible"/>
107107
</DataTrigger>
108+
<DataTrigger Binding="{Binding EditState}" Value="Editing">
109+
<Setter Property="Visibility" Value="Visible"/>
110+
</DataTrigger>
108111
</Style.Triggers>
109112
</Style>
110113
</Grid.Style>
@@ -148,6 +151,10 @@
148151
<Setter Property="MinHeight" Value="100"/>
149152
<Setter Property="PromptText" Value="Leave a comment"/>
150153
</DataTrigger>
154+
<DataTrigger Binding="{Binding EditState}" Value="Editing">
155+
<Setter Property="MinHeight" Value="100"/>
156+
<Setter Property="PromptText" Value="Leave a comment"/>
157+
</DataTrigger>
151158
</Style.Triggers>
152159

153160
<Style.Resources>
@@ -176,7 +183,7 @@
176183
<TextBlock Text="{Binding ErrorMessage}" TextWrapping="Wrap"/>
177184
</DockPanel>
178185

179-
<StackPanel Name="buttonPanel"
186+
<StackPanel Name="creatingButtonPanel"
180187
Grid.Column="1" Grid.Row="3"
181188
Margin="4 8"
182189
HorizontalAlignment="Left"
@@ -200,6 +207,26 @@
200207
</Button>
201208
<Button Margin="4 0 0 0" Command="{Binding CancelCreate}">Cancel</Button>
202209
</StackPanel>
210+
211+
<StackPanel Name="editingButtonPanel"
212+
Grid.Column="1" Grid.Row="3"
213+
Margin="4 8"
214+
HorizontalAlignment="Left"
215+
Orientation="Horizontal"
216+
IsVisibleChanged="buttonPanel_IsVisibleChanged">
217+
<StackPanel.Style>
218+
<Style TargetType="FrameworkElement">
219+
<Setter Property="Visibility" Value="Collapsed"/>
220+
<Style.Triggers>
221+
<DataTrigger Binding="{Binding EditState}" Value="Editing">
222+
<Setter Property="Visibility" Value="Visible"/>
223+
</DataTrigger>
224+
</Style.Triggers>
225+
</Style>
226+
</StackPanel.Style>
227+
<Button Command="{Binding CommitEdit}">Edit</Button>
228+
<Button Margin="4 0 0 0" Command="{Binding CancelEdit}">Cancel</Button>
229+
</StackPanel>
203230
</Grid>
204231
</Grid>
205232
</views:GenericCommentView>

src/GitHub.InlineReviews/Views/CommentView.xaml.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void DoOpenOnGitHub()
3636

3737
private void CommentView_Loaded(object sender, System.Windows.RoutedEventArgs e)
3838
{
39-
if (buttonPanel.IsVisible)
39+
if (creatingButtonPanel.IsVisible || editingButtonPanel.IsVisible)
4040
{
4141
BringIntoView();
4242
body.Focus();
@@ -55,7 +55,7 @@ private void ReplyPlaceholder_GotFocus(object sender, System.Windows.RoutedEvent
5555

5656
private void buttonPanel_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
5757
{
58-
if (buttonPanel.IsVisible)
58+
if (creatingButtonPanel.IsVisible || editingButtonPanel.IsVisible)
5959
{
6060
BringIntoView();
6161
}

0 commit comments

Comments
 (0)