diff --git a/0_Framework/Application/AuthHelper.cs b/0_Framework/Application/AuthHelper.cs index 12f820f8..41e6efa2 100644 --- a/0_Framework/Application/AuthHelper.cs +++ b/0_Framework/Application/AuthHelper.cs @@ -199,7 +199,7 @@ public class AuthHelper : IAuthHelper new("WorkshopSlug",slug), new("WorkshopId", account.WorkshopId.ToString()), new("WorkshopName",account.WorkshopName??""), - new("pm.userId", account.PmUserId?.ToString() ?? "0"), + new("pm.userId", account.PmUserId.ToString()), }; diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionStatusChangedHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionStatusChangedHandler.cs new file mode 100644 index 00000000..cca24761 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionStatusChangedHandler.cs @@ -0,0 +1,23 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; +using MediatR; + +namespace GozareshgirProgramManager.Application.DomainEventHandlers.ProjectSection; + +public class TaskSectionStatusChangedHandler:INotificationHandler> +{ + private readonly IBoardNotificationPublisher _boardNotificationPublisher; + + public TaskSectionStatusChangedHandler(IBoardNotificationPublisher boardNotificationPublisher) + { + _boardNotificationPublisher = boardNotificationPublisher; + } + + public Task Handle(DomainEventNotification notification, CancellationToken cancellationToken) + { + var domainEvent = notification.DomainEvent; + _boardNotificationPublisher.SendProjectStatusChanged(domainEvent.UserId,domainEvent.OldStatus,domainEvent.NewStatus,domainEvent.SectionId); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationPublisher.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationPublisher.cs new file mode 100644 index 00000000..1f4d5f1b --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationPublisher.cs @@ -0,0 +1,9 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Interfaces; + +public interface IBoardNotificationPublisher +{ + Task SendProjectStatusChanged(long userId, TaskSectionStatus oldStatus, + TaskSectionStatus newStatus, Guid sectionId); +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs deleted file mode 100644 index 959e7fbf..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace GozareshgirProgramManager.Application.Interfaces; - -public interface IBoardNotificationService -{ - Task SendProjectAssignedAsync(); -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs index e478478d..b2a6fd91 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs @@ -159,7 +159,7 @@ public class TaskSection : EntityBase { var oldStatus = Status; Status = status; - AddDomainEvent(new TaskSectionStatusChangedEvent(Id, oldStatus, status)); + AddDomainEvent(new TaskSectionStatusChangedEvent(Id, oldStatus, status,CurrentAssignedUserId)); } public TimeSpan GetTotalTimeSpent() diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs index e823967e..fb6ca424 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs @@ -104,7 +104,8 @@ public record TaskSectionRemovedEvent(Guid TaskId, Guid SectionId) : IDomainEven } // TaskSection Events -public record TaskSectionStatusChangedEvent(Guid SectionId, TaskSectionStatus OldStatus, TaskSectionStatus NewStatus) : IDomainEvent +public record TaskSectionStatusChangedEvent(Guid SectionId, TaskSectionStatus OldStatus, + TaskSectionStatus NewStatus,long UserId) : IDomainEvent { public DateTime OccurredOn { get; init; } = DateTime.UtcNow; } diff --git a/ServiceHost/Hubs/ProgramManager/ProjectBoardHub.cs b/ServiceHost/Hubs/ProgramManager/ProjectBoardHub.cs new file mode 100644 index 00000000..5c262095 --- /dev/null +++ b/ServiceHost/Hubs/ProgramManager/ProjectBoardHub.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.SignalR; + +namespace ServiceHost.Hubs.ProgramManager; + +public class ProjectBoardHub:Hub +{ + public override async Task OnConnectedAsync() + { + var user = Context.User?.FindFirst("pm.userId")?.Value; + + if (user != null && user !="0") + { + await Groups.AddToGroupAsync( + Context.ConnectionId, + $"pm.user-{user}" + ); + } + + await base.OnConnectedAsync(); + } +} \ No newline at end of file diff --git a/ServiceHost/Notifications/ProgramManager/SignalRBoardNotificationPublisher.cs b/ServiceHost/Notifications/ProgramManager/SignalRBoardNotificationPublisher.cs new file mode 100644 index 00000000..130d8f09 --- /dev/null +++ b/ServiceHost/Notifications/ProgramManager/SignalRBoardNotificationPublisher.cs @@ -0,0 +1,30 @@ +using GozareshgirProgramManager.Application.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using Microsoft.AspNetCore.SignalR; +using ServiceHost.Hubs.ProgramManager; + +namespace ServiceHost.Notifications.ProgramManager; + +public class SignalRBoardNotificationPublisher:IBoardNotificationPublisher +{ + private readonly IHubContext _hubContext; + + public SignalRBoardNotificationPublisher(IHubContext hubContext) + { + _hubContext = hubContext; + } + + public Task SendProjectStatusChanged(long userId, TaskSectionStatus oldStatus, + TaskSectionStatus newStatus, Guid sectionId) + { + var payload = new + { + UserId = userId, + OldStatus = oldStatus, + NewStatus = newStatus, + SectionId = sectionId + }; + _hubContext.Clients.Group($"pm.user-{userId}").SendAsync("ReceiveProjectStatusChanged",payload); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 4378ec2c..65ff9eff 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -27,10 +27,13 @@ using Swashbuckle.AspNetCore.SwaggerUI; using AccountManagement.Domain.InternalApiCaller; using FluentValidation; using GozareshgirProgramManager.Application._Bootstrapper; +using GozareshgirProgramManager.Application.Interfaces; using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; using GozareshgirProgramManager.Infrastructure; using GozareshgirProgramManager.Infrastructure.Persistence.Seed; using Microsoft.OpenApi; +using ServiceHost.Hubs.ProgramManager; +using ServiceHost.Notifications.ProgramManager; using ServiceHost.Conventions; @@ -55,6 +58,7 @@ builder.Services.AddProgramManagerApplication(); builder.Services.AddProgramManagerInfrastructure(builder.Configuration); builder.Services.AddValidatorsFromAssemblyContaining(); builder.Services.AddScoped(); +builder.Services.AddScoped(); #region MongoDb var mongoConnectionSection = builder.Configuration.GetSection("MongoDb"); @@ -456,6 +460,7 @@ app.MapHub("/trackingHolidayHub"); app.MapHub("/trackingCheckoutHub"); // app.MapHub("/trackingFaceEmbeddingHub"); app.MapHub("/trackingSendSmsHub"); +app.MapHub("api/pm/board"); app.MapRazorPages(); app.MapControllers();