Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

073124.02/subscribe #8886

Merged
merged 2 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ public class ReviewsController : BaseApiController
public readonly UserPreferenceCache _preferenceCache;
private readonly ICosmosUserProfileRepository _userProfileRepository;
private readonly IHubContext<SignalRHub> _signalRHubContext;
private readonly INotificationManager _notificationManager;
private readonly IWebHostEnvironment _env;

public ReviewsController(ILogger<ReviewsController> logger,
IAPIRevisionsManager reviewRevisionsManager, IReviewManager reviewManager,
ICommentsManager commentManager, IBlobCodeFileRepository codeFileRepository,
IConfiguration configuration, UserPreferenceCache preferenceCache,
ICosmosUserProfileRepository userProfileRepository, IHubContext<SignalRHub> signalRHub, IWebHostEnvironment env)
ICosmosUserProfileRepository userProfileRepository, IHubContext<SignalRHub> signalRHub,
INotificationManager notificationManager, IWebHostEnvironment env)
{
_logger = logger;
_apiRevisionsManager = reviewRevisionsManager;
Expand All @@ -44,6 +46,7 @@ public ReviewsController(ILogger<ReviewsController> logger,
_preferenceCache = preferenceCache;
_userProfileRepository = userProfileRepository;
_signalRHubContext = signalRHub;
_notificationManager = notificationManager;
_env = env;
}

Expand Down Expand Up @@ -117,6 +120,20 @@ public async Task<ActionResult> ToggleReviewApprovalAsync(string reviewId, strin
return new LeanJsonResult(updatedReview, StatusCodes.Status200OK);
}

/// <summary>
/// Endpoint used by Client SPA toggling Subscription to a review
/// </summary>
/// <param name="reviewId"></param>
/// <param name="state"></param> true = subscribe, false = unsubscribe
/// <returns></returns>
[HttpPost("{reviewId}/toggleSubscribe", Name = "ToggleSubscribe")]
public async Task<ActionResult<APIRevisionListItemModel>> ToggleSubscribeAsync(string reviewId, [FromQuery] bool state)
{
string userName = User.GetGitHubLogin();
await _notificationManager.ToggleSubscribedAsync(User, reviewId, state);
return Ok();
}

///<summary>
///Retrieve the Content (codeLines and Navigation) of a review
///</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public interface INotificationManager
public Task NotifyUserOnCommentTag(CommentItemModel comment);
public Task NotifyApproversOfReview(ClaimsPrincipal user, string apiRevisionId, HashSet<string> reviewers);
public Task NotifySubscribersOnNewRevisionAsync(ReviewListItemModel review, APIRevisionListItemModel revision, ClaimsPrincipal user);
public Task ToggleSubscribedAsync(ClaimsPrincipal user, string reviewId);
public Task ToggleSubscribedAsync(ClaimsPrincipal user, string reviewId, bool? state = null);
public Task SubscribeAsync(ReviewListItemModel review, ClaimsPrincipal user);
public Task UnsubscribeAsync(ReviewListItemModel review, ClaimsPrincipal user);
}
Expand Down
13 changes: 12 additions & 1 deletion src/dotnet/APIView/APIViewWeb/Managers/NotificationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,27 @@ public async Task NotifySubscribersOnNewRevisionAsync(ReviewListItemModel review
/// </summary>
/// <param name="user"></param>
/// <param name="reviewId"></param>
/// <param name="state"></param> true = subscribe, false = unsubscribe
/// <returns></returns>
public async Task ToggleSubscribedAsync(ClaimsPrincipal user, string reviewId)
public async Task ToggleSubscribedAsync(ClaimsPrincipal user, string reviewId, bool? state = null)
{
var review = await _reviewRepository.GetReviewAsync(reviewId);
if (PageModelHelpers.IsUserSubscribed(user, review.Subscribers))
{
if (state == true)
{
return; // already subscribed
}

await UnsubscribeAsync(review, user);
}
else
{
if (state == false)
{
return; // already unsubscribed
}

await SubscribeAsync(review, user);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@
</ul>
</app-page-options-section>

<app-page-options-section sectionName="Review Options">
<ul class="list-group">
<li class="list-group-item">
<p-inputSwitch [(ngModel)]="subscribeSwitch"
(onChange)="onSubscribeSwitchChange($event)" />
<label class="ms-2">Subscribe</label>
</li>
</ul>
</app-page-options-section>

<app-page-options-section sectionName="Change History" [collapsedInput]="true">
<ul class="list-group">
<li class="list-group-item change-history">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class ReviewPageOptionsComponent implements OnInit, OnChanges{
@Output() showLeftNavigationEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() disableCodeLinesLazyLoadingEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() markAsViewedEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() subscribeEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() showLineNumbersEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() apiRevisionApprovalEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() reviewApprovalEmitter : EventEmitter<boolean> = new EventEmitter<boolean>();
Expand All @@ -50,6 +51,7 @@ export class ReviewPageOptionsComponent implements OnInit, OnChanges{
showHiddenAPISwitch : boolean = false;
showLeftNavigationSwitch : boolean = true;
markedAsViewSwitch : boolean = false;
subscribeSwitch : boolean = false;
showLineNumbersSwitch : boolean = true;
disableCodeLinesLazyLoading: boolean = false;

Expand Down Expand Up @@ -104,26 +106,29 @@ export class ReviewPageOptionsComponent implements OnInit, OnChanges{
}

ngOnChanges(changes: SimpleChanges) {
if (changes['diffStyleInput']) {
if (changes['diffStyleInput'] && changes['diffStyleInput'].currentValue != undefined) {
this.setSelectedDiffStyle();
}

if (changes['userProfile']) {
if (changes['userProfile'] && changes['userProfile'].currentValue != undefined) {
this.setSubscribeSwitch();
this.setMarkedAsViewSwitch();
this.setPageOptionValues();
}

if (changes['activeAPIRevision'] && changes['activeAPIRevision'].currentValue != undefined) {
this.markedAsViewSwitch = this.activeAPIRevision!.viewedBy.includes(this.userProfile?.userName!);
this.setMarkedAsViewSwitch();
this.selectedApprovers = this.activeAPIRevision!.assignedReviewers.map(reviewer => reviewer.assingedTo);
this.setAPIRevisionApprovalStates();
this.setPullRequestsInfo();
}

if (changes['diffAPIRevision']) {
if (changes['diffAPIRevision'] && changes['diffAPIRevision'].currentValue != undefined) {
this.setAPIRevisionApprovalStates();
}

if (changes['review']) {
if (changes['review'] && changes['review'].currentValue != undefined) {
this.setSubscribeSwitch();
this.setReviewApprovalStatus();
}
}
Expand Down Expand Up @@ -193,6 +198,14 @@ export class ReviewPageOptionsComponent implements OnInit, OnChanges{
this.markAsViewedEmitter.emit(event.checked);
}

/**
* Callback for markedAsViewSwitch Change
* @param event the Filter event
*/
onSubscribeSwitchChange(event: InputSwitchOnChangeEvent) {
this.subscribeEmitter.emit(event.checked);
}

/**
* Callback for showLineNumbersSwitch Change
* @param event the Filter event
Expand Down Expand Up @@ -287,6 +300,14 @@ export class ReviewPageOptionsComponent implements OnInit, OnChanges{
});
}
}

setSubscribeSwitch() {
this.subscribeSwitch = (this.userProfile && this.review) ? this.review!.subscribers.includes(this.userProfile?.email!) : this.subscribeSwitch;
}

setMarkedAsViewSwitch() {
this.markedAsViewSwitch = (this.activeAPIRevision && this.userProfile)? this.activeAPIRevision!.viewedBy.includes(this.userProfile?.userName!): this.markedAsViewSwitch;
}

handleAPIRevisionApprovalAction() {
if (!this.activeAPIRevisionIsApprovedByCurrentUser && (this.hasActiveConversation || this.hasFatalDiagnostics)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
(showLeftNavigationEmitter)="handleShowLeftNavigationEmitter($event)"
(diffStyleEmitter)="handleDiffStyleEmitter($event)"
(markAsViewedEmitter)="handleMarkAsViewedEmitter($event)"
(subscribeEmitter)="handleSubscribeEmitter($event)"
(showLineNumbersEmitter)="handleShowLineNumbersEmitter($event)"
(apiRevisionApprovalEmitter)="handleApiRevisionApprovalEmitter($event)"
(reviewApprovalEmitter)="handleReviewApprovalEmitter($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ export class ReviewPageComponent implements OnInit {
});
}

handleSubscribeEmitter(state: boolean) {
this.reviewsService.toggleReviewSubscriptionByUser(this.reviewId!, state).pipe(take(1)).subscribe();
}

handleApiRevisionApprovalEmitter(value: boolean) {
if (value) {
this.apiRevisionsService.toggleAPIRevisionApproval(this.reviewId!, this.activeApiRevisionId!).pipe(take(1)).subscribe({
Expand Down
2 changes: 2 additions & 0 deletions src/dotnet/APIView/ClientSPA/src/app/_models/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class Review {
isDeleted: boolean
isApproved: boolean
changeHistory: ChangeHistory[]
subscribers: string[]

constructor() {
this.id = ''
Expand All @@ -23,6 +24,7 @@ export class Review {
this.isDeleted = false
this.isApproved = false
this.changeHistory = []
this.subscribers = []
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@ export class ReviewsService {
});
}

toggleReviewSubscriptionByUser(reviewId: string, state: boolean) {
let params = new HttpParams();
params = params.append('state', state.toString());

const headers = new HttpHeaders({
'Content-Type': 'application/json',
});

return this.http.post<APIRevision>(this.baseUrl + `/${reviewId}/toggleSubscribe`, {},
{
headers: headers,
params: params,
withCredentials: true
});
}

getReviewContent(reviewId: string, activeApiRevisionId: string | null = null, diffApiRevisionId: string | null = null) : Observable<ArrayBuffer>{
let params = new HttpParams();
if (activeApiRevisionId) {
Expand Down