diff --git a/TfsAdvanced.sln b/TfsAdvanced.sln index 570fa67..7cd3f3d 100644 --- a/TfsAdvanced.sln +++ b/TfsAdvanced.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.15 +VisualStudioVersion = 15.0.26730.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{28430696-29B7-46F4-9140-2EF000FB2D29}" EndProject @@ -53,4 +53,7 @@ Global {23D45B3D-C188-48F3-9078-35B61B1F293D} = {28430696-29B7-46F4-9140-2EF000FB2D29} {F88AE0D1-17B4-427E-8023-42A183EB05D3} = {28430696-29B7-46F4-9140-2EF000FB2D29} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {26745B40-C9AB-4327-8314-D7E3F85B161E} + EndGlobalSection EndGlobal diff --git a/src/TfsAdvanced.MessageBus/MessageBus.csproj b/src/TfsAdvanced.MessageBus/MessageBus.csproj new file mode 100644 index 0000000..88e10d3 --- /dev/null +++ b/src/TfsAdvanced.MessageBus/MessageBus.csproj @@ -0,0 +1,15 @@ + + + + Exe + netcoreapp1.1 + TfsAdvanced.MessageBus + TfsAdvanced.MessageBus + + + + + + + + diff --git a/src/TfsAdvanced.MessageBus/MessageBusExtensions.cs b/src/TfsAdvanced.MessageBus/MessageBusExtensions.cs new file mode 100644 index 0000000..542bf00 --- /dev/null +++ b/src/TfsAdvanced.MessageBus/MessageBusExtensions.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Autofac; +using ServiceConnect; +using ServiceConnect.Interfaces; + +namespace TfsAdvanced.MessageBus +{ + public static class MessageBusExtensions + { + public static void AddMessageBus(this ContainerBuilder builder) + { + var bus = Bus.Initialize(); + builder.RegisterInstance(bus).As(); + } + } +} diff --git a/src/TfsAdvanced.MessageBus/MessageBuses.cs b/src/TfsAdvanced.MessageBus/MessageBuses.cs new file mode 100644 index 0000000..bc59c6f --- /dev/null +++ b/src/TfsAdvanced.MessageBus/MessageBuses.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TfsAdvanced.MessageBus +{ + public class MessageBuses + { + public static string NEW_MESSAGES = "NewMessage"; + public static string UPDATED_MESSAGES = "UpdatedMEssages"; + + } +} diff --git a/src/TfsAdvanced.MessageBus/Messages/NewPullRequestMessage.cs b/src/TfsAdvanced.MessageBus/Messages/NewPullRequestMessage.cs new file mode 100644 index 0000000..44c6252 --- /dev/null +++ b/src/TfsAdvanced.MessageBus/Messages/NewPullRequestMessage.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TfsAdvanced.MessageBus.Messages +{ + public class NewPullRequestMessage + { + } +} diff --git a/src/TfsAdvanced.MessageBus/Messages/UpdatedPullRequestMessage.cs b/src/TfsAdvanced.MessageBus/Messages/UpdatedPullRequestMessage.cs new file mode 100644 index 0000000..e1c3c3b --- /dev/null +++ b/src/TfsAdvanced.MessageBus/Messages/UpdatedPullRequestMessage.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ServiceConnect.Interfaces; + +namespace TfsAdvanced.MessageBus.Messages +{ + public class UpdatedPullRequestMessage : Message + { + public UpdatedPullRequestMessage(Guid correlationId) : base(correlationId) + { + } + } +} diff --git a/src/TfsAdvanced/SocketConnections/ResponseType.cs b/src/TfsAdvanced/SocketConnections/ResponseType.cs index 027c5f6..76a643d 100644 --- a/src/TfsAdvanced/SocketConnections/ResponseType.cs +++ b/src/TfsAdvanced/SocketConnections/ResponseType.cs @@ -10,6 +10,7 @@ public enum ResponseType UpdatedCurrentUserPullRequest, UpdatedPullRequest, NewPullRequest, - CurrentUserCompletedPullRequest + CurrentUserCompletedPullRequest, + NewCurrentUserCompletedPullRequest } } diff --git a/src/TfsAdvanced/SocketConnections/WebSocketUpdater.cs b/src/TfsAdvanced/SocketConnections/WebSocketUpdater.cs index d79310f..788e4b3 100644 --- a/src/TfsAdvanced/SocketConnections/WebSocketUpdater.cs +++ b/src/TfsAdvanced/SocketConnections/WebSocketUpdater.cs @@ -94,7 +94,7 @@ private async Task SendNewPullRequests(WebSocket webSocket, IEnumerable responseObject = new Dictionary { - {"Type", ResponseType.UpdatedPullRequest}, + {"Type", ResponseType.NewPullRequest}, {"Data", newPullRequests} }; await SendMessage(webSocket, responseObject); @@ -134,17 +134,29 @@ private async Task SendPullRequestList(WebSocket webSocket, IEnumerable x.Creator.UniqueName == currentUserUniqueName).ToList(); + if (!currentUserCompletedMessages.Any()) + return; + + var repositoryLastUpdated = currentUserCompletedMessages.OrderByDescending(x => x.ClosedDate).First().ClosedDate; + if (!repositoryLastUpdated.HasValue) + return; if (repositoryLastUpdated > lastCompletedPullRequestUpdated) { - var currentUserCompletedMessages = completedPullRequestRepository.GetAll().Where(x => x.Creator.UniqueName == currentUserUniqueName); - await SendCompletedPullRequests(webSocket, currentUserCompletedMessages); - lastCompletedPullRequestUpdated = repositoryLastUpdated; + await SendCompletedPullRequests(webSocket, currentUserCompletedMessages, ResponseType.CurrentUserCompletedPullRequest); + // If this is the first time loading, don't send all the completed ones + if (lastCompletedPullRequestUpdated > DateTime.MinValue) + { + var newlyCompleted = currentUserCompletedMessages.Where(x => x.ClosedDate.HasValue && x.ClosedDate.Value > lastCompletedPullRequestUpdated); + await SendCompletedPullRequests(webSocket, newlyCompleted, ResponseType.NewCurrentUserCompletedPullRequest); + } + lastCompletedPullRequestUpdated = repositoryLastUpdated.Value; } } + private async Task SendMessage(WebSocket webSocket, IDictionary message) { try @@ -159,14 +171,16 @@ private async Task SendMessage(WebSocket webSocket, IDictionary } - private async Task SendCompletedPullRequests(WebSocket webSocket, IEnumerable completedPullRequests) + private async Task SendCompletedPullRequests(WebSocket webSocket, IEnumerable completedPullRequests, ResponseType responseType) { IDictionary responseObject = new Dictionary { - {"Type", ResponseType.CurrentUserCompletedPullRequest}, + {"Type", responseType}, {"Data", completedPullRequests} }; await SendMessage(webSocket, responseObject); } + + } } diff --git a/src/TfsAdvanced/wwwroot/images/thumbs-up.png b/src/TfsAdvanced/wwwroot/images/thumbs-up.png new file mode 100644 index 0000000..739ddc4 Binary files /dev/null and b/src/TfsAdvanced/wwwroot/images/thumbs-up.png differ diff --git a/src/TfsAdvanced/wwwroot/index.html b/src/TfsAdvanced/wwwroot/index.html index a24e77b..0425401 100644 --- a/src/TfsAdvanced/wwwroot/index.html +++ b/src/TfsAdvanced/wwwroot/index.html @@ -139,7 +139,7 @@

TFS Advanced is Loading

var messageType = message["Type"]; var data = message["Data"]; - + localStorage.setItem("HasUpdate", "true"); console.log("Message Push. Type :", messageType, ", Count: ", data.length); $("#brand").attr('title', "Last Server Response: " + new Date()); switch (messageType) { @@ -148,15 +148,19 @@

TFS Advanced is Loading

break; case "updatedCurrentUserPullRequest": localStorage.setItem("CurrentUserPullRequests", JSON.stringify(data)); - document.getElementById('mainPage').dispatchEvent(newMyPullRequestsEvent); + //window.dispatchEvent(newMyPullRequestsEvent); break; case "updatedPullRequest": localStorage.setItem("PullRequests", JSON.stringify(data)); - document.getElementById('mainPage').dispatchEvent(newPullRequestsEvent); + console.log("Updated pull requests"); + //window.dispatchEvent(updatedPullRequestsEvent); break; case "currentUserCompletedPullRequest": localStorage.setItem("CurrentUserCompletedPullRequests", JSON.stringify(data)); - document.getElementById('mainPage').dispatchEvent(newCompletedPullRequestsEvent); + //window.dispatchEvent(newCompletedPullRequestsEvent); + break; + case "newCurrentUserCompletedPullRequest": + CurrentUserCompletedPullRequestNotificationToast(data); break; } @@ -164,6 +168,26 @@

TFS Advanced is Loading

}); + function CurrentUserCompletedPullRequestNotificationToast(pullRequests) { + $.each(pullRequests, + function(index, pullRequest) { + var notification = new Notification('Your Pull Request Was Completed!', + { + icon: '/images/thumbs-up.png', + body: pullRequest.Repository.Name + " | " + pullRequest.Title + + }); + + notification.onclick = function (event) { + event.preventDefault(); + window.open(pullRequest.Url, '_blank'); + notification.close().bind(notification); + }; + + + }); + } + function NotificationToast(pullRequests) { $.each(pullRequests, function(index, pullRequest) { diff --git a/src/TfsAdvanced/wwwroot/js/pullRequests.js b/src/TfsAdvanced/wwwroot/js/pullRequests.js index cfcf34a..317131f 100644 --- a/src/TfsAdvanced/wwwroot/js/pullRequests.js +++ b/src/TfsAdvanced/wwwroot/js/pullRequests.js @@ -6,20 +6,23 @@ $("#myCompletedPullRequestPanel").on("click", }); function fetchData() { - - HandlMyPullRequests(); - HandleTeamPullRequests(); - HandleMyCompletedPullRequests(); - - formatPage(); + if (localStorage.getItem("HasUpdate") === "true") { + HandlMyPullRequests(); + HandleTeamPullRequests(); + HandleMyCompletedPullRequests(); + + formatPage(); + //window.addEventListener(updatedPullRequestsEvent, HandleTeamPullRequests, false); + //window.addEventListener(newCompletedPullRequestsEvent, HandleMyCompletedPullRequests, false); + //window.addEventListener(newMyPullRequestsEvent, HandlMyPullRequests, false); + localStorage.setItem("HasUpdate", "false"); + } + window.setTimeout(fetchData, 500); - document.getElementById("mainPage").addEventListener(updatedPullRequestsEvent, HandleTeamPullRequests, false); - document.getElementById("mainPage").addEventListener(newCompletedPullRequestsEvent, HandleMyCompletedPullRequests, false); - document.getElementById("mainPage").addEventListener(newMyPullRequestsEvent, HandlMyPullRequests, false); - } function HandlMyPullRequests() { + var myPullRequests = JSON.parse(localStorage.getItem("CurrentUserPullRequests")); if (!myPullRequests) @@ -34,7 +37,7 @@ function HandlMyPullRequests() { } } -function HandleTeamPullRequests() { +function HandleTeamPullRequests(event) { var pullRequests = JSON.parse(localStorage.getItem("PullRequests")); if(!pullRequests) return;