Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(graphql): Add missing search parameters for paging and sorting #1671

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public int? Limit
public class SortablePaginationParameter<TOrderDefinition, TTarget> : PaginationParameter<TOrderDefinition, TTarget>
where TOrderDefinition : IOrderDefinition<TTarget>
{
public OrderSet<TOrderDefinition, TTarget>? OrderBy { get; init; } = OrderSet<TOrderDefinition, TTarget>.Default;
public OrderSet<TOrderDefinition, TTarget>? OrderBy { get; set; } = OrderSet<TOrderDefinition, TTarget>.Default;
}

internal sealed class PaginationParameterValidator<TOrderDefinition, TTarget> : AbstractValidator<PaginationParameter<TOrderDefinition, TTarget>>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AutoMapper;
using Digdir.Domain.Dialogporten.Application.Common.Pagination.Order;
using Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Get;
using Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Search;
using Digdir.Domain.Dialogporten.GraphQL.EndUser.DialogById;
Expand Down Expand Up @@ -32,14 +33,42 @@
{
var searchDialogQuery = mapper.Map<SearchDialogQuery>(input);

// Test sending in continuation token, but not order by, and vice versa
OrderSet<SearchDialogQueryOrderDefinition, IntermediateDialogDto>? orderSet = null;
if (input.OrderBy != null && !input.OrderBy.TryToOrderSet(out orderSet))
{
// error
}

searchDialogQuery.OrderBy = orderSet;

var result = await mediator.Send(searchDialogQuery, cancellationToken);

return result.Match(
mapper.Map<SearchDialogsPayload>,
paginatedList =>
{
var mappedResult = mapper.Map<SearchDialogsPayload>(paginatedList);
mappedResult.OrderBy = paginatedList.OrderBy.ToSearchDialogSortTypeList();

Check failure on line 51 in src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs

View workflow job for this annotation

GitHub Actions / build / build-and-test

'string' does not contain a definition for 'ToSearchDialogSortTypeList' and no accessible extension method 'ToSearchDialogSortTypeList' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 51 in src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs

View workflow job for this annotation

GitHub Actions / build / build-and-test

'string' does not contain a definition for 'ToSearchDialogSortTypeList' and no accessible extension method 'ToSearchDialogSortTypeList' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
return mappedResult;
},
validationError => new SearchDialogsPayload
{
Errors = [.. validationError.Errors.Select(x => new SearchDialogValidationError { Message = x.ErrorMessage })]
},
forbidden => new SearchDialogsPayload { Errors = [new SearchDialogForbidden()] });
}
}

[GraphQLDescription("If more than one property is set, is bad.")]
public sealed class SearchDialogSortType
{
public SortDirection? CreatedAt { get; set; }
public SortDirection? UpdatedAt { get; set; }
public SortDirection? DueAt { get; set; }
}

public enum SortDirection
{
ASC,
DESC
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public MappingProfile()
CreateMap<SearchDialogInput, SearchDialogQuery>()
.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status));

CreateMap<PaginatedList<DialogDto>, SearchDialogsPayload>();
CreateMap<PaginatedList<DialogDto>, SearchDialogsPayload>()
.ForMember(dest => dest.OrderBy, opt => opt.Ignore());

CreateMap<ContentDto, SearchContent>();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using System.Globalization;
using System.Text;
using Digdir.Domain.Dialogporten.Application.Common.Pagination.Order;
using Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Search;
using Digdir.Domain.Dialogporten.GraphQL.EndUser.Common;
using Digdir.Domain.Dialogporten.GraphQL.EndUser.MutationTypes;

Expand All @@ -23,8 +27,13 @@ public sealed class SearchDialogsPayload
{
public List<SearchDialog>? Items { get; set; }
public bool HasNextPage { get; set; }

[GraphQLDescription("Use this token to fetch the next page of dialogs, must be used in combination with OrderBy")]
public string? ContinuationToken { get; set; }
public string? OrderBy { get; set; }

[GraphQLDescription("Use this OrderBy to fetch the next page of dialogs, must be used in combination with ContinuationToken")]
public List<SearchDialogSortType> OrderBy { get; set; } = null!;

public List<ISearchDialogError> Errors { get; set; } = [];
}

Expand Down Expand Up @@ -103,6 +112,55 @@ public sealed class SearchDialogInput
[GraphQLDescription("Search string for free text search. Will attempt to fuzzily match in all free text fields in the aggregate")]
public string? Search { get; init; }

[GraphQLDescription("Limit free text search to texts with this language code, e.g. 'no', 'en'. Culture codes will be normalized to neutral language codes (ISO 639). Default: search all culture codes")]
[GraphQLDescription("Limit free text search to texts with this language code, e.g. 'nb', 'en'. Culture codes will be normalized to neutral language codes (ISO 639). Default: search all culture codes")]
public string? SearchLanguageCode { get; init; }

[GraphQLDescription("Limit the number of results returned, defaults to 100, max 1000")]
public int? Limit { get; set; }

[GraphQLDescription("Continuation token for pagination")]
public string? ContinuationToken { get; init; }

[GraphQLDescription("Sort the results by one or more fields")]
public List<SearchDialogSortType>? OrderBy { get; set; }
}


internal static class SearchDialogSortTypeExtensions
{
public static bool TryToOrderSet(this List<SearchDialogSortType> searchDialogSortTypes,
out OrderSet<SearchDialogQueryOrderDefinition, IntermediateDialogDto>? orderSet)
{

var stringBuilder = new StringBuilder();
foreach (var orderBy in searchDialogSortTypes)
{
if (orderBy.CreatedAt != null)
{
stringBuilder.Append(CultureInfo.InvariantCulture, $"createdAt_{orderBy.CreatedAt},");
continue;
}
if (orderBy.UpdatedAt != null)
{
stringBuilder.Append(CultureInfo.InvariantCulture, $"updatedAt_{orderBy.UpdatedAt},");
continue;
}
if (orderBy.DueAt != null)
{
stringBuilder.Append(CultureInfo.InvariantCulture, $"dueAt_{orderBy.DueAt},");
}

}

if (OrderSet<SearchDialogQueryOrderDefinition, IntermediateDialogDto>.TryParse(stringBuilder.ToString(),
out var parsedOrderSet))
{
orderSet = parsedOrderSet;
return true;
}

orderSet = null;
return false;
}

}
Loading