chore: moving towards agentic development
Some checks failed
Backend CI/CD / build_and_deploy (push) Has been cancelled
Frontend CI/CD / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-04-24 21:12:26 -04:00
parent df3e602015
commit b6eb692c27
179 changed files with 2880 additions and 866 deletions

View File

@@ -0,0 +1,105 @@
using Socialize.Infrastructure.Security;
using Socialize.Modules.ContentItems.Data;
using Socialize.Modules.Notifications.Contracts;
namespace Socialize.Modules.ContentItems.Handlers;
public record UpdateContentItemStatusRequest(string Status);
public class UpdateContentItemStatusRequestValidator
: Validator<UpdateContentItemStatusRequest>
{
public UpdateContentItemStatusRequestValidator()
{
RuleFor(x => x.Status).NotEmpty().MaximumLength(64);
}
}
public class UpdateContentItemStatusHandler(
AppDbContext dbContext,
AccessScopeService accessScopeService,
INotificationEventWriter notificationEventWriter)
: Endpoint<UpdateContentItemStatusRequest, ContentItemDetailDto>
{
private static readonly HashSet<string> AllowedStatuses =
[
"Draft",
"In internal review",
"Changes requested internally",
"Internal changes in progress",
"Ready for client review",
"In client review",
"Changes requested by client",
"Client changes in progress",
"Approved",
"Rejected",
"Ready to publish",
"Published",
"Archived",
];
public override void Configure()
{
Post("/api/content-items/{id}/status");
Options(o => o.WithTags("Content Items"));
}
public override async Task HandleAsync(UpdateContentItemStatusRequest request, CancellationToken ct)
{
Guid id = Route<Guid>("id");
ContentItem? item = await dbContext.ContentItems.SingleOrDefaultAsync(candidate => candidate.Id == id, ct);
if (item is null)
{
await SendNotFoundAsync(ct);
return;
}
if (!accessScopeService.CanManageWorkspace(User, item.WorkspaceId))
{
await SendForbiddenAsync(ct);
return;
}
string normalizedStatus = request.Status.Trim();
if (!AllowedStatuses.Contains(normalizedStatus))
{
AddError(request => request.Status, "The requested status is not valid.");
await SendErrorsAsync(StatusCodes.Status400BadRequest, ct);
return;
}
item.Status = normalizedStatus;
await dbContext.SaveChangesAsync(ct);
await notificationEventWriter.WriteAsync(
new NotificationEventWriteModel(
item.WorkspaceId,
item.Id,
"content-item.status.updated",
"ContentItem",
item.Id,
$"Status changed to {item.Status} for {item.Title}.",
User.GetUserId(),
User.GetEmail(),
$$"""{"status":"{{item.Status}}"}"""),
ct);
ContentItemDetailDto dto = new(
item.Id,
item.WorkspaceId,
item.ClientId,
item.ProjectId,
item.Title,
item.PublicationMessage,
item.PublicationTargets,
item.Hashtags,
item.Status,
item.DueDate,
item.CurrentRevisionLabel,
item.CurrentRevisionNumber,
item.CreatedAt);
await SendOkAsync(dto, ct);
}
}