Clean up
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled

This commit is contained in:
Yaojia Wang
2025-11-09 18:40:36 +01:00
parent 1d6e732018
commit 63ff1a9914
90 changed files with 748 additions and 1462 deletions

View File

@@ -3,29 +3,19 @@ using ColaFlow.API.Hubs;
namespace ColaFlow.API.Services;
public class RealtimeNotificationService : IRealtimeNotificationService
public class RealtimeNotificationService(
IHubContext<ProjectHub> projectHubContext,
IHubContext<NotificationHub> notificationHubContext,
ILogger<RealtimeNotificationService> logger)
: IRealtimeNotificationService
{
private readonly IHubContext<ProjectHub> _projectHubContext;
private readonly IHubContext<NotificationHub> _notificationHubContext;
private readonly ILogger<RealtimeNotificationService> _logger;
public RealtimeNotificationService(
IHubContext<ProjectHub> projectHubContext,
IHubContext<NotificationHub> notificationHubContext,
ILogger<RealtimeNotificationService> logger)
{
_projectHubContext = projectHubContext;
_notificationHubContext = notificationHubContext;
_logger = logger;
}
public async Task NotifyProjectCreated(Guid tenantId, Guid projectId, object project)
{
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying tenant {TenantId} of new project {ProjectId}", tenantId, projectId);
logger.LogInformation("Notifying tenant {TenantId} of new project {ProjectId}", tenantId, projectId);
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectCreated", project);
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectCreated", project);
}
public async Task NotifyProjectUpdated(Guid tenantId, Guid projectId, object project)
@@ -33,10 +23,10 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying project {ProjectId} updated", projectId);
logger.LogInformation("Notifying project {ProjectId} updated", projectId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("ProjectUpdated", project);
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectUpdated", project);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("ProjectUpdated", project);
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectUpdated", project);
}
public async Task NotifyProjectArchived(Guid tenantId, Guid projectId)
@@ -44,19 +34,19 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying project {ProjectId} archived", projectId);
logger.LogInformation("Notifying project {ProjectId} archived", projectId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("ProjectArchived", new { ProjectId = projectId });
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectArchived", new { ProjectId = projectId });
await projectHubContext.Clients.Group(projectGroupName).SendAsync("ProjectArchived", new { ProjectId = projectId });
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("ProjectArchived", new { ProjectId = projectId });
}
public async Task NotifyProjectUpdate(Guid tenantId, Guid projectId, object data)
{
var groupName = $"project-{projectId}";
_logger.LogInformation("Sending project update to group {GroupName}", groupName);
logger.LogInformation("Sending project update to group {GroupName}", groupName);
await _projectHubContext.Clients.Group(groupName).SendAsync("ProjectUpdated", data);
await projectHubContext.Clients.Group(groupName).SendAsync("ProjectUpdated", data);
}
// Epic notifications
@@ -65,28 +55,28 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying epic {EpicId} created in project {ProjectId}", epicId, projectId);
logger.LogInformation("Notifying epic {EpicId} created in project {ProjectId}", epicId, projectId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicCreated", epic);
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("EpicCreated", epic);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicCreated", epic);
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("EpicCreated", epic);
}
public async Task NotifyEpicUpdated(Guid tenantId, Guid projectId, Guid epicId, object epic)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying epic {EpicId} updated", epicId);
logger.LogInformation("Notifying epic {EpicId} updated", epicId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicUpdated", epic);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicUpdated", epic);
}
public async Task NotifyEpicDeleted(Guid tenantId, Guid projectId, Guid epicId)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying epic {EpicId} deleted", epicId);
logger.LogInformation("Notifying epic {EpicId} deleted", epicId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicDeleted", new { EpicId = epicId });
await projectHubContext.Clients.Group(projectGroupName).SendAsync("EpicDeleted", new { EpicId = epicId });
}
// Story notifications
@@ -95,28 +85,28 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying story {StoryId} created in epic {EpicId}", storyId, epicId);
logger.LogInformation("Notifying story {StoryId} created in epic {EpicId}", storyId, epicId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryCreated", story);
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("StoryCreated", story);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryCreated", story);
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("StoryCreated", story);
}
public async Task NotifyStoryUpdated(Guid tenantId, Guid projectId, Guid epicId, Guid storyId, object story)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying story {StoryId} updated", storyId);
logger.LogInformation("Notifying story {StoryId} updated", storyId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryUpdated", story);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryUpdated", story);
}
public async Task NotifyStoryDeleted(Guid tenantId, Guid projectId, Guid epicId, Guid storyId)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying story {StoryId} deleted", storyId);
logger.LogInformation("Notifying story {StoryId} deleted", storyId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryDeleted", new { StoryId = storyId });
await projectHubContext.Clients.Group(projectGroupName).SendAsync("StoryDeleted", new { StoryId = storyId });
}
// Task notifications
@@ -125,37 +115,37 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying task {TaskId} created in story {StoryId}", taskId, storyId);
logger.LogInformation("Notifying task {TaskId} created in story {StoryId}", taskId, storyId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskCreated", task);
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("TaskCreated", task);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskCreated", task);
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("TaskCreated", task);
}
public async Task NotifyTaskUpdated(Guid tenantId, Guid projectId, Guid storyId, Guid taskId, object task)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying task {TaskId} updated", taskId);
logger.LogInformation("Notifying task {TaskId} updated", taskId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskUpdated", task);
await projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskUpdated", task);
}
public async Task NotifyTaskDeleted(Guid tenantId, Guid projectId, Guid storyId, Guid taskId)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying task {TaskId} deleted", taskId);
logger.LogInformation("Notifying task {TaskId} deleted", taskId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskDeleted", new { TaskId = taskId });
await projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskDeleted", new { TaskId = taskId });
}
public async Task NotifyTaskAssigned(Guid tenantId, Guid projectId, Guid taskId, Guid assigneeId)
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying task {TaskId} assigned to {AssigneeId}", taskId, assigneeId);
logger.LogInformation("Notifying task {TaskId} assigned to {AssigneeId}", taskId, assigneeId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskAssigned", new
await projectHubContext.Clients.Group(projectGroupName).SendAsync("TaskAssigned", new
{
TaskId = taskId,
AssigneeId = assigneeId,
@@ -167,21 +157,21 @@ public class RealtimeNotificationService : IRealtimeNotificationService
{
var groupName = $"project-{projectId}";
await _projectHubContext.Clients.Group(groupName).SendAsync("IssueCreated", issue);
await projectHubContext.Clients.Group(groupName).SendAsync("IssueCreated", issue);
}
public async Task NotifyIssueUpdated(Guid tenantId, Guid projectId, object issue)
{
var groupName = $"project-{projectId}";
await _projectHubContext.Clients.Group(groupName).SendAsync("IssueUpdated", issue);
await projectHubContext.Clients.Group(groupName).SendAsync("IssueUpdated", issue);
}
public async Task NotifyIssueDeleted(Guid tenantId, Guid projectId, Guid issueId)
{
var groupName = $"project-{projectId}";
await _projectHubContext.Clients.Group(groupName).SendAsync("IssueDeleted", new { IssueId = issueId });
await projectHubContext.Clients.Group(groupName).SendAsync("IssueDeleted", new { IssueId = issueId });
}
public async Task NotifyIssueStatusChanged(
@@ -193,7 +183,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
{
var groupName = $"project-{projectId}";
await _projectHubContext.Clients.Group(groupName).SendAsync("IssueStatusChanged", new
await projectHubContext.Clients.Group(groupName).SendAsync("IssueStatusChanged", new
{
IssueId = issueId,
OldStatus = oldStatus,
@@ -208,9 +198,9 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying sprint {SprintId} created in project {ProjectId}", sprintId, projectId);
logger.LogInformation("Notifying sprint {SprintId} created in project {ProjectId}", sprintId, projectId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintCreated", new
await projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintCreated", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -218,7 +208,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
Timestamp = DateTime.UtcNow
});
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintCreated", new
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintCreated", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -231,9 +221,9 @@ public class RealtimeNotificationService : IRealtimeNotificationService
{
var projectGroupName = $"project-{projectId}";
_logger.LogInformation("Notifying sprint {SprintId} updated", sprintId);
logger.LogInformation("Notifying sprint {SprintId} updated", sprintId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintUpdated", new
await projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintUpdated", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -247,9 +237,9 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying sprint {SprintId} started", sprintId);
logger.LogInformation("Notifying sprint {SprintId} started", sprintId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintStarted", new
await projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintStarted", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -257,7 +247,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
Timestamp = DateTime.UtcNow
});
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintStarted", new
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintStarted", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -271,9 +261,9 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying sprint {SprintId} completed", sprintId);
logger.LogInformation("Notifying sprint {SprintId} completed", sprintId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintCompleted", new
await projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintCompleted", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -281,7 +271,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
Timestamp = DateTime.UtcNow
});
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintCompleted", new
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintCompleted", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -295,9 +285,9 @@ public class RealtimeNotificationService : IRealtimeNotificationService
var projectGroupName = $"project-{projectId}";
var tenantGroupName = $"tenant-{tenantId}";
_logger.LogInformation("Notifying sprint {SprintId} deleted", sprintId);
logger.LogInformation("Notifying sprint {SprintId} deleted", sprintId);
await _projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintDeleted", new
await projectHubContext.Clients.Group(projectGroupName).SendAsync("SprintDeleted", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -305,7 +295,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
Timestamp = DateTime.UtcNow
});
await _projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintDeleted", new
await projectHubContext.Clients.Group(tenantGroupName).SendAsync("SprintDeleted", new
{
SprintId = sprintId,
SprintName = sprintName,
@@ -318,7 +308,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
{
var userConnectionId = $"user-{userId}";
await _notificationHubContext.Clients.User(userId.ToString()).SendAsync("Notification", new
await notificationHubContext.Clients.User(userId.ToString()).SendAsync("Notification", new
{
Message = message,
Type = type,
@@ -330,7 +320,7 @@ public class RealtimeNotificationService : IRealtimeNotificationService
{
var groupName = $"tenant-{tenantId}";
await _notificationHubContext.Clients.Group(groupName).SendAsync("Notification", new
await notificationHubContext.Clients.Group(groupName).SendAsync("Notification", new
{
Message = message,
Type = type,