This commit implements a complete rebranding of the project: - Updated all namespaces from `DocumentOperator` to `DocumentService`. - Renamed file paths, embedded resources, and test data references. - Updated configuration keys, logging paths, and Redis instance names. - Revised documentation to reflect the new project name. - Modified project and solution files to align with the new structure. - Updated class names, DTOs, commands, queries, and handlers. - Adjusted middleware, controllers, and API endpoints. - Updated Swagger metadata and API titles to `DocumentService API`. - Refactored test namespaces, resource paths, and embedded resources. - Updated build and deployment configurations for the new name. - Replaced all references to `DocumentOperator` in comments and literals. These changes ensure consistency across the codebase and documentation.
79 lines
2.7 KiB
C#
79 lines
2.7 KiB
C#
using DocumentService.Application.Common.Interfaces;
|
|
using DocumentService.Domain.Models.ValueObjects;
|
|
using FluentValidation;
|
|
using MediatR;
|
|
|
|
namespace DocumentService.Application.AddAnnotation;
|
|
|
|
/// <summary>
|
|
/// Command to add an annotation to a PDF document.
|
|
/// </summary>
|
|
public record AddAnnotationCommand : IRequest<byte[]>
|
|
{
|
|
public required Stream PdfStream { get; init; }
|
|
public required AnnotationType AnnotationType { get; init; }
|
|
public required int PageNumber { get; init; }
|
|
public required (double X1, double Y1, double X2, double Y2) Rectangle { get; init; }
|
|
public string? Content { get; init; }
|
|
public string? Author { get; init; }
|
|
public string? Color { get; init; }
|
|
public TextMarkupStyle? TextMarkupStyle { get; init; }
|
|
public AnnotationOrigin Origin { get; init; } = AnnotationOrigin.BottomLeft;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handler for AddAnnotationCommand.
|
|
/// </summary>
|
|
public class AddAnnotationHandler(IPdfProcessor pdfProcessor) : IRequestHandler<AddAnnotationCommand, byte[]>
|
|
{
|
|
public async Task<byte[]> Handle(AddAnnotationCommand request, CancellationToken cancellationToken)
|
|
{
|
|
return await pdfProcessor.AddAnnotationAsync(
|
|
request.PdfStream,
|
|
request.AnnotationType,
|
|
request.PageNumber,
|
|
request.Rectangle,
|
|
request.Content,
|
|
request.Author,
|
|
request.Color,
|
|
request.TextMarkupStyle,
|
|
request.Origin);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validator for AddAnnotationCommand.
|
|
/// </summary>
|
|
public class AddAnnotationValidator : AbstractValidator<AddAnnotationCommand>
|
|
{
|
|
public AddAnnotationValidator()
|
|
{
|
|
RuleFor(x => x.PdfStream)
|
|
.NotNull()
|
|
.WithMessage("PDF stream is required");
|
|
|
|
RuleFor(x => x.PageNumber)
|
|
.GreaterThan(0)
|
|
.WithMessage("Page number must be greater than 0");
|
|
|
|
RuleFor(x => x.Content)
|
|
.NotEmpty()
|
|
.When(x => x.AnnotationType == AnnotationType.FreeText || x.AnnotationType == AnnotationType.StickyNote)
|
|
.WithMessage("Content is required for FreeText and StickyNote annotations");
|
|
|
|
RuleFor(x => x.TextMarkupStyle)
|
|
.NotNull()
|
|
.When(x => x.AnnotationType == AnnotationType.TextMarkup)
|
|
.WithMessage("TextMarkupStyle is required for TextMarkup annotations");
|
|
|
|
RuleFor(x => x.Color)
|
|
.Matches("^[0-9A-Fa-f]{6}$")
|
|
.When(x => !string.IsNullOrWhiteSpace(x.Color))
|
|
.WithMessage("Color must be a 6-digit hex value (e.g., 'FF0000' for red)");
|
|
|
|
RuleFor(x => x.Rectangle)
|
|
.Must(r => r.X2 > r.X1 && r.Y2 > r.Y1)
|
|
.WithMessage("Rectangle coordinates must define a valid area (X2 > X1 and Y2 > Y1)");
|
|
}
|
|
}
|