Updated management API endpoint and model for data type references to align with that used for documents, media etc. (#18905)
* Updated management API endpoint and model for data type references to align with that used for documents, media etc. * Refactoring. * Update src/Umbraco.Core/Constants-ReferenceTypes.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fixed typos. * Added id to tracked reference content type response. * Updated OpenApi.json. * Added missing updates. * Renamed model and constants from code review feedback. * Fix typo * Fix multiple enumeration --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: mole <nikolajlauridsen@protonmail.ch>
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
using Asp.Versioning;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
|
||||||
|
using Umbraco.Cms.Api.Management.Factories;
|
||||||
|
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
||||||
|
using Umbraco.Cms.Core.Models;
|
||||||
|
using Umbraco.Cms.Core.Services;
|
||||||
|
|
||||||
|
namespace Umbraco.Cms.Api.Management.Controllers.DataType.References;
|
||||||
|
|
||||||
|
[ApiVersion("1.0")]
|
||||||
|
public class ReferencedByDataTypeController : DataTypeControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDataTypeService _dataTypeService;
|
||||||
|
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;
|
||||||
|
|
||||||
|
public ReferencedByDataTypeController(IDataTypeService dataTypeService, IRelationTypePresentationFactory relationTypePresentationFactory)
|
||||||
|
{
|
||||||
|
_dataTypeService = dataTypeService;
|
||||||
|
_relationTypePresentationFactory = relationTypePresentationFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a paged list of references for the current data type, so you can see where it is being used.
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{id:guid}/referenced-by")]
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[ProducesResponseType(typeof(PagedViewModel<IReferenceResponseModel>), StatusCodes.Status200OK)]
|
||||||
|
public async Task<ActionResult<PagedViewModel<IReferenceResponseModel>>> ReferencedBy(
|
||||||
|
CancellationToken cancellationToken,
|
||||||
|
Guid id,
|
||||||
|
int skip = 0,
|
||||||
|
int take = 20)
|
||||||
|
{
|
||||||
|
PagedModel<RelationItemModel> relationItems = await _dataTypeService.GetPagedRelationsAsync(id, skip, take);
|
||||||
|
|
||||||
|
var pagedViewModel = new PagedViewModel<IReferenceResponseModel>
|
||||||
|
{
|
||||||
|
Total = relationItems.Total,
|
||||||
|
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
|
||||||
|
};
|
||||||
|
|
||||||
|
return pagedViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Umbraco.Cms.Api.Management.Factories;
|
using Umbraco.Cms.Api.Management.Factories;
|
||||||
@@ -10,6 +10,7 @@ using Umbraco.Cms.Core.Services.OperationStatus;
|
|||||||
namespace Umbraco.Cms.Api.Management.Controllers.DataType;
|
namespace Umbraco.Cms.Api.Management.Controllers.DataType;
|
||||||
|
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0")]
|
||||||
|
[Obsolete("Please use ReferencedByDataTypeController and the referenced-by endpoint. Scheduled for removal in Umbraco 17.")]
|
||||||
public class ReferencesDataTypeController : DataTypeControllerBase
|
public class ReferencesDataTypeController : DataTypeControllerBase
|
||||||
{
|
{
|
||||||
private readonly IDataTypeService _dataTypeService;
|
private readonly IDataTypeService _dataTypeService;
|
||||||
|
|||||||
@@ -56,9 +56,12 @@ public class RelationTypePresentationFactory : IRelationTypePresentationFactory
|
|||||||
IReferenceResponseModel[] result = relationItemModelsCollection.Select(relationItemModel =>
|
IReferenceResponseModel[] result = relationItemModelsCollection.Select(relationItemModel =>
|
||||||
relationItemModel.NodeType switch
|
relationItemModel.NodeType switch
|
||||||
{
|
{
|
||||||
Constants.UdiEntityType.Document => MapDocumentReference(relationItemModel, slimEntities),
|
Constants.ReferenceType.Document => MapDocumentReference(relationItemModel, slimEntities),
|
||||||
Constants.UdiEntityType.Media => _umbracoMapper.Map<MediaReferenceResponseModel>(relationItemModel),
|
Constants.ReferenceType.Media => _umbracoMapper.Map<MediaReferenceResponseModel>(relationItemModel),
|
||||||
Constants.UdiEntityType.Member => _umbracoMapper.Map<MemberReferenceResponseModel>(relationItemModel),
|
Constants.ReferenceType.Member => _umbracoMapper.Map<MemberReferenceResponseModel>(relationItemModel),
|
||||||
|
Constants.ReferenceType.DocumentTypePropertyType => _umbracoMapper.Map<DocumentTypePropertyTypeReferenceResponseModel>(relationItemModel),
|
||||||
|
Constants.ReferenceType.MediaTypePropertyType => _umbracoMapper.Map<MediaTypePropertyTypeReferenceResponseModel>(relationItemModel),
|
||||||
|
Constants.ReferenceType.MemberTypePropertyType => _umbracoMapper.Map<MemberTypePropertyTypeReferenceResponseModel>(relationItemModel),
|
||||||
_ => _umbracoMapper.Map<DefaultReferenceResponseModel>(relationItemModel),
|
_ => _umbracoMapper.Map<DefaultReferenceResponseModel>(relationItemModel),
|
||||||
}).WhereNotNull().ToArray();
|
}).WhereNotNull().ToArray();
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ public class TrackedReferenceViewModelsMapDefinition : IMapDefinition
|
|||||||
mapper.Define<RelationItemModel, DocumentReferenceResponseModel>((source, context) => new DocumentReferenceResponseModel(), Map);
|
mapper.Define<RelationItemModel, DocumentReferenceResponseModel>((source, context) => new DocumentReferenceResponseModel(), Map);
|
||||||
mapper.Define<RelationItemModel, MediaReferenceResponseModel>((source, context) => new MediaReferenceResponseModel(), Map);
|
mapper.Define<RelationItemModel, MediaReferenceResponseModel>((source, context) => new MediaReferenceResponseModel(), Map);
|
||||||
mapper.Define<RelationItemModel, MemberReferenceResponseModel>((source, context) => new MemberReferenceResponseModel(), Map);
|
mapper.Define<RelationItemModel, MemberReferenceResponseModel>((source, context) => new MemberReferenceResponseModel(), Map);
|
||||||
|
mapper.Define<RelationItemModel, DocumentTypePropertyTypeReferenceResponseModel>((source, context) => new DocumentTypePropertyTypeReferenceResponseModel(), Map);
|
||||||
|
mapper.Define<RelationItemModel, MediaTypePropertyTypeReferenceResponseModel>((source, context) => new MediaTypePropertyTypeReferenceResponseModel(), Map);
|
||||||
|
mapper.Define<RelationItemModel, MemberTypePropertyTypeReferenceResponseModel>((source, context) => new MemberTypePropertyTypeReferenceResponseModel(), Map);
|
||||||
mapper.Define<RelationItemModel, DefaultReferenceResponseModel>((source, context) => new DefaultReferenceResponseModel(), Map);
|
mapper.Define<RelationItemModel, DefaultReferenceResponseModel>((source, context) => new DefaultReferenceResponseModel(), Map);
|
||||||
mapper.Define<RelationItemModel, ReferenceByIdModel>((source, context) => new ReferenceByIdModel(), Map);
|
mapper.Define<RelationItemModel, ReferenceByIdModel>((source, context) => new ReferenceByIdModel(), Map);
|
||||||
mapper.Define<Guid, ReferenceByIdModel>((source, context) => new ReferenceByIdModel(), Map);
|
mapper.Define<Guid, ReferenceByIdModel>((source, context) => new ReferenceByIdModel(), Map);
|
||||||
@@ -25,6 +28,7 @@ public class TrackedReferenceViewModelsMapDefinition : IMapDefinition
|
|||||||
target.Published = source.NodePublished;
|
target.Published = source.NodePublished;
|
||||||
target.DocumentType = new TrackedReferenceDocumentType
|
target.DocumentType = new TrackedReferenceDocumentType
|
||||||
{
|
{
|
||||||
|
Id = source.ContentTypeKey,
|
||||||
Alias = source.ContentTypeAlias,
|
Alias = source.ContentTypeAlias,
|
||||||
Icon = source.ContentTypeIcon,
|
Icon = source.ContentTypeIcon,
|
||||||
Name = source.ContentTypeName,
|
Name = source.ContentTypeName,
|
||||||
@@ -38,6 +42,7 @@ public class TrackedReferenceViewModelsMapDefinition : IMapDefinition
|
|||||||
target.Name = source.NodeName;
|
target.Name = source.NodeName;
|
||||||
target.MediaType = new TrackedReferenceMediaType
|
target.MediaType = new TrackedReferenceMediaType
|
||||||
{
|
{
|
||||||
|
Id = source.ContentTypeKey,
|
||||||
Alias = source.ContentTypeAlias,
|
Alias = source.ContentTypeAlias,
|
||||||
Icon = source.ContentTypeIcon,
|
Icon = source.ContentTypeIcon,
|
||||||
Name = source.ContentTypeName,
|
Name = source.ContentTypeName,
|
||||||
@@ -51,6 +56,52 @@ public class TrackedReferenceViewModelsMapDefinition : IMapDefinition
|
|||||||
target.Name = source.NodeName;
|
target.Name = source.NodeName;
|
||||||
target.MemberType = new TrackedReferenceMemberType
|
target.MemberType = new TrackedReferenceMemberType
|
||||||
{
|
{
|
||||||
|
Id = source.ContentTypeKey,
|
||||||
|
Alias = source.ContentTypeAlias,
|
||||||
|
Icon = source.ContentTypeIcon,
|
||||||
|
Name = source.ContentTypeName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Umbraco.Code.MapAll
|
||||||
|
private void Map(RelationItemModel source, DocumentTypePropertyTypeReferenceResponseModel target, MapperContext context)
|
||||||
|
{
|
||||||
|
target.Id = source.NodeKey;
|
||||||
|
target.Name = source.NodeName;
|
||||||
|
target.Alias = source.NodeAlias;
|
||||||
|
target.DocumentType = new TrackedReferenceDocumentType
|
||||||
|
{
|
||||||
|
Id = source.ContentTypeKey,
|
||||||
|
Alias = source.ContentTypeAlias,
|
||||||
|
Icon = source.ContentTypeIcon,
|
||||||
|
Name = source.ContentTypeName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Umbraco.Code.MapAll
|
||||||
|
private void Map(RelationItemModel source, MediaTypePropertyTypeReferenceResponseModel target, MapperContext context)
|
||||||
|
{
|
||||||
|
target.Id = source.NodeKey;
|
||||||
|
target.Name = source.NodeName;
|
||||||
|
target.Alias = source.NodeAlias;
|
||||||
|
target.MediaType = new TrackedReferenceMediaType
|
||||||
|
{
|
||||||
|
Id = source.ContentTypeKey,
|
||||||
|
Alias = source.ContentTypeAlias,
|
||||||
|
Icon = source.ContentTypeIcon,
|
||||||
|
Name = source.ContentTypeName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Umbraco.Code.MapAll
|
||||||
|
private void Map(RelationItemModel source, MemberTypePropertyTypeReferenceResponseModel target, MapperContext context)
|
||||||
|
{
|
||||||
|
target.Id = source.NodeKey;
|
||||||
|
target.Name = source.NodeName;
|
||||||
|
target.Alias = source.NodeAlias;
|
||||||
|
target.MemberType = new TrackedReferenceMemberType
|
||||||
|
{
|
||||||
|
Id = source.ContentTypeKey,
|
||||||
Alias = source.ContentTypeAlias,
|
Alias = source.ContentTypeAlias,
|
||||||
Icon = source.ContentTypeIcon,
|
Icon = source.ContentTypeIcon,
|
||||||
Name = source.ContentTypeName,
|
Name = source.ContentTypeName,
|
||||||
|
|||||||
@@ -816,6 +816,70 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/umbraco/management/api/v1/data-type/{id}/referenced-by": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Data Type"
|
||||||
|
],
|
||||||
|
"operationId": "GetDataTypeByIdReferencedBy",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skip",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "take",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
|
"default": 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/PagedIReferenceResponseModel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "The resource is protected and requires an authentication token"
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "The authenticated user does not have access to this resource"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Backoffice User": [ ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/umbraco/management/api/v1/data-type/{id}/references": {
|
"/umbraco/management/api/v1/data-type/{id}/references": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -872,6 +936,7 @@
|
|||||||
"description": "The authenticated user does not have access to this resource"
|
"description": "The authenticated user does not have access to this resource"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"deprecated": true,
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"Backoffice User": [ ]
|
"Backoffice User": [ ]
|
||||||
@@ -37931,6 +37996,45 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"DocumentTypePropertyReferenceResponseModel": {
|
||||||
|
"required": [
|
||||||
|
"$type",
|
||||||
|
"documentType",
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"$type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"documentType": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/TrackedReferenceDocumentTypeModel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"discriminator": {
|
||||||
|
"propertyName": "$type",
|
||||||
|
"mapping": {
|
||||||
|
"DocumentTypePropertyReferenceResponseModel": "#/components/schemas/DocumentTypePropertyReferenceResponseModel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"DocumentTypePropertyTypeContainerResponseModel": {
|
"DocumentTypePropertyTypeContainerResponseModel": {
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
@@ -39995,6 +40099,45 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"MediaTypePropertyReferenceResponseModel": {
|
||||||
|
"required": [
|
||||||
|
"$type",
|
||||||
|
"id",
|
||||||
|
"mediaType"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"$type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"mediaType": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/TrackedReferenceMediaTypeModel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"discriminator": {
|
||||||
|
"propertyName": "$type",
|
||||||
|
"mapping": {
|
||||||
|
"MediaTypePropertyReferenceResponseModel": "#/components/schemas/MediaTypePropertyReferenceResponseModel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"MediaTypePropertyTypeContainerResponseModel": {
|
"MediaTypePropertyTypeContainerResponseModel": {
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
@@ -40773,6 +40916,45 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"MemberTypePropertyReferenceResponseModel": {
|
||||||
|
"required": [
|
||||||
|
"$type",
|
||||||
|
"id",
|
||||||
|
"memberType"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"$type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"memberType": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/TrackedReferenceMemberTypeModel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"discriminator": {
|
||||||
|
"propertyName": "$type",
|
||||||
|
"mapping": {
|
||||||
|
"MemberTypePropertyReferenceResponseModel": "#/components/schemas/MemberTypePropertyReferenceResponseModel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"MemberTypePropertyTypeContainerResponseModel": {
|
"MemberTypePropertyTypeContainerResponseModel": {
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
@@ -41980,11 +42162,20 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/DocumentReferenceResponseModel"
|
"$ref": "#/components/schemas/DocumentReferenceResponseModel"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/DocumentTypePropertyReferenceResponseModel"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/MediaReferenceResponseModel"
|
"$ref": "#/components/schemas/MediaReferenceResponseModel"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/MediaTypePropertyReferenceResponseModel"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/MemberReferenceResponseModel"
|
"$ref": "#/components/schemas/MemberReferenceResponseModel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/MemberTypePropertyReferenceResponseModel"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -44639,8 +44830,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"TrackedReferenceDocumentTypeModel": {
|
"TrackedReferenceDocumentTypeModel": {
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
"icon": {
|
"icon": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"nullable": true
|
"nullable": true
|
||||||
@@ -44657,8 +44855,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"TrackedReferenceMediaTypeModel": {
|
"TrackedReferenceMediaTypeModel": {
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
"icon": {
|
"icon": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"nullable": true
|
"nullable": true
|
||||||
@@ -44675,8 +44880,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"TrackedReferenceMemberTypeModel": {
|
"TrackedReferenceMemberTypeModel": {
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
"icon": {
|
"icon": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"nullable": true
|
"nullable": true
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
||||||
|
|
||||||
|
public abstract class ContentTypePropertyTypeReferenceResponseModel : ReferenceResponseModel
|
||||||
|
{
|
||||||
|
public string? Alias { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
||||||
|
|
||||||
|
public class DocumentTypePropertyTypeReferenceResponseModel : ContentTypePropertyTypeReferenceResponseModel
|
||||||
|
{
|
||||||
|
public TrackedReferenceDocumentType DocumentType { get; set; } = new();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
||||||
|
|
||||||
|
public class MediaTypePropertyTypeReferenceResponseModel : ContentTypePropertyTypeReferenceResponseModel
|
||||||
|
{
|
||||||
|
public TrackedReferenceMediaType MediaType { get; set; } = new();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
||||||
|
|
||||||
|
public class MemberTypePropertyTypeReferenceResponseModel : ContentTypePropertyTypeReferenceResponseModel
|
||||||
|
{
|
||||||
|
public TrackedReferenceMemberType MemberType { get; set; } = new();
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
|
||||||
|
|
||||||
public abstract class TrackedReferenceContentType
|
public abstract class TrackedReferenceContentType
|
||||||
{
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public string? Icon { get; set; }
|
public string? Icon { get; set; }
|
||||||
|
|
||||||
public string? Alias { get; set; }
|
public string? Alias { get; set; }
|
||||||
|
|||||||
25
src/Umbraco.Core/Constants-ReferenceTypes.cs
Normal file
25
src/Umbraco.Core/Constants-ReferenceTypes.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace Umbraco.Cms.Core;
|
||||||
|
|
||||||
|
public static partial class Constants
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines reference types.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Reference types are used to identify the type of entity that is being referenced when exposing references
|
||||||
|
/// between Umbraco entities.
|
||||||
|
/// These are used in the management API and backoffice to indicate and warn editors when working with an entity,
|
||||||
|
/// as to what other entities depend on it.
|
||||||
|
/// These consist of references managed by Umbraco relations (e.g. document, media and member).
|
||||||
|
/// But also references that come from schema (e.g. data type usage on content types).
|
||||||
|
/// </remarks>
|
||||||
|
public static class ReferenceType
|
||||||
|
{
|
||||||
|
public const string Document = UdiEntityType.Document;
|
||||||
|
public const string Media = UdiEntityType.Media;
|
||||||
|
public const string Member = UdiEntityType.Member;
|
||||||
|
public const string DocumentTypePropertyType = "document-type-property-type";
|
||||||
|
public const string MediaTypePropertyType = "media-type-property-type";
|
||||||
|
public const string MemberTypePropertyType = "member-type-property-type";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,9 @@ public class RelationItem
|
|||||||
[DataMember(Name = "published")]
|
[DataMember(Name = "published")]
|
||||||
public bool? NodePublished { get; set; }
|
public bool? NodePublished { get; set; }
|
||||||
|
|
||||||
|
[DataMember(Name = "contentTypeKey")]
|
||||||
|
public Guid ContentTypeKey { get; set; }
|
||||||
|
|
||||||
[DataMember(Name = "icon")]
|
[DataMember(Name = "icon")]
|
||||||
public string? ContentTypeIcon { get; set; }
|
public string? ContentTypeIcon { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
namespace Umbraco.Cms.Core.Models;
|
namespace Umbraco.Cms.Core.Models;
|
||||||
|
|
||||||
public class RelationItemModel
|
public class RelationItemModel
|
||||||
{
|
{
|
||||||
public Guid NodeKey { get; set; }
|
public Guid NodeKey { get; set; }
|
||||||
|
|
||||||
|
public string? NodeAlias { get; set; }
|
||||||
|
|
||||||
public string? NodeName { get; set; }
|
public string? NodeName { get; set; }
|
||||||
|
|
||||||
public string? NodeType { get; set; }
|
public string? NodeType { get; set; }
|
||||||
|
|
||||||
public bool? NodePublished { get; set; }
|
public bool? NodePublished { get; set; }
|
||||||
|
|
||||||
|
public Guid ContentTypeKey { get; set; }
|
||||||
|
|
||||||
public string? ContentTypeIcon { get; set; }
|
public string? ContentTypeIcon { get; set; }
|
||||||
|
|
||||||
public string? ContentTypeAlias { get; set; }
|
public string? ContentTypeAlias { get; set; }
|
||||||
|
|||||||
@@ -24,6 +24,5 @@ public interface IDataTypeRepository : IReadWriteQueryRepository<int, IDataType>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
||||||
IReadOnlyDictionary<Udi, IEnumerable<string>> FindListViewUsages(int id) => throw new NotImplementedException();
|
IReadOnlyDictionary<Udi, IEnumerable<string>> FindListViewUsages(int id) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,15 @@ namespace Umbraco.Cms.Core.Services.Implement
|
|||||||
private readonly IDataTypeRepository _dataTypeRepository;
|
private readonly IDataTypeRepository _dataTypeRepository;
|
||||||
private readonly IDataTypeContainerRepository _dataTypeContainerRepository;
|
private readonly IDataTypeContainerRepository _dataTypeContainerRepository;
|
||||||
private readonly IContentTypeRepository _contentTypeRepository;
|
private readonly IContentTypeRepository _contentTypeRepository;
|
||||||
|
private readonly IMediaTypeRepository _mediaTypeRepository;
|
||||||
|
private readonly IMemberTypeRepository _memberTypeRepository;
|
||||||
private readonly IAuditRepository _auditRepository;
|
private readonly IAuditRepository _auditRepository;
|
||||||
private readonly IIOHelper _ioHelper;
|
private readonly IIOHelper _ioHelper;
|
||||||
private readonly IDataTypeContainerService _dataTypeContainerService;
|
private readonly IDataTypeContainerService _dataTypeContainerService;
|
||||||
private readonly IUserIdKeyResolver _userIdKeyResolver;
|
private readonly IUserIdKeyResolver _userIdKeyResolver;
|
||||||
private readonly Lazy<IIdKeyMap> _idKeyMap;
|
private readonly Lazy<IIdKeyMap> _idKeyMap;
|
||||||
|
|
||||||
|
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
|
||||||
public DataTypeService(
|
public DataTypeService(
|
||||||
ICoreScopeProvider provider,
|
ICoreScopeProvider provider,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
@@ -41,12 +44,41 @@ namespace Umbraco.Cms.Core.Services.Implement
|
|||||||
IContentTypeRepository contentTypeRepository,
|
IContentTypeRepository contentTypeRepository,
|
||||||
IIOHelper ioHelper,
|
IIOHelper ioHelper,
|
||||||
Lazy<IIdKeyMap> idKeyMap)
|
Lazy<IIdKeyMap> idKeyMap)
|
||||||
|
: this(
|
||||||
|
provider,
|
||||||
|
loggerFactory,
|
||||||
|
eventMessagesFactory,
|
||||||
|
dataTypeRepository,
|
||||||
|
dataValueEditorFactory,
|
||||||
|
auditRepository,
|
||||||
|
contentTypeRepository,
|
||||||
|
StaticServiceProvider.Instance.GetRequiredService<IMediaTypeRepository>(),
|
||||||
|
StaticServiceProvider.Instance.GetRequiredService<IMemberTypeRepository>(),
|
||||||
|
ioHelper,
|
||||||
|
idKeyMap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTypeService(
|
||||||
|
ICoreScopeProvider provider,
|
||||||
|
ILoggerFactory loggerFactory,
|
||||||
|
IEventMessagesFactory eventMessagesFactory,
|
||||||
|
IDataTypeRepository dataTypeRepository,
|
||||||
|
IDataValueEditorFactory dataValueEditorFactory,
|
||||||
|
IAuditRepository auditRepository,
|
||||||
|
IContentTypeRepository contentTypeRepository,
|
||||||
|
IMediaTypeRepository mediaTypeRepository,
|
||||||
|
IMemberTypeRepository memberTypeRepository,
|
||||||
|
IIOHelper ioHelper,
|
||||||
|
Lazy<IIdKeyMap> idKeyMap)
|
||||||
: base(provider, loggerFactory, eventMessagesFactory)
|
: base(provider, loggerFactory, eventMessagesFactory)
|
||||||
{
|
{
|
||||||
_dataValueEditorFactory = dataValueEditorFactory;
|
_dataValueEditorFactory = dataValueEditorFactory;
|
||||||
_dataTypeRepository = dataTypeRepository;
|
_dataTypeRepository = dataTypeRepository;
|
||||||
_auditRepository = auditRepository;
|
_auditRepository = auditRepository;
|
||||||
_contentTypeRepository = contentTypeRepository;
|
_contentTypeRepository = contentTypeRepository;
|
||||||
|
_mediaTypeRepository = mediaTypeRepository;
|
||||||
|
_memberTypeRepository = memberTypeRepository;
|
||||||
_ioHelper = ioHelper;
|
_ioHelper = ioHelper;
|
||||||
_idKeyMap = idKeyMap;
|
_idKeyMap = idKeyMap;
|
||||||
|
|
||||||
@@ -703,12 +735,119 @@ namespace Umbraco.Cms.Core.Services.Implement
|
|||||||
return await Task.FromResult(Attempt.SucceedWithStatus(DataTypeOperationStatus.Success, usages));
|
return await Task.FromResult(Attempt.SucceedWithStatus(DataTypeOperationStatus.Success, usages));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public IReadOnlyDictionary<Udi, IEnumerable<string>> GetListViewReferences(int id)
|
public IReadOnlyDictionary<Udi, IEnumerable<string>> GetListViewReferences(int id)
|
||||||
{
|
{
|
||||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||||
return _dataTypeRepository.FindListViewUsages(id);
|
return _dataTypeRepository.FindListViewUsages(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<PagedModel<RelationItemModel>> GetPagedRelationsAsync(Guid key, int skip, int take)
|
||||||
|
{
|
||||||
|
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||||
|
|
||||||
|
IDataType? dataType = GetDataTypeFromRepository(key);
|
||||||
|
if (dataType == null)
|
||||||
|
{
|
||||||
|
// Is an unexpected response, but returning an empty collection aligns with how we handle retrieval of concrete Umbraco
|
||||||
|
// relations based on documents, media and members.
|
||||||
|
return Task.FromResult(new PagedModel<RelationItemModel>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't really need true paging here, as the number of data type relations will be small compared to what there could
|
||||||
|
// potentially by for concrete Umbraco relations based on documents, media and members.
|
||||||
|
// So we'll retrieve all usages for the data type and construct a paged response.
|
||||||
|
// This allows us to re-use the existing repository methods used for FindUsages and FindListViewUsages.
|
||||||
|
IReadOnlyDictionary<Udi, IEnumerable<string>> usages = _dataTypeRepository.FindUsages(dataType.Id);
|
||||||
|
IReadOnlyDictionary<Udi, IEnumerable<string>> listViewUsages = _dataTypeRepository.FindListViewUsages(dataType.Id);
|
||||||
|
|
||||||
|
// Combine the property and list view usages into a single collection of property aliases and content type UDIs.
|
||||||
|
IList<(string PropertyAlias, Udi Udi)> combinedUsages = usages
|
||||||
|
.SelectMany(kvp => kvp.Value.Select(value => (value, kvp.Key)))
|
||||||
|
.Concat(listViewUsages.SelectMany(kvp => kvp.Value.Select(value => (value, kvp.Key))))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var totalItems = combinedUsages.Count;
|
||||||
|
|
||||||
|
// Create the page of items.
|
||||||
|
IList<(string PropertyAlias, Udi Udi)> pagedUsages = combinedUsages
|
||||||
|
.OrderBy(x => x.Udi.EntityType) // Document types first, then media types, then member types.
|
||||||
|
.ThenBy(x => x.PropertyAlias)
|
||||||
|
.Skip(skip)
|
||||||
|
.Take(take)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Get the content types for the UDIs referenced in the page of items to construct the response from.
|
||||||
|
// They could be document, media or member types.
|
||||||
|
IList<IContentTypeComposition> contentTypes = GetReferencedContentTypes(pagedUsages);
|
||||||
|
|
||||||
|
IEnumerable<RelationItemModel> relations = pagedUsages
|
||||||
|
.Select(x =>
|
||||||
|
{
|
||||||
|
// Get the matching content type so we can populate the content type and property details.
|
||||||
|
IContentTypeComposition contentType = contentTypes.Single(y => y.Key == ((GuidUdi)x.Udi).Guid);
|
||||||
|
|
||||||
|
string nodeType = x.Udi.EntityType switch
|
||||||
|
{
|
||||||
|
Constants.UdiEntityType.DocumentType => Constants.ReferenceType.DocumentTypePropertyType,
|
||||||
|
Constants.UdiEntityType.MediaType => Constants.ReferenceType.MediaTypePropertyType,
|
||||||
|
Constants.UdiEntityType.MemberType => Constants.ReferenceType.MemberTypePropertyType,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(x.Udi.EntityType)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Look-up the property details from the property alias. This will be null for a list view reference.
|
||||||
|
IPropertyType? propertyType = contentType.PropertyTypes.SingleOrDefault(y => y.Alias == x.PropertyAlias);
|
||||||
|
return new RelationItemModel
|
||||||
|
{
|
||||||
|
ContentTypeKey = contentType.Key,
|
||||||
|
ContentTypeAlias = contentType.Alias,
|
||||||
|
ContentTypeIcon = contentType.Icon,
|
||||||
|
ContentTypeName = contentType.Name,
|
||||||
|
NodeType = nodeType,
|
||||||
|
NodeName = propertyType?.Name ?? x.PropertyAlias,
|
||||||
|
NodeAlias = x.PropertyAlias,
|
||||||
|
NodeKey = propertyType?.Key ?? Guid.Empty,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
var pagedModel = new PagedModel<RelationItemModel>(totalItems, relations);
|
||||||
|
return Task.FromResult(pagedModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IList<IContentTypeComposition> GetReferencedContentTypes(IList<(string PropertyAlias, Udi Udi)> pagedUsages)
|
||||||
|
{
|
||||||
|
IEnumerable<IContentTypeComposition> documentTypes = GetContentTypes(
|
||||||
|
pagedUsages,
|
||||||
|
Constants.UdiEntityType.DocumentType,
|
||||||
|
_contentTypeRepository);
|
||||||
|
IEnumerable<IContentTypeComposition> mediaTypes = GetContentTypes(
|
||||||
|
pagedUsages,
|
||||||
|
Constants.UdiEntityType.MediaType,
|
||||||
|
_mediaTypeRepository);
|
||||||
|
IEnumerable<IContentTypeComposition> memberTypes = GetContentTypes(
|
||||||
|
pagedUsages,
|
||||||
|
Constants.UdiEntityType.MemberType,
|
||||||
|
_memberTypeRepository);
|
||||||
|
return documentTypes.Concat(mediaTypes).Concat(memberTypes).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<T> GetContentTypes<T>(
|
||||||
|
IEnumerable<(string PropertyAlias, Udi Udi)> dataTypeUsages,
|
||||||
|
string entityType,
|
||||||
|
IContentTypeRepositoryBase<T> repository)
|
||||||
|
where T : IContentTypeComposition
|
||||||
|
{
|
||||||
|
Guid[] contentTypeKeys = dataTypeUsages
|
||||||
|
.Where(x => x.Udi is GuidUdi && x.Udi.EntityType == entityType)
|
||||||
|
.Select(x => ((GuidUdi)x.Udi).Guid)
|
||||||
|
.Distinct()
|
||||||
|
.ToArray();
|
||||||
|
return contentTypeKeys.Length > 0
|
||||||
|
? repository.GetMany(contentTypeKeys)
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<ValidationResult> ValidateConfigurationData(IDataType dataType)
|
public IEnumerable<ValidationResult> ValidateConfigurationData(IDataType dataType)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public interface IDataTypeService : IService
|
|||||||
[Obsolete("Please use GetReferencesAsync. Will be deleted in V15.")]
|
[Obsolete("Please use GetReferencesAsync. Will be deleted in V15.")]
|
||||||
IReadOnlyDictionary<Udi, IEnumerable<string>> GetReferences(int id);
|
IReadOnlyDictionary<Udi, IEnumerable<string>> GetReferences(int id);
|
||||||
|
|
||||||
|
[Obsolete("Please use GetPagedRelationsAsync. Scheduled for removal in Umbraco 17.")]
|
||||||
IReadOnlyDictionary<Udi, IEnumerable<string>> GetListViewReferences(int id) => throw new NotImplementedException();
|
IReadOnlyDictionary<Udi, IEnumerable<string>> GetListViewReferences(int id) => throw new NotImplementedException();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,8 +26,25 @@ public interface IDataTypeService : IService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The guid Id of the <see cref="IDataType" /></param>
|
/// <param name="id">The guid Id of the <see cref="IDataType" /></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[Obsolete("Please use GetPagedRelationsAsync. Scheduled for removal in Umbraco 17.")]
|
||||||
Task<Attempt<IReadOnlyDictionary<Udi, IEnumerable<string>>, DataTypeOperationStatus>> GetReferencesAsync(Guid id);
|
Task<Attempt<IReadOnlyDictionary<Udi, IEnumerable<string>>, DataTypeOperationStatus>> GetReferencesAsync(Guid id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a paged result of items which are in relation with the current data type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The identifier of the data type to retrieve relations for.</param>
|
||||||
|
/// <param name="skip">The amount of items to skip</param>
|
||||||
|
/// <param name="take">The amount of items to take.</param>
|
||||||
|
/// <returns>A paged result of <see cref="RelationItemModel" /> objects.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Note that the model and method signature here aligns with with how we handle retrieval of concrete Umbraco
|
||||||
|
/// relations based on documents, media and members in <see cref="ITrackedReferencesService"/>.
|
||||||
|
/// The intention is that we align data type relations with these so they can be handled polymorphically at the management API
|
||||||
|
/// and backoffice UI level.
|
||||||
|
/// </remarks>
|
||||||
|
Task<PagedModel<RelationItemModel>> GetPagedRelationsAsync(Guid key, int skip, int take)
|
||||||
|
=> Task.FromResult(new PagedModel<RelationItemModel>());
|
||||||
|
|
||||||
[Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")]
|
[Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")]
|
||||||
Attempt<OperationResult<OperationResultType, EntityContainer>?> CreateContainer(int parentId, Guid key, string name,
|
Attempt<OperationResult<OperationResultType, EntityContainer>?> CreateContainer(int parentId, Guid key, string name,
|
||||||
int userId = Constants.Security.SuperUserId);
|
int userId = Constants.Security.SuperUserId);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Umbraco.Cms.Core.Mapping;
|
using Umbraco.Cms.Core.Mapping;
|
||||||
using Umbraco.Cms.Core.Models;
|
using Umbraco.Cms.Core.Models;
|
||||||
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ public class RelationModelMapDefinition : IMapDefinition
|
|||||||
target.RelationTypeName = source.RelationTypeName;
|
target.RelationTypeName = source.RelationTypeName;
|
||||||
target.RelationTypeIsBidirectional = source.RelationTypeIsBidirectional;
|
target.RelationTypeIsBidirectional = source.RelationTypeIsBidirectional;
|
||||||
target.RelationTypeIsDependency = source.RelationTypeIsDependency;
|
target.RelationTypeIsDependency = source.RelationTypeIsDependency;
|
||||||
|
target.ContentTypeKey = source.ChildContentTypeKey;
|
||||||
target.ContentTypeAlias = source.ChildContentTypeAlias;
|
target.ContentTypeAlias = source.ChildContentTypeAlias;
|
||||||
target.ContentTypeIcon = source.ChildContentTypeIcon;
|
target.ContentTypeIcon = source.ChildContentTypeIcon;
|
||||||
target.ContentTypeName = source.ChildContentTypeName;
|
target.ContentTypeName = source.ChildContentTypeName;
|
||||||
|
|||||||
@@ -475,6 +475,9 @@ internal class RelationItemDto
|
|||||||
[Column(Name = "nodeObjectType")]
|
[Column(Name = "nodeObjectType")]
|
||||||
public Guid ChildNodeObjectType { get; set; }
|
public Guid ChildNodeObjectType { get; set; }
|
||||||
|
|
||||||
|
[Column(Name = "contentTypeKey")]
|
||||||
|
public Guid ChildContentTypeKey { get; set; }
|
||||||
|
|
||||||
[Column(Name = "contentTypeIcon")]
|
[Column(Name = "contentTypeIcon")]
|
||||||
public string? ChildContentTypeIcon { get; set; }
|
public string? ChildContentTypeIcon { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
"[d].[published] as nodePublished",
|
"[d].[published] as nodePublished",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -188,6 +189,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
"[d].[published] as nodePublished",
|
"[d].[published] as nodePublished",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -250,6 +252,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
"[d].[published] as nodePublished",
|
"[d].[published] as nodePublished",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -336,6 +339,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
"[d].[published] as nodePublished",
|
"[d].[published] as nodePublished",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -411,6 +415,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[uniqueId] as nodeKey",
|
"[n].[uniqueId] as nodeKey",
|
||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -477,6 +482,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[uniqueId] as nodeKey",
|
"[n].[uniqueId] as nodeKey",
|
||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -595,6 +601,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
"[d].[published] as nodePublished",
|
"[d].[published] as nodePublished",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -671,6 +678,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[uniqueId] as nodeKey",
|
"[n].[uniqueId] as nodeKey",
|
||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -749,6 +757,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
"[n].[uniqueId] as nodeKey",
|
"[n].[uniqueId] as nodeKey",
|
||||||
"[n].[text] as nodeName",
|
"[n].[text] as nodeName",
|
||||||
"[n].[nodeObjectType] as nodeObjectType",
|
"[n].[nodeObjectType] as nodeObjectType",
|
||||||
|
"[ctn].[uniqueId] as contentTypeKey",
|
||||||
"[ct].[icon] as contentTypeIcon",
|
"[ct].[icon] as contentTypeIcon",
|
||||||
"[ct].[alias] as contentTypeAlias",
|
"[ct].[alias] as contentTypeAlias",
|
||||||
"[ctn].[text] as contentTypeName",
|
"[ctn].[text] as contentTypeName",
|
||||||
@@ -841,6 +850,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
|||||||
RelationTypeName = dto.RelationTypeName,
|
RelationTypeName = dto.RelationTypeName,
|
||||||
RelationTypeIsBidirectional = dto.RelationTypeIsBidirectional,
|
RelationTypeIsBidirectional = dto.RelationTypeIsBidirectional,
|
||||||
RelationTypeIsDependency = dto.RelationTypeIsDependency,
|
RelationTypeIsDependency = dto.RelationTypeIsDependency,
|
||||||
|
ContentTypeKey = dto.ChildContentTypeKey,
|
||||||
ContentTypeAlias = dto.ChildContentTypeAlias,
|
ContentTypeAlias = dto.ChildContentTypeAlias,
|
||||||
ContentTypeIcon = dto.ChildContentTypeIcon,
|
ContentTypeIcon = dto.ChildContentTypeIcon,
|
||||||
ContentTypeName = dto.ChildContentTypeName,
|
ContentTypeName = dto.ChildContentTypeName,
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ public class MediaTypeBuilder
|
|||||||
var mediaType = builder
|
var mediaType = builder
|
||||||
.WithAlias(alias)
|
.WithAlias(alias)
|
||||||
.WithName(name)
|
.WithName(name)
|
||||||
|
.WithIcon("icon-picture")
|
||||||
.WithParentContentType(parent)
|
.WithParentContentType(parent)
|
||||||
.AddPropertyGroup()
|
.AddPropertyGroup()
|
||||||
.WithAlias(propertyGroupAlias)
|
.WithAlias(propertyGroupAlias)
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ public class DataTypeServiceTests : UmbracoIntegrationTest
|
|||||||
|
|
||||||
private IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
private IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
||||||
|
|
||||||
|
private IMediaTypeService MediaTypeService => GetRequiredService<IMediaTypeService>();
|
||||||
|
|
||||||
private IFileService FileService => GetRequiredService<IFileService>();
|
private IFileService FileService => GetRequiredService<IFileService>();
|
||||||
|
|
||||||
private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer =>
|
private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer =>
|
||||||
@@ -446,4 +448,43 @@ public class DataTypeServiceTests : UmbracoIntegrationTest
|
|||||||
Assert.IsFalse(result.Success);
|
Assert.IsFalse(result.Success);
|
||||||
Assert.AreEqual(DataTypeOperationStatus.NonDeletable, result.Status);
|
Assert.AreEqual(DataTypeOperationStatus.NonDeletable, result.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task DataTypeService_Can_Get_References()
|
||||||
|
{
|
||||||
|
IEnumerable<IDataType> dataTypeDefinitions = await DataTypeService.GetByEditorAliasAsync(Constants.PropertyEditors.Aliases.RichText);
|
||||||
|
|
||||||
|
IContentType documentType = ContentTypeBuilder.CreateSimpleContentType("umbTextpage", "Text Page");
|
||||||
|
ContentTypeService.Save(documentType);
|
||||||
|
|
||||||
|
IMediaType mediaType = MediaTypeBuilder.CreateSimpleMediaType("umbMediaItem", "Media Item");
|
||||||
|
MediaTypeService.Save(mediaType);
|
||||||
|
|
||||||
|
documentType = ContentTypeService.Get(documentType.Id);
|
||||||
|
Assert.IsNotNull(documentType.PropertyTypes.SingleOrDefault(pt => pt.PropertyEditorAlias is Constants.PropertyEditors.Aliases.RichText));
|
||||||
|
|
||||||
|
mediaType = MediaTypeService.Get(mediaType.Id);
|
||||||
|
Assert.IsNotNull(mediaType.PropertyTypes.SingleOrDefault(pt => pt.PropertyEditorAlias is Constants.PropertyEditors.Aliases.RichText));
|
||||||
|
|
||||||
|
var definition = dataTypeDefinitions.First();
|
||||||
|
var definitionKey = definition.Key;
|
||||||
|
PagedModel<RelationItemModel> result = await DataTypeService.GetPagedRelationsAsync(definitionKey, 0, 10);
|
||||||
|
Assert.AreEqual(2, result.Total);
|
||||||
|
|
||||||
|
RelationItemModel firstResult = result.Items.First();
|
||||||
|
Assert.AreEqual("umbTextpage", firstResult.ContentTypeAlias);
|
||||||
|
Assert.AreEqual("Text Page", firstResult.ContentTypeName);
|
||||||
|
Assert.AreEqual("icon-document", firstResult.ContentTypeIcon);
|
||||||
|
Assert.AreEqual(documentType.Key, firstResult.ContentTypeKey);
|
||||||
|
Assert.AreEqual("bodyText", firstResult.NodeAlias);
|
||||||
|
Assert.AreEqual("Body text", firstResult.NodeName);
|
||||||
|
|
||||||
|
RelationItemModel secondResult = result.Items.Skip(1).First();
|
||||||
|
Assert.AreEqual("umbMediaItem", secondResult.ContentTypeAlias);
|
||||||
|
Assert.AreEqual("Media Item", secondResult.ContentTypeName);
|
||||||
|
Assert.AreEqual("icon-picture", secondResult.ContentTypeIcon);
|
||||||
|
Assert.AreEqual(mediaType.Key, secondResult.ContentTypeKey);
|
||||||
|
Assert.AreEqual("bodyText", secondResult.NodeAlias);
|
||||||
|
Assert.AreEqual("Body text", secondResult.NodeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user