From 0f1e7f64ff1faae16dcc9fd21f79c2b31652065c Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:39:02 +0200 Subject: [PATCH] New backoffice: Tag controller (#14072) * Implement ByQueryEndpoint * Implement new async methods on tag service * dont have nullable query * Formatting * Add default implementation to interface * Allow nullable query in api --------- Co-authored-by: Zeegaan Co-authored-by: Nikolaj --- .../Controllers/Tag/ByQueryTagController.cs | 39 +++++++++++++++++++ .../Controllers/Tag/TagControllerBase.cs | 12 ++++++ .../TagBuilderExtensions.cs | 16 ++++++++ .../ManagementApiComposer.cs | 1 + .../Tag/TagResponseModelMapDefinition.cs | 20 ++++++++++ .../ViewModels/Tag/TagResponseModel.cs | 12 ++++++ src/Umbraco.Core/Services/ITagService.cs | 14 +++++++ src/Umbraco.Core/Services/TagService.cs | 13 +++++++ 8 files changed, 127 insertions(+) create mode 100644 src/Umbraco.Cms.Api.Management/Controllers/Tag/ByQueryTagController.cs create mode 100644 src/Umbraco.Cms.Api.Management/Controllers/Tag/TagControllerBase.cs create mode 100644 src/Umbraco.Cms.Api.Management/DependencyInjection/TagBuilderExtensions.cs create mode 100644 src/Umbraco.Cms.Api.Management/Mapping/Tag/TagResponseModelMapDefinition.cs create mode 100644 src/Umbraco.Cms.Api.Management/ViewModels/Tag/TagResponseModel.cs diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Tag/ByQueryTagController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Tag/ByQueryTagController.cs new file mode 100644 index 0000000000..924397447e --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/Tag/ByQueryTagController.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Common.ViewModels.Pagination; +using Umbraco.Cms.Api.Management.ViewModels.Tag; +using Umbraco.Cms.Core.Mapping; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Services; + +namespace Umbraco.Cms.Api.Management.Controllers.Tag; + +public class ByQueryTagController : TagControllerBase +{ + private readonly ITagService _tagService; + private readonly IUmbracoMapper _mapper; + + public ByQueryTagController(ITagService tagService, IUmbracoMapper mapper) + { + _tagService = tagService; + _mapper = mapper; + } + + [HttpGet] + [MapToApiVersion("1.0")] + [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)] + public async Task>> ByQuery(string? query, string? tagGroup, string? culture, int skip = 0, int take = 100) + { + IEnumerable result = await _tagService.GetByQueryAsync(query ?? string.Empty, tagGroup, culture); + + List responseModels = _mapper.MapEnumerable(result); + + var pagedViewModel = new PagedViewModel + { + Items = responseModels.Skip(skip).Take(take), + Total = responseModels.Count, + }; + + return await Task.FromResult(Ok(pagedViewModel)); + } +} diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Tag/TagControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/Tag/TagControllerBase.cs new file mode 100644 index 0000000000..b5a5b0ffe4 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Controllers/Tag/TagControllerBase.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Api.Management.Routing; + +namespace Umbraco.Cms.Api.Management.Controllers.Tag; + +[ApiController] +[VersionedApiBackOfficeRoute("tag")] +[ApiExplorerSettings(GroupName = "Tag")] +[ApiVersion("1.0")] +public class TagControllerBase : ManagementApiControllerBase +{ +} diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/TagBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/TagBuilderExtensions.cs new file mode 100644 index 0000000000..1d043c1ea2 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/TagBuilderExtensions.cs @@ -0,0 +1,16 @@ +using Umbraco.Cms.Api.Management.Mapping.Tag; +using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Mapping; + +namespace Umbraco.Cms.Api.Management.DependencyInjection; + +public static class TagBuilderExtensions +{ + internal static IUmbracoBuilder AddTags(this IUmbracoBuilder builder) + { + builder.WithCollectionBuilder() + .Add(); + + return builder; + } +} diff --git a/src/Umbraco.Cms.Api.Management/ManagementApiComposer.cs b/src/Umbraco.Cms.Api.Management/ManagementApiComposer.cs index 21155f25b2..d62d8028af 100644 --- a/src/Umbraco.Cms.Api.Management/ManagementApiComposer.cs +++ b/src/Umbraco.Cms.Api.Management/ManagementApiComposer.cs @@ -35,6 +35,7 @@ public class ManagementApiComposer : IComposer .AddHealthChecks() .AddModelsBuilder() .AddRedirectUrl() + .AddTags() .AddTrackedReferences() .AddTemporaryFiles() .AddDataTypes() diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Tag/TagResponseModelMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/Tag/TagResponseModelMapDefinition.cs new file mode 100644 index 0000000000..b72d9da00a --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Mapping/Tag/TagResponseModelMapDefinition.cs @@ -0,0 +1,20 @@ +using Umbraco.Cms.Api.Management.ViewModels.Tag; +using Umbraco.Cms.Core.Mapping; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Api.Management.Mapping.Tag; + +public class TagResponseModelMapDefinition : IMapDefinition +{ + public void DefineMaps(IUmbracoMapper mapper) => + mapper.Define((_, _) => new TagResponseModel(), Map); + + // Umbraco.Code.MapAll + private void Map(ITag source, TagResponseModel target, MapperContext context) + { + target.Group = source.Group; + target.Id = source.Key; + target.NodeCount = source.NodeCount; + target.Text = source.Text; + } +} diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/Tag/TagResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/Tag/TagResponseModel.cs new file mode 100644 index 0000000000..78b72936cc --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/Tag/TagResponseModel.cs @@ -0,0 +1,12 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.Tag; + +public class TagResponseModel +{ + public Guid Id { get; set; } + + public string? Text { get; set; } + + public string? Group { get; set; } + + public int NodeCount { get; set; } +} diff --git a/src/Umbraco.Core/Services/ITagService.cs b/src/Umbraco.Core/Services/ITagService.cs index 5e2f164a35..db2e841f29 100644 --- a/src/Umbraco.Core/Services/ITagService.cs +++ b/src/Umbraco.Core/Services/ITagService.cs @@ -1,4 +1,5 @@ using Umbraco.Cms.Core.Models; +using Umbraco.Extensions; namespace Umbraco.Cms.Core.Services; @@ -58,6 +59,19 @@ public interface ITagService : IService /// IEnumerable GetAllTags(string? group = null, string? culture = null); + Task> GetAllAsync(string? group = null, string? culture = null) + { + if (culture == string.Empty) + { + culture = null; + } + + return Task.FromResult(GetAllTags(group, culture)); + } + + Task> GetByQueryAsync(string query, string? group = null, string? culture = null) + => Task.FromResult(GetAllAsync(group, culture).GetAwaiter().GetResult().Where(x => x.Text.InvariantContains(query))); + /// /// Gets all document tags. /// diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index c75863f6de..d88af65d6b 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -3,6 +3,7 @@ using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; +using Umbraco.Extensions; namespace Umbraco.Cms.Core.Services; @@ -102,6 +103,18 @@ public class TagService : RepositoryService, ITagService } } + public Task> GetAllAsync(string? group = null, string? culture = null) + { + if (culture == string.Empty) + { + culture = null; + } + + return Task.FromResult(GetAllTags(group, culture)); + } + + public async Task> GetByQueryAsync(string query, string? group = null, string? culture = null) => (await GetAllAsync(group, culture)).Where(x => x.Text.InvariantContains(query)); + /// public IEnumerable GetAllContentTags(string? group = null, string? culture = null) {