From 0f659087e44c574bc9d5353bc81fc670a212ebdf Mon Sep 17 00:00:00 2001 From: Francis Pion Date: Mon, 7 Oct 2024 13:34:25 -0400 Subject: [PATCH] SearchLanguagesQuery --- .../Languages/LanguageSort.cs | 11 ++++++ .../Languages/LanguageSortOption.cs | 20 +++++++++++ .../Languages/SearchLanguagesPayload.cs | 8 +++++ .../Search/SearchOperator.cs | 7 ++++ .../Search/SearchPayload.cs | 12 +++++++ .../Search/SearchResults.cs | 25 ++++++++++++++ .../Search/SearchTerm.cs | 15 ++++++++ .../Search/SortOption.cs | 17 ++++++++++ .../Search/TextSearch.cs | 17 ++++++++++ .../Languages/ILanguageQuerier.cs | 3 ++ .../Languages/Queries/SearchLanguagesQuery.cs | 22 ++++++++++++ .../SearchLanguagesQueryHandlerTests.cs | 34 +++++++++++++++++++ 12 files changed, 191 insertions(+) create mode 100644 backend/src/Logitar.Cms.Contracts/Languages/LanguageSort.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Languages/LanguageSortOption.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Languages/SearchLanguagesPayload.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Search/SearchOperator.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Search/SearchPayload.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Search/SearchResults.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Search/SearchTerm.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Search/SortOption.cs create mode 100644 backend/src/Logitar.Cms.Contracts/Search/TextSearch.cs create mode 100644 backend/src/Logitar.Cms.Core/Languages/Queries/SearchLanguagesQuery.cs create mode 100644 backend/tests/Logitar.Cms.Core.UnitTests/Languages/Queries/SearchLanguagesQueryHandlerTests.cs diff --git a/backend/src/Logitar.Cms.Contracts/Languages/LanguageSort.cs b/backend/src/Logitar.Cms.Contracts/Languages/LanguageSort.cs new file mode 100644 index 0000000..00db02b --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Languages/LanguageSort.cs @@ -0,0 +1,11 @@ +namespace Logitar.Cms.Contracts.Languages; + +public enum LanguageSort +{ + Code, + CreatedOn, + DisplayName, + EnglishName, + NativeName, + UpdatedOn +} diff --git a/backend/src/Logitar.Cms.Contracts/Languages/LanguageSortOption.cs b/backend/src/Logitar.Cms.Contracts/Languages/LanguageSortOption.cs new file mode 100644 index 0000000..6570e4d --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Languages/LanguageSortOption.cs @@ -0,0 +1,20 @@ +using Logitar.Cms.Contracts.Search; + +namespace Logitar.Cms.Contracts.Languages; + +public record LanguageSortOption : SortOption +{ + public new LanguageSort Field + { + get => Enum.Parse(base.Field); + set => base.Field = value.ToString(); + } + + public LanguageSortOption() : this(LanguageSort.DisplayName) + { + } + + public LanguageSortOption(LanguageSort field, bool isDescending = false) : base(field.ToString(), isDescending) + { + } +} diff --git a/backend/src/Logitar.Cms.Contracts/Languages/SearchLanguagesPayload.cs b/backend/src/Logitar.Cms.Contracts/Languages/SearchLanguagesPayload.cs new file mode 100644 index 0000000..ae7eee6 --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Languages/SearchLanguagesPayload.cs @@ -0,0 +1,8 @@ +using Logitar.Cms.Contracts.Search; + +namespace Logitar.Cms.Contracts.Languages; + +public record SearchLanguagesPayload : SearchPayload +{ + public new List Sort { get; set; } = []; +} diff --git a/backend/src/Logitar.Cms.Contracts/Search/SearchOperator.cs b/backend/src/Logitar.Cms.Contracts/Search/SearchOperator.cs new file mode 100644 index 0000000..0834e6f --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Search/SearchOperator.cs @@ -0,0 +1,7 @@ +namespace Logitar.Cms.Contracts.Search; + +public enum SearchOperator +{ + And = 0, + Or = 1 +} diff --git a/backend/src/Logitar.Cms.Contracts/Search/SearchPayload.cs b/backend/src/Logitar.Cms.Contracts/Search/SearchPayload.cs new file mode 100644 index 0000000..8443c45 --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Search/SearchPayload.cs @@ -0,0 +1,12 @@ +namespace Logitar.Cms.Contracts.Search; + +public record SearchPayload +{ + public List Ids { get; set; } = []; + public TextSearch Search { get; set; } = new(); + + public List Sort { get; set; } = []; + + public int Skip { get; set; } + public int Limit { get; set; } +} diff --git a/backend/src/Logitar.Cms.Contracts/Search/SearchResults.cs b/backend/src/Logitar.Cms.Contracts/Search/SearchResults.cs new file mode 100644 index 0000000..0b07efe --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Search/SearchResults.cs @@ -0,0 +1,25 @@ +namespace Logitar.Cms.Contracts.Search; + +public record SearchResults +{ + public List Items { get; set; } + public long Total { get; set; } + + public SearchResults() : this([]) + { + } + + public SearchResults(IEnumerable items) : this(items, items.LongCount()) + { + } + + public SearchResults(long total) : this([], total) + { + } + + public SearchResults(IEnumerable items, long total) + { + Items = items.ToList(); + Total = total; + } +} diff --git a/backend/src/Logitar.Cms.Contracts/Search/SearchTerm.cs b/backend/src/Logitar.Cms.Contracts/Search/SearchTerm.cs new file mode 100644 index 0000000..58d80d9 --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Search/SearchTerm.cs @@ -0,0 +1,15 @@ +namespace Logitar.Cms.Contracts.Search; + +public record SearchTerm +{ + public string Value { get; set; } + + public SearchTerm() : this(string.Empty) + { + } + + public SearchTerm(string value) + { + Value = value; + } +} diff --git a/backend/src/Logitar.Cms.Contracts/Search/SortOption.cs b/backend/src/Logitar.Cms.Contracts/Search/SortOption.cs new file mode 100644 index 0000000..1181e72 --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Search/SortOption.cs @@ -0,0 +1,17 @@ +namespace Logitar.Cms.Contracts.Search; + +public record SortOption +{ + public string Field { get; set; } + public bool IsDescending { get; set; } + + public SortOption() : this(string.Empty) + { + } + + public SortOption(string field, bool isDescending = false) + { + Field = field; + IsDescending = isDescending; + } +} diff --git a/backend/src/Logitar.Cms.Contracts/Search/TextSearch.cs b/backend/src/Logitar.Cms.Contracts/Search/TextSearch.cs new file mode 100644 index 0000000..bebb32a --- /dev/null +++ b/backend/src/Logitar.Cms.Contracts/Search/TextSearch.cs @@ -0,0 +1,17 @@ +namespace Logitar.Cms.Contracts.Search; + +public record TextSearch +{ + public List Terms { get; set; } + public SearchOperator Operator { get; set; } + + public TextSearch() : this([]) + { + } + + public TextSearch(IEnumerable terms, SearchOperator @operator = SearchOperator.And) + { + Terms = terms.ToList(); + Operator = @operator; + } +} diff --git a/backend/src/Logitar.Cms.Core/Languages/ILanguageQuerier.cs b/backend/src/Logitar.Cms.Core/Languages/ILanguageQuerier.cs index 30099d6..afdbe39 100644 --- a/backend/src/Logitar.Cms.Core/Languages/ILanguageQuerier.cs +++ b/backend/src/Logitar.Cms.Core/Languages/ILanguageQuerier.cs @@ -1,4 +1,5 @@ using Logitar.Cms.Contracts.Languages; +using Logitar.Cms.Contracts.Search; namespace Logitar.Cms.Core.Languages; @@ -11,4 +12,6 @@ public interface ILanguageQuerier Task ReadAsync(Guid id, CancellationToken cancellationToken = default); Task ReadAsync(string locale, CancellationToken cancellationToken = default); Task ReadDefaultAsync(CancellationToken cancellationToken = default); + + Task> SearchAsync(SearchLanguagesPayload payload, CancellationToken cancellationToken = default); } diff --git a/backend/src/Logitar.Cms.Core/Languages/Queries/SearchLanguagesQuery.cs b/backend/src/Logitar.Cms.Core/Languages/Queries/SearchLanguagesQuery.cs new file mode 100644 index 0000000..fccb52e --- /dev/null +++ b/backend/src/Logitar.Cms.Core/Languages/Queries/SearchLanguagesQuery.cs @@ -0,0 +1,22 @@ +using Logitar.Cms.Contracts.Languages; +using Logitar.Cms.Contracts.Search; +using MediatR; + +namespace Logitar.Cms.Core.Languages.Queries; + +public record SearchLanguagesQuery(SearchLanguagesPayload Payload) : IRequest>; + +internal class SearchLanguagesQueryHandler : IRequestHandler> +{ + private readonly ILanguageQuerier _languageQuerier; + + public SearchLanguagesQueryHandler(ILanguageQuerier languageQuerier) + { + _languageQuerier = languageQuerier; + } + + public async Task> Handle(SearchLanguagesQuery query, CancellationToken cancellationToken) + { + return await _languageQuerier.SearchAsync(query.Payload, cancellationToken); + } +} diff --git a/backend/tests/Logitar.Cms.Core.UnitTests/Languages/Queries/SearchLanguagesQueryHandlerTests.cs b/backend/tests/Logitar.Cms.Core.UnitTests/Languages/Queries/SearchLanguagesQueryHandlerTests.cs new file mode 100644 index 0000000..f366dea --- /dev/null +++ b/backend/tests/Logitar.Cms.Core.UnitTests/Languages/Queries/SearchLanguagesQueryHandlerTests.cs @@ -0,0 +1,34 @@ +using Logitar.Cms.Contracts.Languages; +using Logitar.Cms.Contracts.Search; +using Moq; + +namespace Logitar.Cms.Core.Languages.Queries; + +[Trait(Traits.Category, Categories.Unit)] +public class SearchLanguagesQueryHandlerTests +{ + private readonly CancellationToken _cancellationToken = default; + + private readonly Mock _languageQuerier = new(); + + private readonly SearchLanguagesQueryHandler _handler; + + public SearchLanguagesQueryHandlerTests() + { + _handler = new(_languageQuerier.Object); + } + + [Fact(DisplayName = "It should return the correct search results.")] + public async Task It_should_return_the_correct_search_results() + { + SearchLanguagesPayload payload = new(); + + SearchResults results = new(); + _languageQuerier.Setup(x => x.SearchAsync(payload, _cancellationToken)).ReturnsAsync(results); + + SearchLanguagesQuery query = new(payload); + + SearchResults searchResults = await _handler.Handle(query, _cancellationToken); + Assert.Same(results, searchResults); + } +}