diff --git a/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs b/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs index 20ffc583f..e1603f42b 100644 --- a/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs +++ b/services/Directory/FilterLists.Directory.Api/Controllers/ChangesController.cs @@ -20,9 +20,23 @@ public ChangesController(IMemoryCache cache, IMediator mediator) : base(cache) /// The cancellation token. /// The changes. [HttpGet] - [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] public Task Get(CancellationToken cancellationToken) { return CacheGetOrCreateAsync(() => _mediator.Send(new GetChanges.Query(), cancellationToken)); } + + /// + /// Gets the change. + /// + /// The identifier of the change. + /// The cancellation token. + /// The change. + [HttpGet("{id:long}")] + [ProducesResponseType(typeof(GetChange.ChangeVm), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public Task GetDetails(long id, CancellationToken cancellationToken) + { + return CacheGetOrCreateAsync(() => _mediator.Send(new GetChange.Query(id), cancellationToken), id); + } } diff --git a/services/Directory/FilterLists.Directory.Api/SwaggerConfigurationExtensions.cs b/services/Directory/FilterLists.Directory.Api/SwaggerConfigurationExtensions.cs index c340b60e4..6464af5ab 100644 --- a/services/Directory/FilterLists.Directory.Api/SwaggerConfigurationExtensions.cs +++ b/services/Directory/FilterLists.Directory.Api/SwaggerConfigurationExtensions.cs @@ -26,6 +26,9 @@ public static void AddSwaggerGen(this IServiceCollection services) } }); + // Swagger UI struggles with lookups of nested types represented by concatenated '+' + o.CustomSchemaIds(t => t.FullName?.Replace("+", ".")); + var apiXmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; o.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, apiXmlFile)); diff --git a/services/Directory/FilterLists.Directory.Application/Queries/GetChange.cs b/services/Directory/FilterLists.Directory.Application/Queries/GetChange.cs new file mode 100644 index 000000000..65c2f34da --- /dev/null +++ b/services/Directory/FilterLists.Directory.Application/Queries/GetChange.cs @@ -0,0 +1,63 @@ +using System.Text.Json; +using AutoMapper; +using AutoMapper.QueryableExtensions; +using FilterLists.Directory.Domain.Aggregates; +using FilterLists.Directory.Infrastructure.Persistence.Queries.Context; +using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace FilterLists.Directory.Application.Queries; + +public static class GetChange +{ + public record Query(long Id) : IRequest; + + internal class Handler : IRequestHandler + { + private readonly IQueryContext _context; + private readonly IMapper _mapper; + + public Handler(IQueryContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public Task Handle(Query request, CancellationToken cancellationToken) + { + return _context.Changes + .Where(c => c.Id == request.Id) + .ProjectTo(_mapper.ConfigurationProvider) + .SingleOrDefaultAsync(cancellationToken); + } + } + + internal class ChangesVmProfile : Profile + { + public ChangesVmProfile() + { + CreateMap(); + } + } + + public record ChangeVm + { + public long Id { get; private init; } + public string? Reason { get; private init; } + public DateTime SubmittedAt { get; private init; } + public DateTime? ApprovedAt { get; private init; } + public DateTime? RejectedAt { get; private init; } + public string? RejectedReason { get; private init; } + public JsonDocument? Before { get; private init; } + public JsonDocument? After { get; private init; } + public AggregateType AggregateType { get; private init; } + public long? FilterListId { get; private init; } + public long? LanguageId { get; private init; } + public long? LicenseId { get; private init; } + public long? MaintainerId { get; private init; } + public long? SoftwareId { get; private init; } + public long? SyntaxId { get; private init; } + public long? TagId { get; private init; } + } +} diff --git a/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs b/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs index b83a4f175..4c2fd195e 100644 --- a/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs +++ b/services/Directory/FilterLists.Directory.Application/Queries/GetChanges.cs @@ -11,9 +11,9 @@ namespace FilterLists.Directory.Application.Queries; public static class GetChanges { - public record Query : IRequest>; + public record Query : IRequest>; - internal class Handler : IRequestHandler> + internal class Handler : IRequestHandler> { private readonly IQueryContext _context; private readonly IMapper _mapper; @@ -24,12 +24,12 @@ public Handler(IQueryContext context, IMapper mapper) _mapper = mapper; } - public Task> Handle(Query request, CancellationToken cancellationToken) + public Task> Handle(Query request, CancellationToken cancellationToken) { return _context.Changes .Where(c => c.ApprovedAt == null && c.RejectedAt == null) .OrderBy(c => c.SubmittedAt) - .ProjectTo(_mapper.ConfigurationProvider) + .ProjectTo(_mapper.ConfigurationProvider) .ToListAsync(cancellationToken); } } @@ -38,11 +38,11 @@ internal class ChangesVmProfile : Profile { public ChangesVmProfile() { - CreateMap(); + CreateMap(); } } - public record ChangesVm + public record ChangeVm { public long Id { get; private init; } public string? Reason { get; private init; }