feat: ship agent-first mission control v0.2.57
CI - Build & Test / Backend (.NET) (push) Successful in 42s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 2m46s
CI - Build & Test / Security Check (push) Successful in 3s
CI - Build & Test / Deploy Nexus (push) Successful in 56s

This commit is contained in:
AzuTear
2026-07-31 22:39:47 +02:00
parent 3bc7622977
commit f5552218bc
535 changed files with 95242 additions and 8791 deletions
+41 -8
View File
@@ -19,7 +19,7 @@ public class NotificationsController(INotificationService notificationService) :
CancellationToken ct = default)
{
var notifications = await notificationService.GetForUserAsync(forUser, limit, unreadOnly, ct);
return Ok(notifications.Select(MapToDto).ToList());
return Ok(notifications.Select(notification => MapToDto(notification)).ToList());
}
[HttpGet("unread-count")]
@@ -42,22 +42,55 @@ public class NotificationsController(INotificationService notificationService) :
}
[HttpPatch("{id:guid}/read")]
public async Task<ActionResult> MarkAsRead(Guid id, CancellationToken ct = default)
[ProducesResponseType(typeof(NotificationDto), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<ActionResult<NotificationDto>> MarkAsRead(
Guid id,
CancellationToken ct = default)
{
var ok = await notificationService.MarkAsReadAsync(id, ct);
return ok ? NoContent() : NotFound(new { error = "Notification not found." });
var readResult = await notificationService.MarkAsReadAsync(id, ct);
var notification = readResult.Notification;
if (notification is null)
return NotFound(new ProblemDetails
{
Title = "Notification not found",
Detail = $"Notification '{id}' does not exist.",
Status = StatusCodes.Status404NotFound
});
var primary = new EntityRefDto(
"notification",
notification.Id.ToString(),
notification.Title);
var affected = notification.TaskId is { } taskId
? new[] { new EntityRefDto("task", taskId.ToString()) }
: [];
var operation = OperationResultFactory.FromHttpContext(
HttpContext,
readResult.Changed ? "completed" : "noop",
primary,
revision: readResult.Changed ? 1 : 0,
affectedRefs: affected);
return Ok(MapToDto(notification, operation));
}
[HttpPatch("read-all")]
public async Task<ActionResult> MarkAllAsRead(
[ProducesResponseType(typeof(NotificationReadAllResultDto), StatusCodes.Status200OK)]
public async Task<ActionResult<NotificationReadAllResultDto>> MarkAllAsRead(
[FromQuery] string forUser = "bao",
CancellationToken ct = default)
{
var count = await notificationService.MarkAllAsReadAsync(forUser, ct);
return Ok(new { marked = count });
var operation = OperationResultFactory.FromHttpContext(
HttpContext,
count > 0 ? "completed" : "noop",
new EntityRefDto("notification", "*", "Benachrichtigungen"));
return Ok(new NotificationReadAllResultDto(count, operation));
}
private static NotificationDto MapToDto(Notification n) => new(
private static NotificationDto MapToDto(
Notification n,
OperationResultDto? operation = null) => new(
n.Id, n.Type, n.Title, n.Message,
n.ForUser, n.TaskId, n.IsRead, n.CreatedAt);
n.ForUser, n.TaskId, n.IsRead, n.CreatedAt, operation);
}