Fixed up the relation management api endpoints to use guids and paging (#14706)
* Fixed up the relation management api endpoints to use guids and paging * Cleanup * Updated OpenApi.json
This commit is contained in:
@@ -6,6 +6,8 @@ using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Api.Management.Factories;
|
||||
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Relation;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.Relation;
|
||||
@@ -24,31 +26,25 @@ public class ByChildRelationController : RelationControllerBase
|
||||
_relationPresentationFactory = relationPresentationFactory;
|
||||
}
|
||||
|
||||
[HttpGet("child-relation/{childId:int}")]
|
||||
/// <summary>
|
||||
/// Gets a paged list of relations by the unique relation child keys.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use case: When you wanna restore a deleted item, this is used to find the old location
|
||||
/// </remarks>
|
||||
[HttpGet("child-relation/{childId:guid}")]
|
||||
[MapToApiVersion("1.0")]
|
||||
[ProducesResponseType(typeof(PagedViewModel<RelationResponseModel>), StatusCodes.Status200OK)]
|
||||
public async Task<PagedViewModel<RelationResponseModel>> ByChild(int childId, int skip = 0, int take = 100, string? relationTypeAlias = "")
|
||||
public async Task<IActionResult> ByChild(Guid childId, int skip = 0, int take = 100, string? relationTypeAlias = "")
|
||||
{
|
||||
IRelation[] relations = _relationService.GetByChildId(childId).ToArray();
|
||||
RelationResponseModel[] result = Array.Empty<RelationResponseModel>();
|
||||
PagedModel<IRelation> relationsAttempt = await _relationService.GetPagedByChildKeyAsync(childId, skip, take, relationTypeAlias);
|
||||
|
||||
if (relations.Any())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(relationTypeAlias) == false)
|
||||
{
|
||||
result = _relationPresentationFactory.CreateMultiple(relations.Where(x =>
|
||||
x.RelationType.Alias.InvariantEquals(relationTypeAlias))).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = _relationPresentationFactory.CreateMultiple(relations).ToArray();
|
||||
}
|
||||
}
|
||||
IEnumerable<RelationResponseModel> mappedRelations = relationsAttempt.Items.Select(_relationPresentationFactory.Create);
|
||||
|
||||
return await Task.FromResult(new PagedViewModel<RelationResponseModel>
|
||||
return await Task.FromResult(Ok(new PagedViewModel<RelationResponseModel>
|
||||
{
|
||||
Total = result.Length,
|
||||
Items = result.Skip(skip).Take(take),
|
||||
});
|
||||
Total = relationsAttempt.Total,
|
||||
Items = mappedRelations,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Api.Management.Factories;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Relation;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.Relation;
|
||||
|
||||
[ApiVersion("1.0")]
|
||||
public class ByIdRelationController : RelationControllerBase
|
||||
{
|
||||
private readonly IRelationService _relationService;
|
||||
private readonly IRelationPresentationFactory _relationPresentationFactory;
|
||||
|
||||
public ByIdRelationController(IRelationService relationService, IRelationPresentationFactory relationPresentationFactory)
|
||||
{
|
||||
_relationService = relationService;
|
||||
_relationPresentationFactory = relationPresentationFactory;
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
[MapToApiVersion("1.0")]
|
||||
[ProducesResponseType(typeof(RelationResponseModel), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> ById(int id)
|
||||
{
|
||||
IRelation? relation = _relationService.GetById(id);
|
||||
if (relation is null)
|
||||
{
|
||||
return RelationNotFound();
|
||||
}
|
||||
|
||||
return await Task.FromResult(Ok(_relationPresentationFactory.Create(relation)));
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,19 @@ public class ByRelationTypeKeyRelationController : RelationControllerBase
|
||||
_relationPresentationFactory = relationPresentationFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a paged list of relations by the unique relation key.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use case: On a relation type page you can see all created relations of this type.
|
||||
/// </remarks>
|
||||
[HttpGet("type/{id:guid}")]
|
||||
[MapToApiVersion("1.0")]
|
||||
[ProducesResponseType(typeof(PagedViewModel<RelationResponseModel>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(PagedViewModel<ProblemDetails>), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> ByRelationTypeKey(Guid id, int skip = 0, int take = 100)
|
||||
{
|
||||
Attempt<PagedModel<IRelation>, RelationOperationStatus> relationsAttempt = await _relationService.GetPagedByRelationTypeKey(id, skip, take);
|
||||
Attempt<PagedModel<IRelation>, RelationOperationStatus> relationsAttempt = await _relationService.GetPagedByRelationTypeKeyAsync(id, skip, take);
|
||||
|
||||
if (relationsAttempt.Success is false)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Api.Management.Factories;
|
||||
using Umbraco.Cms.Api.Management.Mapping.Relation;
|
||||
using Umbraco.Cms.Api.Management.Mapping.TrackedReferences;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
@@ -16,8 +15,7 @@ internal static class TrackedReferencesBuilderExtensions
|
||||
|
||||
builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
|
||||
.Add<TrackedReferenceViewModelsMapDefinition>()
|
||||
.Add<RelationModelMapDefinition>()
|
||||
.Add<RelationViewModelsMapDefinition>();
|
||||
.Add<RelationModelMapDefinition>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -9,17 +9,26 @@ namespace Umbraco.Cms.Api.Management.Factories;
|
||||
public class RelationPresentationFactory : IRelationPresentationFactory
|
||||
{
|
||||
private readonly IRelationService _relationService;
|
||||
private readonly IUmbracoMapper _umbracoMapper;
|
||||
private readonly IEntityService _entityService;
|
||||
|
||||
public RelationPresentationFactory(IRelationService relationService, IUmbracoMapper umbracoMapper)
|
||||
public RelationPresentationFactory(IRelationService relationService, IEntityService entityService)
|
||||
{
|
||||
_relationService = relationService;
|
||||
_umbracoMapper = umbracoMapper;
|
||||
_entityService = entityService;
|
||||
}
|
||||
|
||||
public RelationResponseModel Create(IRelation relation)
|
||||
{
|
||||
RelationResponseModel relationResponseModel = _umbracoMapper.Map<RelationResponseModel>(relation)!;
|
||||
var child = _entityService.Get(relation.ChildId)!;
|
||||
var parent = _entityService.Get(relation.ParentId)!;
|
||||
|
||||
RelationResponseModel relationResponseModel = new RelationResponseModel()
|
||||
{
|
||||
ChildId = child.Key,
|
||||
Comment = relation.Comment,
|
||||
CreateDate = relation.CreateDate,
|
||||
ParentId = parent.Key,
|
||||
};
|
||||
Tuple<IUmbracoEntity, IUmbracoEntity>? entities = _relationService.GetEntitiesFromRelation(relation);
|
||||
|
||||
if (entities is not null)
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Relation;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Mapping.Relation;
|
||||
|
||||
public class RelationViewModelsMapDefinition : IMapDefinition
|
||||
{
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<IRelation, RelationResponseModel>((source, context) => new RelationResponseModel(), Map);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll -ParentName -ChildName
|
||||
private void Map(IRelation source, RelationResponseModel target, MapperContext context)
|
||||
{
|
||||
target.ChildId = source.ChildId;
|
||||
target.Comment = source.Comment;
|
||||
target.CreateDate = source.CreateDate;
|
||||
target.ParentId = source.ParentId;
|
||||
}
|
||||
}
|
||||
@@ -11407,84 +11407,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/umbraco/management/api/v1/relation/{id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Relation"
|
||||
],
|
||||
"operationId": "GetRelationById",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/RelationResponseModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"text/json": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/RelationResponseModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"text/plain": {
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/RelationResponseModel"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
},
|
||||
"text/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
},
|
||||
"text/plain": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"Backoffice User": [ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/umbraco/management/api/v1/relation/child-relation/{childId}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -11497,8 +11419,8 @@
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -21091,16 +21013,16 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parentId": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"parentName": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"childId": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"childName": {
|
||||
"type": "string",
|
||||
|
||||
@@ -9,7 +9,7 @@ public class RelationResponseModel
|
||||
/// Gets or sets the Parent Id of the Relation (Source).
|
||||
/// </summary>
|
||||
[ReadOnly(true)]
|
||||
public int ParentId { get; set; }
|
||||
public Guid ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Parent Name of the relation (Source).
|
||||
@@ -21,7 +21,7 @@ public class RelationResponseModel
|
||||
/// Gets or sets the Child Id of the Relation (Destination).
|
||||
/// </summary>
|
||||
[ReadOnly(true)]
|
||||
public int ChildId { get; set; }
|
||||
public Guid ChildId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Child Name of the relation (Destination).
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
namespace Umbraco.Cms.Core.Persistence.Repositories;
|
||||
|
||||
@@ -33,4 +34,5 @@ public interface IRelationRepository : IReadWriteQueryRepository<int, IRelation>
|
||||
IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildId(int childId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes);
|
||||
|
||||
IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes);
|
||||
Task<PagedModel<IRelation>> GetPagedByChildKeyAsync(Guid childKey, int skip, int take, string? relationTypeAlias);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ public interface IRelationService : IService
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="ordering"></param>
|
||||
/// <returns></returns>
|
||||
Task<Attempt<PagedModel<IRelation>, RelationOperationStatus>> GetPagedByRelationTypeKey(Guid key, int skip, int take, Ordering? ordering = null);
|
||||
Task<Attempt<PagedModel<IRelation>, RelationOperationStatus>> GetPagedByRelationTypeKeyAsync(Guid key, int skip, int take, Ordering? ordering = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Child object from a Relation as an <see cref="IUmbracoEntity" />
|
||||
@@ -392,4 +392,6 @@ public interface IRelationService : IService
|
||||
/// </summary>
|
||||
/// <returns>All of the allowed <see cref="UmbracoObjectTypes"/>.</returns>
|
||||
IEnumerable<UmbracoObjectTypes> GetAllowedObjectTypes();
|
||||
|
||||
Task<PagedModel<IRelation>> GetPagedByChildKeyAsync(Guid childKey, int skip, int take, string? relationTypeAlias);
|
||||
}
|
||||
|
||||
@@ -273,7 +273,15 @@ public class RelationService : RepositoryService, IRelationService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Attempt<PagedModel<IRelation>, RelationOperationStatus>> GetPagedByRelationTypeKey(Guid key, int skip, int take, Ordering? ordering = null)
|
||||
public async Task<PagedModel<IRelation>> GetPagedByChildKeyAsync(Guid childKey, int skip, int take, string? relationTypeAlias)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
return await _relationRepository.GetPagedByChildKeyAsync(childKey, skip, take, relationTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Attempt<PagedModel<IRelation>, RelationOperationStatus>> GetPagedByRelationTypeKeyAsync(Guid key, int skip, int take, Ordering? ordering = null)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Factories;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Querying;
|
||||
@@ -38,6 +39,27 @@ internal class RelationRepository : EntityRepositoryBase<int, IRelation>, IRelat
|
||||
public IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes)
|
||||
=> GetPagedChildEntitiesByParentId(parentId, pageIndex, pageSize, out totalRecords, new int[0], entityTypes);
|
||||
|
||||
public Task<PagedModel<IRelation>> GetPagedByChildKeyAsync(Guid childKey, int skip, int take, string? relationTypeAlias)
|
||||
{
|
||||
Sql<ISqlContext> sql = GetBaseQuery(false);
|
||||
|
||||
if (string.IsNullOrEmpty(relationTypeAlias) is false)
|
||||
{
|
||||
|
||||
sql = sql.InnerJoin<RelationTypeDto>().On<RelationDto, RelationTypeDto>(umbracoRelation => umbracoRelation.RelationType, rt => rt.Id)
|
||||
.Where<RelationTypeDto>(rt => rt.Alias == relationTypeAlias);
|
||||
}
|
||||
sql = sql.Where<NodeDto>(n => n.UniqueId == childKey, "uchild"); // "uchild" comes from the base query
|
||||
|
||||
|
||||
RelationDto[] pagedResult =
|
||||
Database.SkipTake<RelationDto>(skip, take, sql).ToArray();
|
||||
var totalRecords = Database.Count(sql);
|
||||
|
||||
return Task.FromResult(new PagedModel<IRelation>(totalRecords, DtosToEntities(pagedResult)));
|
||||
|
||||
}
|
||||
|
||||
public void Save(IEnumerable<IRelation> relations)
|
||||
{
|
||||
foreach (IGrouping<bool, IRelation> hasIdentityGroup in relations.GroupBy(r => r.HasIdentity))
|
||||
|
||||
Reference in New Issue
Block a user