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; }