From 468ca9ae94fbd329440b9bb7288328603e79a8a0 Mon Sep 17 00:00:00 2001
From: Andy Butland
Date: Fri, 28 Mar 2025 16:34:25 +0100
Subject: [PATCH] Member relation tracking (#18852)
* Added member reference type model.
* Updated client-side types and sdk.
* Render member relations on the member info view.
* Add relation type for related member with migration.
* Extend tests for track relations to include member relations.
* Extend tests for relation repository.
* Extend tests for relation service.
* Addressed comments from Copilot review.
* Add relation notification to member deletion.
* Removed unused import.
* Updates from code review.
* export const
* Fixed failing integration tests.
* deprecate interface with wrong name
* fix import
---------
Co-authored-by: Mads Rasmussen
---
.../AreReferencedDocumentController.cs | 4 +-
.../ReferencedByDocumentController.cs | 2 +-
...ReferencedDescendantsDocumentController.cs | 4 +-
.../AreReferencedMediaController.cs | 4 +-
.../References/ReferencedByMediaController.cs | 2 +-
.../ReferencedDescendantsMediaController.cs | 4 +-
.../AreReferencedMemberController.cs | 51 ++++
.../ReferencedByMemberController.cs | 50 ++++
.../ReferencedDescendantsMemberController.cs | 50 ++++
.../RelationTypePresentationFactory.cs | 3 +-
...TrackedReferenceViewModelsMapDefinition.cs | 16 +-
src/Umbraco.Cms.Api.Management/OpenApi.json | 274 +++++++++++++++++-
.../DefaultReferenceResponseModel.cs | 8 +-
.../DocumentReferenceResponseModel.cs | 8 +-
.../MediaReferenceResponseModel.cs | 8 +-
.../MemberReferenceResponseModel.cs | 6 +
.../ReferenceResponseModel.cs | 8 +
.../TrackedReferenceMemberType.cs | 5 +
src/Umbraco.Core/Constants-Conventions.cs | 16 +-
.../Models/Editors/UmbracoEntityReference.cs | 3 +
.../Models/RelationTypeExtensions.cs | 1 +
.../DataValueReferenceFactoryCollection.cs | 2 +-
.../MemberPickerPropertyEditor.cs | 17 +-
.../Migrations/Install/DatabaseDataCreator.cs | 3 +
.../Migrations/Upgrade/UmbracoPlan.cs | 1 +
.../V_15_4_0/AddRelationTypeForMembers.cs | 46 +++
.../src/external/backend-api/src/sdk.gen.ts | 84 +++++-
.../src/external/backend-api/src/types.gen.ts | 43 ++-
.../src/mocks/data/tracked-reference.data.ts | 5 +-
.../workspace-info-app-layout.element.ts | 8 +-
.../document-reference-table.element.ts | 4 +
.../media/media/entity-actions/manifests.ts | 2 +-
...a-references-workspace-info-app.element.ts | 4 -
.../src/packages/members/member/constants.ts | 1 +
.../member/entity-actions/manifests.ts | 8 +-
.../members/member/item/repository/types.ts | 11 +-
.../src/packages/members/member/manifests.ts | 2 +
.../members/member/reference/constants.ts | 1 +
.../members/member/reference/index.ts | 1 +
.../member/reference/info-app/manifests.ts | 18 ++
...r-references-workspace-info-app.element.ts | 161 ++++++++++
.../members/member/reference/manifests.ts | 4 +
.../member/reference/repository/constants.ts | 1 +
.../member/reference/repository/index.ts | 1 +
.../member/reference/repository/manifests.ts | 19 ++
...ference-response.management-api.mapping.ts | 32 ++
.../repository/member-reference.repository.ts | 36 +++
.../member-reference.server.data.ts | 121 ++++++++
.../member/reference/repository/types.ts | 14 +
...mber-workspace-view-member-info.element.ts | 4 +-
.../member-workspace-view-member.element.ts | 7 +
.../relations/relations/reference/types.ts | 4 +-
.../src/packages/relations/relations/utils.ts | 9 +
.../Repositories/RelationRepositoryTest.cs | 49 ++--
.../RelationTypeRepositoryTest.cs | 6 +-
.../Services/RelationServiceTests.cs | 37 +++
.../Services/TrackRelationsTests.cs | 18 +-
57 files changed, 1238 insertions(+), 73 deletions(-)
create mode 100644 src/Umbraco.Cms.Api.Management/Controllers/Member/References/AreReferencedMemberController.cs
create mode 100644 src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedByMemberController.cs
create mode 100644 src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedDescendantsMemberController.cs
create mode 100644 src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MemberReferenceResponseModel.cs
create mode 100644 src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/ReferenceResponseModel.cs
create mode 100644 src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/TrackedReferenceMemberType.cs
create mode 100644 src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddRelationTypeForMembers.cs
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/constants.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/member-references-workspace-info-app.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/constants.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference-response.management-api.mapping.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.server.data.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/types.ts
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/References/AreReferencedDocumentController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/References/AreReferencedDocumentController.cs
index ed593e9c9e..bc2353dc55 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Document/References/AreReferencedDocumentController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/References/AreReferencedDocumentController.cs
@@ -1,4 +1,4 @@
-using Asp.Versioning;
+using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
@@ -45,6 +45,6 @@ public class AreReferencedDocumentController : DocumentControllerBase
Items = _umbracoMapper.MapEnumerable(distinctByKeyItemsWithReferencedRelations.Items),
};
- return await Task.FromResult(pagedViewModel);
+ return pagedViewModel;
}
}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedByDocumentController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedByDocumentController.cs
index 47df66fd6d..6a1d9b2824 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedByDocumentController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedByDocumentController.cs
@@ -45,6 +45,6 @@ public class ReferencedByDocumentController : DocumentControllerBase
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
};
- return await Task.FromResult(pagedViewModel);
+ return pagedViewModel;
}
}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedDescendantsDocumentController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedDescendantsDocumentController.cs
index 4b931632e1..138b919628 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedDescendantsDocumentController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Document/References/ReferencedDescendantsDocumentController.cs
@@ -1,4 +1,4 @@
-using Asp.Versioning;
+using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
@@ -45,6 +45,6 @@ public class ReferencedDescendantsDocumentController : DocumentControllerBase
Items = _umbracoMapper.MapEnumerable(relationItems.Items),
};
- return await Task.FromResult(pagedViewModel);
+ return pagedViewModel;
}
}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/References/AreReferencedMediaController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/References/AreReferencedMediaController.cs
index 89e0c2d1ba..d10bdb9627 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Media/References/AreReferencedMediaController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/References/AreReferencedMediaController.cs
@@ -1,4 +1,4 @@
-using Asp.Versioning;
+using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
@@ -46,6 +46,6 @@ public class AreReferencedMediaController : MediaControllerBase
Items = _umbracoMapper.MapEnumerable(distinctByKeyItemsWithReferencedRelations.Items),
};
- return await Task.FromResult(pagedViewModel);
+ return pagedViewModel;
}
}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedByMediaController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedByMediaController.cs
index 63748741b1..e9e62504ed 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedByMediaController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedByMediaController.cs
@@ -45,6 +45,6 @@ public class ReferencedByMediaController : MediaControllerBase
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
};
- return await Task.FromResult(pagedViewModel);
+ return pagedViewModel;
}
}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedDescendantsMediaController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedDescendantsMediaController.cs
index 2990602e02..c6c16cb222 100644
--- a/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedDescendantsMediaController.cs
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Media/References/ReferencedDescendantsMediaController.cs
@@ -1,4 +1,4 @@
-using Asp.Versioning;
+using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
@@ -45,6 +45,6 @@ public class ReferencedDescendantsMediaController : MediaControllerBase
Items = _umbracoMapper.MapEnumerable(relationItems.Items),
};
- return await Task.FromResult(pagedViewModel);
+ return pagedViewModel;
}
}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Member/References/AreReferencedMemberController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Member/References/AreReferencedMemberController.cs
new file mode 100644
index 0000000000..1b46a981ce
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Member/References/AreReferencedMemberController.cs
@@ -0,0 +1,51 @@
+using Asp.Versioning;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Umbraco.Cms.Api.Common.ViewModels.Pagination;
+using Umbraco.Cms.Api.Management.ViewModels;
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Core.Mapping;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Services;
+
+namespace Umbraco.Cms.Api.Management.Controllers.Member.References;
+
+[ApiVersion("1.0")]
+public class AreReferencedMemberController : MemberControllerBase
+{
+ private readonly ITrackedReferencesService _trackedReferencesSkipTakeService;
+ private readonly IUmbracoMapper _umbracoMapper;
+
+ public AreReferencedMemberController(ITrackedReferencesService trackedReferencesSkipTakeService, IUmbracoMapper umbracoMapper)
+ {
+ _trackedReferencesSkipTakeService = trackedReferencesSkipTakeService;
+ _umbracoMapper = umbracoMapper;
+ }
+
+ ///
+ /// Gets a page list of the items used in any kind of relation from selected keys.
+ ///
+ ///
+ /// Used when bulk deleting content/media and bulk unpublishing content (delete and unpublish on List view).
+ /// This is basically finding children of relations.
+ ///
+ // [HttpGet("item")]
+ [HttpGet("are-referenced")]
+ [MapToApiVersion("1.0")]
+ [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)]
+ public async Task>> GetPagedReferencedItems(
+ CancellationToken cancellationToken,
+ [FromQuery(Name="id")] HashSet ids,
+ int skip = 0,
+ int take = 20)
+ {
+ PagedModel distinctByKeyItemsWithReferencedRelations = await _trackedReferencesSkipTakeService.GetPagedKeysWithDependentReferencesAsync(ids, Constants.ObjectTypes.Member, skip, take);
+ var pagedViewModel = new PagedViewModel
+ {
+ Total = distinctByKeyItemsWithReferencedRelations.Total,
+ Items = _umbracoMapper.MapEnumerable(distinctByKeyItemsWithReferencedRelations.Items),
+ };
+
+ return pagedViewModel;
+ }
+}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedByMemberController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedByMemberController.cs
new file mode 100644
index 0000000000..69237278a5
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedByMemberController.cs
@@ -0,0 +1,50 @@
+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.Member.References;
+
+[ApiVersion("1.0")]
+public class ReferencedByMemberController : MemberControllerBase
+{
+ private readonly ITrackedReferencesService _trackedReferencesService;
+ private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;
+
+ public ReferencedByMemberController(ITrackedReferencesService trackedReferencesService, IRelationTypePresentationFactory relationTypePresentationFactory)
+ {
+ _trackedReferencesService = trackedReferencesService;
+ _relationTypePresentationFactory = relationTypePresentationFactory;
+ }
+
+ ///
+ /// Gets a page list of tracked references for the current item, so you can see where an item is being used.
+ ///
+ ///
+ /// Used by info tabs on content, media etc. and for the delete and unpublish of single items.
+ /// This is basically finding parents of relations.
+ ///
+ [HttpGet("{id:guid}/referenced-by")]
+ [MapToApiVersion("1.0")]
+ [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)]
+ public async Task>> ReferencedBy(
+ CancellationToken cancellationToken,
+ Guid id,
+ int skip = 0,
+ int take = 20)
+ {
+ PagedModel relationItems = await _trackedReferencesService.GetPagedRelationsForItemAsync(id, skip, take, true);
+
+ var pagedViewModel = new PagedViewModel
+ {
+ Total = relationItems.Total,
+ Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
+ };
+
+ return pagedViewModel;
+ }
+}
diff --git a/src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedDescendantsMemberController.cs b/src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedDescendantsMemberController.cs
new file mode 100644
index 0000000000..aa86950e6e
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/Controllers/Member/References/ReferencedDescendantsMemberController.cs
@@ -0,0 +1,50 @@
+using Asp.Versioning;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Umbraco.Cms.Api.Common.ViewModels.Pagination;
+using Umbraco.Cms.Api.Management.ViewModels;
+using Umbraco.Cms.Core.Mapping;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Services;
+
+namespace Umbraco.Cms.Api.Management.Controllers.Member.References;
+
+[ApiVersion("1.0")]
+public class ReferencedDescendantsMemberController : MemberControllerBase
+{
+ private readonly ITrackedReferencesService _trackedReferencesSkipTakeService;
+ private readonly IUmbracoMapper _umbracoMapper;
+
+ public ReferencedDescendantsMemberController(ITrackedReferencesService trackedReferencesSkipTakeService, IUmbracoMapper umbracoMapper)
+ {
+ _trackedReferencesSkipTakeService = trackedReferencesSkipTakeService;
+ _umbracoMapper = umbracoMapper;
+ }
+
+ ///
+ /// Gets a page list of the child nodes of the current item used in any kind of relation.
+ ///
+ ///
+ /// Used when deleting and unpublishing a single item to check if this item has any descending items that are in any
+ /// kind of relation.
+ /// This is basically finding the descending items which are children in relations.
+ ///
+ [HttpGet("{id:guid}/referenced-descendants")]
+ [MapToApiVersion("1.0")]
+ [ProducesResponseType(typeof(PagedViewModel), StatusCodes.Status200OK)]
+ public async Task>> ReferencedDescendants(
+ CancellationToken cancellationToken,
+ Guid id,
+ int skip = 0,
+ int take = 20)
+ {
+ PagedModel relationItems = await _trackedReferencesSkipTakeService.GetPagedDescendantsInReferencesAsync(id, skip, take, true);
+ var pagedViewModel = new PagedViewModel
+ {
+ Total = relationItems.Total,
+ Items = _umbracoMapper.MapEnumerable(relationItems.Items),
+ };
+
+ return pagedViewModel;
+ }
+}
diff --git a/src/Umbraco.Cms.Api.Management/Factories/RelationTypePresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/RelationTypePresentationFactory.cs
index 0c718bf663..a6fb1cbae8 100644
--- a/src/Umbraco.Cms.Api.Management/Factories/RelationTypePresentationFactory.cs
+++ b/src/Umbraco.Cms.Api.Management/Factories/RelationTypePresentationFactory.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
@@ -58,6 +58,7 @@ public class RelationTypePresentationFactory : IRelationTypePresentationFactory
{
Constants.UdiEntityType.Document => MapDocumentReference(relationItemModel, slimEntities),
Constants.UdiEntityType.Media => _umbracoMapper.Map(relationItemModel),
+ Constants.UdiEntityType.Member => _umbracoMapper.Map(relationItemModel),
_ => _umbracoMapper.Map(relationItemModel),
}).WhereNotNull().ToArray();
diff --git a/src/Umbraco.Cms.Api.Management/Mapping/TrackedReferences/TrackedReferenceViewModelsMapDefinition.cs b/src/Umbraco.Cms.Api.Management/Mapping/TrackedReferences/TrackedReferenceViewModelsMapDefinition.cs
index 7a3874271c..e9f2700f5a 100644
--- a/src/Umbraco.Cms.Api.Management/Mapping/TrackedReferences/TrackedReferenceViewModelsMapDefinition.cs
+++ b/src/Umbraco.Cms.Api.Management/Mapping/TrackedReferences/TrackedReferenceViewModelsMapDefinition.cs
@@ -1,4 +1,4 @@
-using Umbraco.Cms.Api.Management.ViewModels;
+using Umbraco.Cms.Api.Management.ViewModels;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
@@ -11,6 +11,7 @@ public class TrackedReferenceViewModelsMapDefinition : IMapDefinition
{
mapper.Define((source, context) => new DocumentReferenceResponseModel(), Map);
mapper.Define((source, context) => new MediaReferenceResponseModel(), Map);
+ mapper.Define((source, context) => new MemberReferenceResponseModel(), Map);
mapper.Define((source, context) => new DefaultReferenceResponseModel(), Map);
mapper.Define((source, context) => new ReferenceByIdModel(), Map);
mapper.Define((source, context) => new ReferenceByIdModel(), Map);
@@ -43,6 +44,19 @@ public class TrackedReferenceViewModelsMapDefinition : IMapDefinition
};
}
+ // Umbraco.Code.MapAll
+ private void Map(RelationItemModel source, MemberReferenceResponseModel target, MapperContext context)
+ {
+ target.Id = source.NodeKey;
+ target.Name = source.NodeName;
+ target.MemberType = new TrackedReferenceMemberType
+ {
+ Alias = source.ContentTypeAlias,
+ Icon = source.ContentTypeIcon,
+ Name = source.ContentTypeName,
+ };
+ }
+
// Umbraco.Code.MapAll
private void Map(RelationItemModel source, DefaultReferenceResponseModel target, MapperContext context)
{
diff --git a/src/Umbraco.Cms.Api.Management/OpenApi.json b/src/Umbraco.Cms.Api.Management/OpenApi.json
index ebecf3e9cb..44a69ccc95 100644
--- a/src/Umbraco.Cms.Api.Management/OpenApi.json
+++ b/src/Umbraco.Cms.Api.Management/OpenApi.json
@@ -6245,6 +6245,13 @@
"type": "string"
}
},
+ {
+ "name": "isElement",
+ "in": "query",
+ "schema": {
+ "type": "boolean"
+ }
+ },
{
"name": "skip",
"in": "query",
@@ -10069,6 +10076,13 @@
"type": "string"
}
},
+ {
+ "name": "trashed",
+ "in": "query",
+ "schema": {
+ "type": "boolean"
+ }
+ },
{
"name": "skip",
"in": "query",
@@ -15766,6 +15780,13 @@
"type": "string"
}
},
+ {
+ "name": "trashed",
+ "in": "query",
+ "schema": {
+ "type": "boolean"
+ }
+ },
{
"name": "skip",
"in": "query",
@@ -20170,6 +20191,134 @@
]
}
},
+ "/umbraco/management/api/v1/member/{id}/referenced-by": {
+ "get": {
+ "tags": [
+ "Member"
+ ],
+ "operationId": "GetMemberByIdReferencedBy",
+ "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/member/{id}/referenced-descendants": {
+ "get": {
+ "tags": [
+ "Member"
+ ],
+ "operationId": "GetMemberByIdReferencedDescendants",
+ "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/PagedReferenceByIdModel"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "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/member/{id}/validate": {
"put": {
"tags": [
@@ -20312,6 +20461,73 @@
]
}
},
+ "/umbraco/management/api/v1/member/are-referenced": {
+ "get": {
+ "tags": [
+ "Member"
+ ],
+ "operationId": "GetMemberAreReferenced",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "query",
+ "schema": {
+ "uniqueItems": true,
+ "type": "array",
+ "items": {
+ "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/PagedReferenceByIdModel"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "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/member/configuration": {
"get": {
"tags": [
@@ -40095,6 +40311,41 @@
],
"type": "string"
},
+ "MemberReferenceResponseModel": {
+ "required": [
+ "$type",
+ "id",
+ "memberType"
+ ],
+ "type": "object",
+ "properties": {
+ "$type": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string",
+ "nullable": true
+ },
+ "memberType": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/TrackedReferenceMemberTypeModel"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "discriminator": {
+ "propertyName": "$type",
+ "mapping": {
+ "MemberReferenceResponseModel": "#/components/schemas/MemberReferenceResponseModel"
+ }
+ }
+ },
"MemberResponseModel": {
"required": [
"email",
@@ -41505,6 +41756,9 @@
},
{
"$ref": "#/components/schemas/MediaReferenceResponseModel"
+ },
+ {
+ "$ref": "#/components/schemas/MemberReferenceResponseModel"
}
]
}
@@ -44177,6 +44431,24 @@
},
"additionalProperties": false
},
+ "TrackedReferenceMemberTypeModel": {
+ "type": "object",
+ "properties": {
+ "icon": {
+ "type": "string",
+ "nullable": true
+ },
+ "alias": {
+ "type": "string",
+ "nullable": true
+ },
+ "name": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ "additionalProperties": false
+ },
"UnknownTypePermissionPresentationModel": {
"required": [
"$type",
@@ -46521,4 +46793,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DefaultReferenceResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DefaultReferenceResponseModel.cs
index 66780c9b47..f74b0d2840 100644
--- a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DefaultReferenceResponseModel.cs
+++ b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DefaultReferenceResponseModel.cs
@@ -1,11 +1,7 @@
-namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
+namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
-public class DefaultReferenceResponseModel : IReferenceResponseModel
+public class DefaultReferenceResponseModel : ReferenceResponseModel
{
- public Guid Id { get; set; }
-
- public string? Name { get; set; }
-
public string? Type { get; set; }
public string? Icon { get; set; }
diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DocumentReferenceResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DocumentReferenceResponseModel.cs
index e2bb767f99..a24ab23990 100644
--- a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DocumentReferenceResponseModel.cs
+++ b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/DocumentReferenceResponseModel.cs
@@ -1,13 +1,9 @@
-using Umbraco.Cms.Api.Management.ViewModels.Document;
+using Umbraco.Cms.Api.Management.ViewModels.Document;
namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
-public class DocumentReferenceResponseModel : IReferenceResponseModel
+public class DocumentReferenceResponseModel : ReferenceResponseModel
{
- public Guid Id { get; set; }
-
- public string? Name { get; set; }
-
public bool? Published { get; set; }
public TrackedReferenceDocumentType DocumentType { get; set; } = new();
diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MediaReferenceResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MediaReferenceResponseModel.cs
index c9b910d0b1..5358088bb3 100644
--- a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MediaReferenceResponseModel.cs
+++ b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MediaReferenceResponseModel.cs
@@ -1,10 +1,6 @@
-namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
+namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
-public class MediaReferenceResponseModel : IReferenceResponseModel
+public class MediaReferenceResponseModel : ReferenceResponseModel
{
- public Guid Id { get; set; }
-
- public string? Name { get; set; }
-
public TrackedReferenceMediaType MediaType { get; set; } = new();
}
diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MemberReferenceResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MemberReferenceResponseModel.cs
new file mode 100644
index 0000000000..8e33a2a175
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/MemberReferenceResponseModel.cs
@@ -0,0 +1,6 @@
+namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
+
+public class MemberReferenceResponseModel : ReferenceResponseModel
+{
+ public TrackedReferenceMemberType MemberType { get; set; } = new();
+}
diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/ReferenceResponseModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/ReferenceResponseModel.cs
new file mode 100644
index 0000000000..dae755fd33
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/ReferenceResponseModel.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
+
+public abstract class ReferenceResponseModel : IReferenceResponseModel
+{
+ public Guid Id { get; set; }
+
+ public string? Name { get; set; }
+}
diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/TrackedReferenceMemberType.cs b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/TrackedReferenceMemberType.cs
new file mode 100644
index 0000000000..501ababd1f
--- /dev/null
+++ b/src/Umbraco.Cms.Api.Management/ViewModels/TrackedReferences/TrackedReferenceMemberType.cs
@@ -0,0 +1,5 @@
+namespace Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
+
+public class TrackedReferenceMemberType : TrackedReferenceContentType
+{
+}
diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs
index 647226b6d7..989b947adc 100644
--- a/src/Umbraco.Core/Constants-Conventions.cs
+++ b/src/Umbraco.Core/Constants-Conventions.cs
@@ -233,17 +233,27 @@ public static partial class Constants
public const string RelatedMediaName = "Related Media";
///
- /// Alias for default relation type "Related Media"
+ /// Alias for default relation type "Related Media".
///
public const string RelatedMediaAlias = "umbMedia";
+ ///
+ /// Name for default relation type "Related Member".
+ ///
+ public const string RelatedMemberName = "Related Member";
+
+ ///
+ /// Alias for default relation type "Related Member".
+ ///
+ public const string RelatedMemberAlias = "umbMember";
+
///
/// Name for default relation type "Related Document".
///
public const string RelatedDocumentName = "Related Document";
///
- /// Alias for default relation type "Related Document"
+ /// Alias for default relation type "Related Document".
///
public const string RelatedDocumentAlias = "umbDocument";
@@ -284,7 +294,7 @@ public static partial class Constants
/// Developers should not manually use these relation types since they will all be cleared whenever an entity
/// (content, media or member) is saved since they are auto-populated based on property values.
///
- public static string[] AutomaticRelationTypes { get; } = { RelatedMediaAlias, RelatedDocumentAlias };
+ public static string[] AutomaticRelationTypes { get; } = { RelatedMediaAlias, RelatedMemberAlias, RelatedDocumentAlias };
// TODO: return a list of built in types so we can use that to prevent deletion in the UI
}
diff --git a/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs b/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs
index 3f02be10b1..3c22042b99 100644
--- a/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs
+++ b/src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs
@@ -34,6 +34,9 @@ public struct UmbracoEntityReference : IEquatable
case Constants.UdiEntityType.Media:
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedMediaAlias;
break;
+ case Constants.UdiEntityType.Member:
+ RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedMemberAlias;
+ break;
default:
// No relation type alias convention for this entity type, so leave it empty
RelationTypeAlias = string.Empty;
diff --git a/src/Umbraco.Core/Models/RelationTypeExtensions.cs b/src/Umbraco.Core/Models/RelationTypeExtensions.cs
index 6a22f607be..81d6801330 100644
--- a/src/Umbraco.Core/Models/RelationTypeExtensions.cs
+++ b/src/Umbraco.Core/Models/RelationTypeExtensions.cs
@@ -11,6 +11,7 @@ public static class RelationTypeExtensions
public static bool IsSystemRelationType(this IRelationType relationType) =>
relationType.Alias == Constants.Conventions.RelationTypes.RelatedDocumentAlias
|| relationType.Alias == Constants.Conventions.RelationTypes.RelatedMediaAlias
+ || relationType.Alias == Constants.Conventions.RelationTypes.RelatedMemberAlias
|| relationType.Alias == Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias
|| relationType.Alias == Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias
|| relationType.Alias == Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias;
diff --git a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs
index 86c9c48fc0..c35ae6d2ae 100644
--- a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs
+++ b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs
@@ -91,7 +91,7 @@ public class DataValueReferenceFactoryCollection : BuilderCollectionBase
DataValueEditorFactory.Create(Attribute!);
- private class MemberPickerPropertyValueEditor : DataValueEditor
+ private class MemberPickerPropertyValueEditor : DataValueEditor, IDataValueReference
{
private readonly IMemberService _memberService;
@@ -61,5 +61,20 @@ public class MemberPickerPropertyEditor : DataEditor
=> editorValue.Value is string stringValue && Guid.TryParse(stringValue, out Guid memberKey)
? new GuidUdi(Constants.UdiEntityType.Member, memberKey)
: null;
+
+ public IEnumerable GetReferences(object? value)
+ {
+ var asString = value is string str ? str : value?.ToString();
+
+ if (string.IsNullOrEmpty(asString))
+ {
+ yield break;
+ }
+
+ if (UdiParser.TryParse(asString, out Udi? udi))
+ {
+ yield return new UmbracoEntityReference(udi);
+ }
+ }
}
}
diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
index 379a3a91da..68209ee155 100644
--- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
@@ -2299,6 +2299,9 @@ internal class DatabaseDataCreator
Constants.Conventions.RelationTypes.RelatedMediaName, null, null, false, true);
CreateRelationTypeData(5, Constants.Conventions.RelationTypes.RelatedDocumentAlias,
Constants.Conventions.RelationTypes.RelatedDocumentName, null, null, false, true);
+ CreateRelationTypeData(6, Constants.Conventions.RelationTypes.RelatedMemberAlias,
+ Constants.Conventions.RelationTypes.RelatedMemberName, null, null, false, true);
+
}
private void CreateRelationTypeData(int id, string alias, string name, Guid? parentObjectType,
diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
index fe14f785d8..395504cfdc 100644
--- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
@@ -114,5 +114,6 @@ public class UmbracoPlan : MigrationPlan
// To 15.4.0
To("{A9E72794-4036-4563-B543-1717C73B8879}");
+ To("{33D62294-D0DE-4A86-A830-991EB36B96DA}");
}
}
diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddRelationTypeForMembers.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddRelationTypeForMembers.cs
new file mode 100644
index 0000000000..bcc3422946
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddRelationTypeForMembers.cs
@@ -0,0 +1,46 @@
+using Microsoft.Extensions.Logging;
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Infrastructure.Migrations.Install;
+
+namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_4_0;
+
+///
+/// Migration to add an automatic relation type for members if it doesn't already exist.
+///
+public class AddRelationTypeForMembers : MigrationBase
+{
+ private readonly IRelationService _relationService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AddRelationTypeForMembers(IMigrationContext context, IRelationService relationService)
+ : base(context) => _relationService = relationService;
+
+ ///
+ protected override void Migrate()
+ {
+ Logger.LogDebug("Adding automatic relation type for members if it doesn't already exist");
+
+ IRelationType? relationType = _relationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMemberAlias);
+ if (relationType != null)
+ {
+ Logger.LogDebug("Automatic relation type for members already exists.");
+ return;
+ }
+
+ // Generate a new unique relation type key that is the same as would have come from a new install.
+ Guid key = DatabaseDataCreator.CreateUniqueRelationTypeId(
+ Constants.Conventions.RelationTypes.RelatedMemberAlias,
+ Constants.Conventions.RelationTypes.RelatedMemberName);
+
+ // Create new relation type using service, so the repository cache gets updated as well.
+ relationType = new RelationType(Constants.Conventions.RelationTypes.RelatedMemberName, Constants.Conventions.RelationTypes.RelatedMemberAlias, false, null, null, true)
+ {
+ Key = key
+ };
+ _relationService.Save(relationType);
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts
index 9b36b8ffd2..ae4012fb62 100644
--- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts
+++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts
@@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
-import type { GetCultureData, GetCultureResponse, PostDataTypeData, PostDataTypeResponse, GetDataTypeByIdData, GetDataTypeByIdResponse, DeleteDataTypeByIdData, DeleteDataTypeByIdResponse, PutDataTypeByIdData, PutDataTypeByIdResponse, PostDataTypeByIdCopyData, PostDataTypeByIdCopyResponse, GetDataTypeByIdIsUsedData, GetDataTypeByIdIsUsedResponse, PutDataTypeByIdMoveData, PutDataTypeByIdMoveResponse, GetDataTypeByIdReferencesData, GetDataTypeByIdReferencesResponse, GetDataTypeConfigurationResponse, PostDataTypeFolderData, PostDataTypeFolderResponse, GetDataTypeFolderByIdData, GetDataTypeFolderByIdResponse, DeleteDataTypeFolderByIdData, DeleteDataTypeFolderByIdResponse, PutDataTypeFolderByIdData, PutDataTypeFolderByIdResponse, GetFilterDataTypeData, GetFilterDataTypeResponse, GetItemDataTypeData, GetItemDataTypeResponse, GetItemDataTypeSearchData, GetItemDataTypeSearchResponse, GetTreeDataTypeAncestorsData, GetTreeDataTypeAncestorsResponse, GetTreeDataTypeChildrenData, GetTreeDataTypeChildrenResponse, GetTreeDataTypeRootData, GetTreeDataTypeRootResponse, GetDictionaryData, GetDictionaryResponse, PostDictionaryData, PostDictionaryResponse, GetDictionaryByIdData, GetDictionaryByIdResponse, DeleteDictionaryByIdData, DeleteDictionaryByIdResponse, PutDictionaryByIdData, PutDictionaryByIdResponse, GetDictionaryByIdExportData, GetDictionaryByIdExportResponse, PutDictionaryByIdMoveData, PutDictionaryByIdMoveResponse, PostDictionaryImportData, PostDictionaryImportResponse, GetItemDictionaryData, GetItemDictionaryResponse, GetTreeDictionaryAncestorsData, GetTreeDictionaryAncestorsResponse, GetTreeDictionaryChildrenData, GetTreeDictionaryChildrenResponse, GetTreeDictionaryRootData, GetTreeDictionaryRootResponse, GetCollectionDocumentByIdData, GetCollectionDocumentByIdResponse, PostDocumentData, PostDocumentResponse, GetDocumentByIdData, GetDocumentByIdResponse, DeleteDocumentByIdData, DeleteDocumentByIdResponse, PutDocumentByIdData, PutDocumentByIdResponse, GetDocumentByIdAuditLogData, GetDocumentByIdAuditLogResponse, PostDocumentByIdCopyData, PostDocumentByIdCopyResponse, GetDocumentByIdDomainsData, GetDocumentByIdDomainsResponse, PutDocumentByIdDomainsData, PutDocumentByIdDomainsResponse, PutDocumentByIdMoveData, PutDocumentByIdMoveResponse, PutDocumentByIdMoveToRecycleBinData, PutDocumentByIdMoveToRecycleBinResponse, GetDocumentByIdNotificationsData, GetDocumentByIdNotificationsResponse, PutDocumentByIdNotificationsData, PutDocumentByIdNotificationsResponse, PostDocumentByIdPublicAccessData, PostDocumentByIdPublicAccessResponse, DeleteDocumentByIdPublicAccessData, DeleteDocumentByIdPublicAccessResponse, GetDocumentByIdPublicAccessData, GetDocumentByIdPublicAccessResponse, PutDocumentByIdPublicAccessData, PutDocumentByIdPublicAccessResponse, PutDocumentByIdPublishData, PutDocumentByIdPublishResponse, PutDocumentByIdPublishWithDescendantsData, PutDocumentByIdPublishWithDescendantsResponse, GetDocumentByIdPublishedData, GetDocumentByIdPublishedResponse, GetDocumentByIdReferencedByData, GetDocumentByIdReferencedByResponse, GetDocumentByIdReferencedDescendantsData, GetDocumentByIdReferencedDescendantsResponse, PutDocumentByIdUnpublishData, PutDocumentByIdUnpublishResponse, PutDocumentByIdValidateData, PutDocumentByIdValidateResponse, PutUmbracoManagementApiV11DocumentByIdValidate11Data, PutUmbracoManagementApiV11DocumentByIdValidate11Response, GetDocumentAreReferencedData, GetDocumentAreReferencedResponse, GetDocumentConfigurationResponse, PutDocumentSortData, PutDocumentSortResponse, GetDocumentUrlsData, GetDocumentUrlsResponse, PostDocumentValidateData, PostDocumentValidateResponse, GetItemDocumentData, GetItemDocumentResponse, GetItemDocumentSearchData, GetItemDocumentSearchResponse, DeleteRecycleBinDocumentResponse, DeleteRecycleBinDocumentByIdData, DeleteRecycleBinDocumentByIdResponse, GetRecycleBinDocumentByIdOriginalParentData, GetRecycleBinDocumentByIdOriginalParentResponse, PutRecycleBinDocumentByIdRestoreData, PutRecycleBinDocumentByIdRestoreResponse, GetRecycleBinDocumentChildrenData, GetRecycleBinDocumentChildrenResponse, GetRecycleBinDocumentRootData, GetRecycleBinDocumentRootResponse, GetTreeDocumentAncestorsData, GetTreeDocumentAncestorsResponse, GetTreeDocumentChildrenData, GetTreeDocumentChildrenResponse, GetTreeDocumentRootData, GetTreeDocumentRootResponse, PostDocumentBlueprintData, PostDocumentBlueprintResponse, GetDocumentBlueprintByIdData, GetDocumentBlueprintByIdResponse, DeleteDocumentBlueprintByIdData, DeleteDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdData, PutDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdMoveData, PutDocumentBlueprintByIdMoveResponse, PostDocumentBlueprintFolderData, PostDocumentBlueprintFolderResponse, GetDocumentBlueprintFolderByIdData, GetDocumentBlueprintFolderByIdResponse, DeleteDocumentBlueprintFolderByIdData, DeleteDocumentBlueprintFolderByIdResponse, PutDocumentBlueprintFolderByIdData, PutDocumentBlueprintFolderByIdResponse, PostDocumentBlueprintFromDocumentData, PostDocumentBlueprintFromDocumentResponse, GetItemDocumentBlueprintData, GetItemDocumentBlueprintResponse, GetTreeDocumentBlueprintAncestorsData, GetTreeDocumentBlueprintAncestorsResponse, GetTreeDocumentBlueprintChildrenData, GetTreeDocumentBlueprintChildrenResponse, GetTreeDocumentBlueprintRootData, GetTreeDocumentBlueprintRootResponse, PostDocumentTypeData, PostDocumentTypeResponse, GetDocumentTypeByIdData, GetDocumentTypeByIdResponse, DeleteDocumentTypeByIdData, DeleteDocumentTypeByIdResponse, PutDocumentTypeByIdData, PutDocumentTypeByIdResponse, GetDocumentTypeByIdAllowedChildrenData, GetDocumentTypeByIdAllowedChildrenResponse, GetDocumentTypeByIdBlueprintData, GetDocumentTypeByIdBlueprintResponse, GetDocumentTypeByIdCompositionReferencesData, GetDocumentTypeByIdCompositionReferencesResponse, PostDocumentTypeByIdCopyData, PostDocumentTypeByIdCopyResponse, GetDocumentTypeByIdExportData, GetDocumentTypeByIdExportResponse, PutDocumentTypeByIdImportData, PutDocumentTypeByIdImportResponse, PutDocumentTypeByIdMoveData, PutDocumentTypeByIdMoveResponse, GetDocumentTypeAllowedAtRootData, GetDocumentTypeAllowedAtRootResponse, PostDocumentTypeAvailableCompositionsData, PostDocumentTypeAvailableCompositionsResponse, GetDocumentTypeConfigurationResponse, PostDocumentTypeFolderData, PostDocumentTypeFolderResponse, GetDocumentTypeFolderByIdData, GetDocumentTypeFolderByIdResponse, DeleteDocumentTypeFolderByIdData, DeleteDocumentTypeFolderByIdResponse, PutDocumentTypeFolderByIdData, PutDocumentTypeFolderByIdResponse, PostDocumentTypeImportData, PostDocumentTypeImportResponse, GetItemDocumentTypeData, GetItemDocumentTypeResponse, GetItemDocumentTypeSearchData, GetItemDocumentTypeSearchResponse, GetTreeDocumentTypeAncestorsData, GetTreeDocumentTypeAncestorsResponse, GetTreeDocumentTypeChildrenData, GetTreeDocumentTypeChildrenResponse, GetTreeDocumentTypeRootData, GetTreeDocumentTypeRootResponse, GetDocumentVersionData, GetDocumentVersionResponse, GetDocumentVersionByIdData, GetDocumentVersionByIdResponse, PutDocumentVersionByIdPreventCleanupData, PutDocumentVersionByIdPreventCleanupResponse, PostDocumentVersionByIdRollbackData, PostDocumentVersionByIdRollbackResponse, PostDynamicRootQueryData, PostDynamicRootQueryResponse, GetDynamicRootStepsResponse, GetHealthCheckGroupData, GetHealthCheckGroupResponse, GetHealthCheckGroupByNameData, GetHealthCheckGroupByNameResponse, PostHealthCheckGroupByNameCheckData, PostHealthCheckGroupByNameCheckResponse, PostHealthCheckExecuteActionData, PostHealthCheckExecuteActionResponse, GetHelpData, GetHelpResponse, GetImagingResizeUrlsData, GetImagingResizeUrlsResponse, GetImportAnalyzeData, GetImportAnalyzeResponse, GetIndexerData, GetIndexerResponse, GetIndexerByIndexNameData, GetIndexerByIndexNameResponse, PostIndexerByIndexNameRebuildData, PostIndexerByIndexNameRebuildResponse, GetInstallSettingsResponse, PostInstallSetupData, PostInstallSetupResponse, PostInstallValidateDatabaseData, PostInstallValidateDatabaseResponse, GetItemLanguageData, GetItemLanguageResponse, GetItemLanguageDefaultResponse, GetLanguageData, GetLanguageResponse, PostLanguageData, PostLanguageResponse, GetLanguageByIsoCodeData, GetLanguageByIsoCodeResponse, DeleteLanguageByIsoCodeData, DeleteLanguageByIsoCodeResponse, PutLanguageByIsoCodeData, PutLanguageByIsoCodeResponse, GetLogViewerLevelData, GetLogViewerLevelResponse, GetLogViewerLevelCountData, GetLogViewerLevelCountResponse, GetLogViewerLogData, GetLogViewerLogResponse, GetLogViewerMessageTemplateData, GetLogViewerMessageTemplateResponse, GetLogViewerSavedSearchData, GetLogViewerSavedSearchResponse, PostLogViewerSavedSearchData, PostLogViewerSavedSearchResponse, GetLogViewerSavedSearchByNameData, GetLogViewerSavedSearchByNameResponse, DeleteLogViewerSavedSearchByNameData, DeleteLogViewerSavedSearchByNameResponse, GetLogViewerValidateLogsSizeData, GetLogViewerValidateLogsSizeResponse, GetManifestManifestResponse, GetManifestManifestPrivateResponse, GetManifestManifestPublicResponse, GetCollectionMediaData, GetCollectionMediaResponse, GetItemMediaData, GetItemMediaResponse, GetItemMediaSearchData, GetItemMediaSearchResponse, PostMediaData, PostMediaResponse, GetMediaByIdData, GetMediaByIdResponse, DeleteMediaByIdData, DeleteMediaByIdResponse, PutMediaByIdData, PutMediaByIdResponse, GetMediaByIdAuditLogData, GetMediaByIdAuditLogResponse, PutMediaByIdMoveData, PutMediaByIdMoveResponse, PutMediaByIdMoveToRecycleBinData, PutMediaByIdMoveToRecycleBinResponse, GetMediaByIdReferencedByData, GetMediaByIdReferencedByResponse, GetMediaByIdReferencedDescendantsData, GetMediaByIdReferencedDescendantsResponse, PutMediaByIdValidateData, PutMediaByIdValidateResponse, GetMediaAreReferencedData, GetMediaAreReferencedResponse, GetMediaConfigurationResponse, PutMediaSortData, PutMediaSortResponse, GetMediaUrlsData, GetMediaUrlsResponse, PostMediaValidateData, PostMediaValidateResponse, DeleteRecycleBinMediaResponse, DeleteRecycleBinMediaByIdData, DeleteRecycleBinMediaByIdResponse, GetRecycleBinMediaByIdOriginalParentData, GetRecycleBinMediaByIdOriginalParentResponse, PutRecycleBinMediaByIdRestoreData, PutRecycleBinMediaByIdRestoreResponse, GetRecycleBinMediaChildrenData, GetRecycleBinMediaChildrenResponse, GetRecycleBinMediaRootData, GetRecycleBinMediaRootResponse, GetTreeMediaAncestorsData, GetTreeMediaAncestorsResponse, GetTreeMediaChildrenData, GetTreeMediaChildrenResponse, GetTreeMediaRootData, GetTreeMediaRootResponse, GetItemMediaTypeData, GetItemMediaTypeResponse, GetItemMediaTypeAllowedData, GetItemMediaTypeAllowedResponse, GetItemMediaTypeFoldersData, GetItemMediaTypeFoldersResponse, GetItemMediaTypeSearchData, GetItemMediaTypeSearchResponse, PostMediaTypeData, PostMediaTypeResponse, GetMediaTypeByIdData, GetMediaTypeByIdResponse, DeleteMediaTypeByIdData, DeleteMediaTypeByIdResponse, PutMediaTypeByIdData, PutMediaTypeByIdResponse, GetMediaTypeByIdAllowedChildrenData, GetMediaTypeByIdAllowedChildrenResponse, GetMediaTypeByIdCompositionReferencesData, GetMediaTypeByIdCompositionReferencesResponse, PostMediaTypeByIdCopyData, PostMediaTypeByIdCopyResponse, GetMediaTypeByIdExportData, GetMediaTypeByIdExportResponse, PutMediaTypeByIdImportData, PutMediaTypeByIdImportResponse, PutMediaTypeByIdMoveData, PutMediaTypeByIdMoveResponse, GetMediaTypeAllowedAtRootData, GetMediaTypeAllowedAtRootResponse, PostMediaTypeAvailableCompositionsData, PostMediaTypeAvailableCompositionsResponse, GetMediaTypeConfigurationResponse, PostMediaTypeFolderData, PostMediaTypeFolderResponse, GetMediaTypeFolderByIdData, GetMediaTypeFolderByIdResponse, DeleteMediaTypeFolderByIdData, DeleteMediaTypeFolderByIdResponse, PutMediaTypeFolderByIdData, PutMediaTypeFolderByIdResponse, PostMediaTypeImportData, PostMediaTypeImportResponse, GetTreeMediaTypeAncestorsData, GetTreeMediaTypeAncestorsResponse, GetTreeMediaTypeChildrenData, GetTreeMediaTypeChildrenResponse, GetTreeMediaTypeRootData, GetTreeMediaTypeRootResponse, GetFilterMemberData, GetFilterMemberResponse, GetItemMemberData, GetItemMemberResponse, GetItemMemberSearchData, GetItemMemberSearchResponse, PostMemberData, PostMemberResponse, GetMemberByIdData, GetMemberByIdResponse, DeleteMemberByIdData, DeleteMemberByIdResponse, PutMemberByIdData, PutMemberByIdResponse, PutMemberByIdValidateData, PutMemberByIdValidateResponse, GetMemberConfigurationResponse, PostMemberValidateData, PostMemberValidateResponse, GetItemMemberGroupData, GetItemMemberGroupResponse, GetMemberGroupData, GetMemberGroupResponse, PostMemberGroupData, PostMemberGroupResponse, GetMemberGroupByIdData, GetMemberGroupByIdResponse, DeleteMemberGroupByIdData, DeleteMemberGroupByIdResponse, PutMemberGroupByIdData, PutMemberGroupByIdResponse, GetTreeMemberGroupRootData, GetTreeMemberGroupRootResponse, GetItemMemberTypeData, GetItemMemberTypeResponse, GetItemMemberTypeSearchData, GetItemMemberTypeSearchResponse, PostMemberTypeData, PostMemberTypeResponse, GetMemberTypeByIdData, GetMemberTypeByIdResponse, DeleteMemberTypeByIdData, DeleteMemberTypeByIdResponse, PutMemberTypeByIdData, PutMemberTypeByIdResponse, GetMemberTypeByIdCompositionReferencesData, GetMemberTypeByIdCompositionReferencesResponse, PostMemberTypeByIdCopyData, PostMemberTypeByIdCopyResponse, PostMemberTypeAvailableCompositionsData, PostMemberTypeAvailableCompositionsResponse, GetMemberTypeConfigurationResponse, GetTreeMemberTypeRootData, GetTreeMemberTypeRootResponse, PostModelsBuilderBuildResponse, GetModelsBuilderDashboardResponse, GetModelsBuilderStatusResponse, GetObjectTypesData, GetObjectTypesResponse, GetOembedQueryData, GetOembedQueryResponse, PostPackageByNameRunMigrationData, PostPackageByNameRunMigrationResponse, GetPackageConfigurationResponse, GetPackageCreatedData, GetPackageCreatedResponse, PostPackageCreatedData, PostPackageCreatedResponse, GetPackageCreatedByIdData, GetPackageCreatedByIdResponse, DeletePackageCreatedByIdData, DeletePackageCreatedByIdResponse, PutPackageCreatedByIdData, PutPackageCreatedByIdResponse, GetPackageCreatedByIdDownloadData, GetPackageCreatedByIdDownloadResponse, GetPackageMigrationStatusData, GetPackageMigrationStatusResponse, GetItemPartialViewData, GetItemPartialViewResponse, PostPartialViewData, PostPartialViewResponse, GetPartialViewByPathData, GetPartialViewByPathResponse, DeletePartialViewByPathData, DeletePartialViewByPathResponse, PutPartialViewByPathData, PutPartialViewByPathResponse, PutPartialViewByPathRenameData, PutPartialViewByPathRenameResponse, PostPartialViewFolderData, PostPartialViewFolderResponse, GetPartialViewFolderByPathData, GetPartialViewFolderByPathResponse, DeletePartialViewFolderByPathData, DeletePartialViewFolderByPathResponse, GetPartialViewSnippetData, GetPartialViewSnippetResponse, GetPartialViewSnippetByIdData, GetPartialViewSnippetByIdResponse, GetTreePartialViewAncestorsData, GetTreePartialViewAncestorsResponse, GetTreePartialViewChildrenData, GetTreePartialViewChildrenResponse, GetTreePartialViewRootData, GetTreePartialViewRootResponse, DeletePreviewResponse, PostPreviewResponse, GetProfilingStatusResponse, PutProfilingStatusData, PutProfilingStatusResponse, GetPropertyTypeIsUsedData, GetPropertyTypeIsUsedResponse, PostPublishedCacheRebuildResponse, GetPublishedCacheRebuildStatusResponse, PostPublishedCacheReloadResponse, GetRedirectManagementData, GetRedirectManagementResponse, GetRedirectManagementByIdData, GetRedirectManagementByIdResponse, DeleteRedirectManagementByIdData, DeleteRedirectManagementByIdResponse, GetRedirectManagementStatusResponse, PostRedirectManagementStatusData, PostRedirectManagementStatusResponse, GetRelationByRelationTypeIdData, GetRelationByRelationTypeIdResponse, GetItemRelationTypeData, GetItemRelationTypeResponse, GetRelationTypeData, GetRelationTypeResponse, GetRelationTypeByIdData, GetRelationTypeByIdResponse, GetItemScriptData, GetItemScriptResponse, PostScriptData, PostScriptResponse, GetScriptByPathData, GetScriptByPathResponse, DeleteScriptByPathData, DeleteScriptByPathResponse, PutScriptByPathData, PutScriptByPathResponse, PutScriptByPathRenameData, PutScriptByPathRenameResponse, PostScriptFolderData, PostScriptFolderResponse, GetScriptFolderByPathData, GetScriptFolderByPathResponse, DeleteScriptFolderByPathData, DeleteScriptFolderByPathResponse, GetTreeScriptAncestorsData, GetTreeScriptAncestorsResponse, GetTreeScriptChildrenData, GetTreeScriptChildrenResponse, GetTreeScriptRootData, GetTreeScriptRootResponse, GetSearcherData, GetSearcherResponse, GetSearcherBySearcherNameQueryData, GetSearcherBySearcherNameQueryResponse, GetSecurityConfigurationResponse, PostSecurityForgotPasswordData, PostSecurityForgotPasswordResponse, PostSecurityForgotPasswordResetData, PostSecurityForgotPasswordResetResponse, PostSecurityForgotPasswordVerifyData, PostSecurityForgotPasswordVerifyResponse, GetSegmentData, GetSegmentResponse, GetServerConfigurationResponse, GetServerInformationResponse, GetServerStatusResponse, GetServerTroubleshootingResponse, GetServerUpgradeCheckResponse, GetItemStaticFileData, GetItemStaticFileResponse, GetTreeStaticFileAncestorsData, GetTreeStaticFileAncestorsResponse, GetTreeStaticFileChildrenData, GetTreeStaticFileChildrenResponse, GetTreeStaticFileRootData, GetTreeStaticFileRootResponse, GetItemStylesheetData, GetItemStylesheetResponse, PostStylesheetData, PostStylesheetResponse, GetStylesheetByPathData, GetStylesheetByPathResponse, DeleteStylesheetByPathData, DeleteStylesheetByPathResponse, PutStylesheetByPathData, PutStylesheetByPathResponse, PutStylesheetByPathRenameData, PutStylesheetByPathRenameResponse, PostStylesheetFolderData, PostStylesheetFolderResponse, GetStylesheetFolderByPathData, GetStylesheetFolderByPathResponse, DeleteStylesheetFolderByPathData, DeleteStylesheetFolderByPathResponse, GetTreeStylesheetAncestorsData, GetTreeStylesheetAncestorsResponse, GetTreeStylesheetChildrenData, GetTreeStylesheetChildrenResponse, GetTreeStylesheetRootData, GetTreeStylesheetRootResponse, GetTagData, GetTagResponse, GetTelemetryData, GetTelemetryResponse, GetTelemetryLevelResponse, PostTelemetryLevelData, PostTelemetryLevelResponse, GetItemTemplateData, GetItemTemplateResponse, GetItemTemplateSearchData, GetItemTemplateSearchResponse, PostTemplateData, PostTemplateResponse, GetTemplateByIdData, GetTemplateByIdResponse, DeleteTemplateByIdData, DeleteTemplateByIdResponse, PutTemplateByIdData, PutTemplateByIdResponse, GetTemplateConfigurationResponse, PostTemplateQueryExecuteData, PostTemplateQueryExecuteResponse, GetTemplateQuerySettingsResponse, GetTreeTemplateAncestorsData, GetTreeTemplateAncestorsResponse, GetTreeTemplateChildrenData, GetTreeTemplateChildrenResponse, GetTreeTemplateRootData, GetTreeTemplateRootResponse, PostTemporaryFileData, PostTemporaryFileResponse, GetTemporaryFileByIdData, GetTemporaryFileByIdResponse, DeleteTemporaryFileByIdData, DeleteTemporaryFileByIdResponse, GetTemporaryFileConfigurationResponse, PostUpgradeAuthorizeResponse, GetUpgradeSettingsResponse, GetFilterUserData, GetFilterUserResponse, GetItemUserData, GetItemUserResponse, PostUserData, PostUserResponse, DeleteUserData, DeleteUserResponse, GetUserData, GetUserResponse, GetUserByIdData, GetUserByIdResponse, DeleteUserByIdData, DeleteUserByIdResponse, PutUserByIdData, PutUserByIdResponse, GetUserById2FaData, GetUserById2FaResponse, DeleteUserById2FaByProviderNameData, DeleteUserById2FaByProviderNameResponse, GetUserByIdCalculateStartNodesData, GetUserByIdCalculateStartNodesResponse, PostUserByIdChangePasswordData, PostUserByIdChangePasswordResponse, PostUserByIdClientCredentialsData, PostUserByIdClientCredentialsResponse, GetUserByIdClientCredentialsData, GetUserByIdClientCredentialsResponse, DeleteUserByIdClientCredentialsByClientIdData, DeleteUserByIdClientCredentialsByClientIdResponse, PostUserByIdResetPasswordData, PostUserByIdResetPasswordResponse, DeleteUserAvatarByIdData, DeleteUserAvatarByIdResponse, PostUserAvatarByIdData, PostUserAvatarByIdResponse, GetUserConfigurationResponse, GetUserCurrentResponse, GetUserCurrent2FaResponse, DeleteUserCurrent2FaByProviderNameData, DeleteUserCurrent2FaByProviderNameResponse, PostUserCurrent2FaByProviderNameData, PostUserCurrent2FaByProviderNameResponse, GetUserCurrent2FaByProviderNameData, GetUserCurrent2FaByProviderNameResponse, PostUserCurrentAvatarData, PostUserCurrentAvatarResponse, PostUserCurrentChangePasswordData, PostUserCurrentChangePasswordResponse, GetUserCurrentConfigurationResponse, GetUserCurrentLoginProvidersResponse, GetUserCurrentPermissionsData, GetUserCurrentPermissionsResponse, GetUserCurrentPermissionsDocumentData, GetUserCurrentPermissionsDocumentResponse, GetUserCurrentPermissionsMediaData, GetUserCurrentPermissionsMediaResponse, PostUserDisableData, PostUserDisableResponse, PostUserEnableData, PostUserEnableResponse, PostUserInviteData, PostUserInviteResponse, PostUserInviteCreatePasswordData, PostUserInviteCreatePasswordResponse, PostUserInviteResendData, PostUserInviteResendResponse, PostUserInviteVerifyData, PostUserInviteVerifyResponse, PostUserSetUserGroupsData, PostUserSetUserGroupsResponse, PostUserUnlockData, PostUserUnlockResponse, PostUserDataData, PostUserDataResponse, GetUserDataData, GetUserDataResponse, PutUserDataData, PutUserDataResponse, GetUserDataByIdData, GetUserDataByIdResponse, GetFilterUserGroupData, GetFilterUserGroupResponse, GetItemUserGroupData, GetItemUserGroupResponse, DeleteUserGroupData, DeleteUserGroupResponse, PostUserGroupData, PostUserGroupResponse, GetUserGroupData, GetUserGroupResponse, GetUserGroupByIdData, GetUserGroupByIdResponse, DeleteUserGroupByIdData, DeleteUserGroupByIdResponse, PutUserGroupByIdData, PutUserGroupByIdResponse, DeleteUserGroupByIdUsersData, DeleteUserGroupByIdUsersResponse, PostUserGroupByIdUsersData, PostUserGroupByIdUsersResponse, GetItemWebhookData, GetItemWebhookResponse, GetWebhookData, GetWebhookResponse, PostWebhookData, PostWebhookResponse, GetWebhookByIdData, GetWebhookByIdResponse, DeleteWebhookByIdData, DeleteWebhookByIdResponse, PutWebhookByIdData, PutWebhookByIdResponse, GetWebhookByIdLogsData, GetWebhookByIdLogsResponse, GetWebhookEventsData, GetWebhookEventsResponse, GetWebhookLogsData, GetWebhookLogsResponse } from './types.gen';
+import type { GetCultureData, GetCultureResponse, PostDataTypeData, PostDataTypeResponse, GetDataTypeByIdData, GetDataTypeByIdResponse, DeleteDataTypeByIdData, DeleteDataTypeByIdResponse, PutDataTypeByIdData, PutDataTypeByIdResponse, PostDataTypeByIdCopyData, PostDataTypeByIdCopyResponse, GetDataTypeByIdIsUsedData, GetDataTypeByIdIsUsedResponse, PutDataTypeByIdMoveData, PutDataTypeByIdMoveResponse, GetDataTypeByIdReferencesData, GetDataTypeByIdReferencesResponse, GetDataTypeConfigurationResponse, PostDataTypeFolderData, PostDataTypeFolderResponse, GetDataTypeFolderByIdData, GetDataTypeFolderByIdResponse, DeleteDataTypeFolderByIdData, DeleteDataTypeFolderByIdResponse, PutDataTypeFolderByIdData, PutDataTypeFolderByIdResponse, GetFilterDataTypeData, GetFilterDataTypeResponse, GetItemDataTypeData, GetItemDataTypeResponse, GetItemDataTypeSearchData, GetItemDataTypeSearchResponse, GetTreeDataTypeAncestorsData, GetTreeDataTypeAncestorsResponse, GetTreeDataTypeChildrenData, GetTreeDataTypeChildrenResponse, GetTreeDataTypeRootData, GetTreeDataTypeRootResponse, GetDictionaryData, GetDictionaryResponse, PostDictionaryData, PostDictionaryResponse, GetDictionaryByIdData, GetDictionaryByIdResponse, DeleteDictionaryByIdData, DeleteDictionaryByIdResponse, PutDictionaryByIdData, PutDictionaryByIdResponse, GetDictionaryByIdExportData, GetDictionaryByIdExportResponse, PutDictionaryByIdMoveData, PutDictionaryByIdMoveResponse, PostDictionaryImportData, PostDictionaryImportResponse, GetItemDictionaryData, GetItemDictionaryResponse, GetTreeDictionaryAncestorsData, GetTreeDictionaryAncestorsResponse, GetTreeDictionaryChildrenData, GetTreeDictionaryChildrenResponse, GetTreeDictionaryRootData, GetTreeDictionaryRootResponse, GetCollectionDocumentByIdData, GetCollectionDocumentByIdResponse, PostDocumentData, PostDocumentResponse, GetDocumentByIdData, GetDocumentByIdResponse, DeleteDocumentByIdData, DeleteDocumentByIdResponse, PutDocumentByIdData, PutDocumentByIdResponse, GetDocumentByIdAuditLogData, GetDocumentByIdAuditLogResponse, PostDocumentByIdCopyData, PostDocumentByIdCopyResponse, GetDocumentByIdDomainsData, GetDocumentByIdDomainsResponse, PutDocumentByIdDomainsData, PutDocumentByIdDomainsResponse, PutDocumentByIdMoveData, PutDocumentByIdMoveResponse, PutDocumentByIdMoveToRecycleBinData, PutDocumentByIdMoveToRecycleBinResponse, GetDocumentByIdNotificationsData, GetDocumentByIdNotificationsResponse, PutDocumentByIdNotificationsData, PutDocumentByIdNotificationsResponse, PostDocumentByIdPublicAccessData, PostDocumentByIdPublicAccessResponse, DeleteDocumentByIdPublicAccessData, DeleteDocumentByIdPublicAccessResponse, GetDocumentByIdPublicAccessData, GetDocumentByIdPublicAccessResponse, PutDocumentByIdPublicAccessData, PutDocumentByIdPublicAccessResponse, PutDocumentByIdPublishData, PutDocumentByIdPublishResponse, PutDocumentByIdPublishWithDescendantsData, PutDocumentByIdPublishWithDescendantsResponse, GetDocumentByIdPublishedData, GetDocumentByIdPublishedResponse, GetDocumentByIdReferencedByData, GetDocumentByIdReferencedByResponse, GetDocumentByIdReferencedDescendantsData, GetDocumentByIdReferencedDescendantsResponse, PutDocumentByIdUnpublishData, PutDocumentByIdUnpublishResponse, PutDocumentByIdValidateData, PutDocumentByIdValidateResponse, PutUmbracoManagementApiV11DocumentByIdValidate11Data, PutUmbracoManagementApiV11DocumentByIdValidate11Response, GetDocumentAreReferencedData, GetDocumentAreReferencedResponse, GetDocumentConfigurationResponse, PutDocumentSortData, PutDocumentSortResponse, GetDocumentUrlsData, GetDocumentUrlsResponse, PostDocumentValidateData, PostDocumentValidateResponse, GetItemDocumentData, GetItemDocumentResponse, GetItemDocumentSearchData, GetItemDocumentSearchResponse, DeleteRecycleBinDocumentResponse, DeleteRecycleBinDocumentByIdData, DeleteRecycleBinDocumentByIdResponse, GetRecycleBinDocumentByIdOriginalParentData, GetRecycleBinDocumentByIdOriginalParentResponse, PutRecycleBinDocumentByIdRestoreData, PutRecycleBinDocumentByIdRestoreResponse, GetRecycleBinDocumentChildrenData, GetRecycleBinDocumentChildrenResponse, GetRecycleBinDocumentRootData, GetRecycleBinDocumentRootResponse, GetTreeDocumentAncestorsData, GetTreeDocumentAncestorsResponse, GetTreeDocumentChildrenData, GetTreeDocumentChildrenResponse, GetTreeDocumentRootData, GetTreeDocumentRootResponse, PostDocumentBlueprintData, PostDocumentBlueprintResponse, GetDocumentBlueprintByIdData, GetDocumentBlueprintByIdResponse, DeleteDocumentBlueprintByIdData, DeleteDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdData, PutDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdMoveData, PutDocumentBlueprintByIdMoveResponse, PostDocumentBlueprintFolderData, PostDocumentBlueprintFolderResponse, GetDocumentBlueprintFolderByIdData, GetDocumentBlueprintFolderByIdResponse, DeleteDocumentBlueprintFolderByIdData, DeleteDocumentBlueprintFolderByIdResponse, PutDocumentBlueprintFolderByIdData, PutDocumentBlueprintFolderByIdResponse, PostDocumentBlueprintFromDocumentData, PostDocumentBlueprintFromDocumentResponse, GetItemDocumentBlueprintData, GetItemDocumentBlueprintResponse, GetTreeDocumentBlueprintAncestorsData, GetTreeDocumentBlueprintAncestorsResponse, GetTreeDocumentBlueprintChildrenData, GetTreeDocumentBlueprintChildrenResponse, GetTreeDocumentBlueprintRootData, GetTreeDocumentBlueprintRootResponse, PostDocumentTypeData, PostDocumentTypeResponse, GetDocumentTypeByIdData, GetDocumentTypeByIdResponse, DeleteDocumentTypeByIdData, DeleteDocumentTypeByIdResponse, PutDocumentTypeByIdData, PutDocumentTypeByIdResponse, GetDocumentTypeByIdAllowedChildrenData, GetDocumentTypeByIdAllowedChildrenResponse, GetDocumentTypeByIdBlueprintData, GetDocumentTypeByIdBlueprintResponse, GetDocumentTypeByIdCompositionReferencesData, GetDocumentTypeByIdCompositionReferencesResponse, PostDocumentTypeByIdCopyData, PostDocumentTypeByIdCopyResponse, GetDocumentTypeByIdExportData, GetDocumentTypeByIdExportResponse, PutDocumentTypeByIdImportData, PutDocumentTypeByIdImportResponse, PutDocumentTypeByIdMoveData, PutDocumentTypeByIdMoveResponse, GetDocumentTypeAllowedAtRootData, GetDocumentTypeAllowedAtRootResponse, PostDocumentTypeAvailableCompositionsData, PostDocumentTypeAvailableCompositionsResponse, GetDocumentTypeConfigurationResponse, PostDocumentTypeFolderData, PostDocumentTypeFolderResponse, GetDocumentTypeFolderByIdData, GetDocumentTypeFolderByIdResponse, DeleteDocumentTypeFolderByIdData, DeleteDocumentTypeFolderByIdResponse, PutDocumentTypeFolderByIdData, PutDocumentTypeFolderByIdResponse, PostDocumentTypeImportData, PostDocumentTypeImportResponse, GetItemDocumentTypeData, GetItemDocumentTypeResponse, GetItemDocumentTypeSearchData, GetItemDocumentTypeSearchResponse, GetTreeDocumentTypeAncestorsData, GetTreeDocumentTypeAncestorsResponse, GetTreeDocumentTypeChildrenData, GetTreeDocumentTypeChildrenResponse, GetTreeDocumentTypeRootData, GetTreeDocumentTypeRootResponse, GetDocumentVersionData, GetDocumentVersionResponse, GetDocumentVersionByIdData, GetDocumentVersionByIdResponse, PutDocumentVersionByIdPreventCleanupData, PutDocumentVersionByIdPreventCleanupResponse, PostDocumentVersionByIdRollbackData, PostDocumentVersionByIdRollbackResponse, PostDynamicRootQueryData, PostDynamicRootQueryResponse, GetDynamicRootStepsResponse, GetHealthCheckGroupData, GetHealthCheckGroupResponse, GetHealthCheckGroupByNameData, GetHealthCheckGroupByNameResponse, PostHealthCheckGroupByNameCheckData, PostHealthCheckGroupByNameCheckResponse, PostHealthCheckExecuteActionData, PostHealthCheckExecuteActionResponse, GetHelpData, GetHelpResponse, GetImagingResizeUrlsData, GetImagingResizeUrlsResponse, GetImportAnalyzeData, GetImportAnalyzeResponse, GetIndexerData, GetIndexerResponse, GetIndexerByIndexNameData, GetIndexerByIndexNameResponse, PostIndexerByIndexNameRebuildData, PostIndexerByIndexNameRebuildResponse, GetInstallSettingsResponse, PostInstallSetupData, PostInstallSetupResponse, PostInstallValidateDatabaseData, PostInstallValidateDatabaseResponse, GetItemLanguageData, GetItemLanguageResponse, GetItemLanguageDefaultResponse, GetLanguageData, GetLanguageResponse, PostLanguageData, PostLanguageResponse, GetLanguageByIsoCodeData, GetLanguageByIsoCodeResponse, DeleteLanguageByIsoCodeData, DeleteLanguageByIsoCodeResponse, PutLanguageByIsoCodeData, PutLanguageByIsoCodeResponse, GetLogViewerLevelData, GetLogViewerLevelResponse, GetLogViewerLevelCountData, GetLogViewerLevelCountResponse, GetLogViewerLogData, GetLogViewerLogResponse, GetLogViewerMessageTemplateData, GetLogViewerMessageTemplateResponse, GetLogViewerSavedSearchData, GetLogViewerSavedSearchResponse, PostLogViewerSavedSearchData, PostLogViewerSavedSearchResponse, GetLogViewerSavedSearchByNameData, GetLogViewerSavedSearchByNameResponse, DeleteLogViewerSavedSearchByNameData, DeleteLogViewerSavedSearchByNameResponse, GetLogViewerValidateLogsSizeData, GetLogViewerValidateLogsSizeResponse, GetManifestManifestResponse, GetManifestManifestPrivateResponse, GetManifestManifestPublicResponse, GetCollectionMediaData, GetCollectionMediaResponse, GetItemMediaData, GetItemMediaResponse, GetItemMediaSearchData, GetItemMediaSearchResponse, PostMediaData, PostMediaResponse, GetMediaByIdData, GetMediaByIdResponse, DeleteMediaByIdData, DeleteMediaByIdResponse, PutMediaByIdData, PutMediaByIdResponse, GetMediaByIdAuditLogData, GetMediaByIdAuditLogResponse, PutMediaByIdMoveData, PutMediaByIdMoveResponse, PutMediaByIdMoveToRecycleBinData, PutMediaByIdMoveToRecycleBinResponse, GetMediaByIdReferencedByData, GetMediaByIdReferencedByResponse, GetMediaByIdReferencedDescendantsData, GetMediaByIdReferencedDescendantsResponse, PutMediaByIdValidateData, PutMediaByIdValidateResponse, GetMediaAreReferencedData, GetMediaAreReferencedResponse, GetMediaConfigurationResponse, PutMediaSortData, PutMediaSortResponse, GetMediaUrlsData, GetMediaUrlsResponse, PostMediaValidateData, PostMediaValidateResponse, DeleteRecycleBinMediaResponse, DeleteRecycleBinMediaByIdData, DeleteRecycleBinMediaByIdResponse, GetRecycleBinMediaByIdOriginalParentData, GetRecycleBinMediaByIdOriginalParentResponse, PutRecycleBinMediaByIdRestoreData, PutRecycleBinMediaByIdRestoreResponse, GetRecycleBinMediaChildrenData, GetRecycleBinMediaChildrenResponse, GetRecycleBinMediaRootData, GetRecycleBinMediaRootResponse, GetTreeMediaAncestorsData, GetTreeMediaAncestorsResponse, GetTreeMediaChildrenData, GetTreeMediaChildrenResponse, GetTreeMediaRootData, GetTreeMediaRootResponse, GetItemMediaTypeData, GetItemMediaTypeResponse, GetItemMediaTypeAllowedData, GetItemMediaTypeAllowedResponse, GetItemMediaTypeFoldersData, GetItemMediaTypeFoldersResponse, GetItemMediaTypeSearchData, GetItemMediaTypeSearchResponse, PostMediaTypeData, PostMediaTypeResponse, GetMediaTypeByIdData, GetMediaTypeByIdResponse, DeleteMediaTypeByIdData, DeleteMediaTypeByIdResponse, PutMediaTypeByIdData, PutMediaTypeByIdResponse, GetMediaTypeByIdAllowedChildrenData, GetMediaTypeByIdAllowedChildrenResponse, GetMediaTypeByIdCompositionReferencesData, GetMediaTypeByIdCompositionReferencesResponse, PostMediaTypeByIdCopyData, PostMediaTypeByIdCopyResponse, GetMediaTypeByIdExportData, GetMediaTypeByIdExportResponse, PutMediaTypeByIdImportData, PutMediaTypeByIdImportResponse, PutMediaTypeByIdMoveData, PutMediaTypeByIdMoveResponse, GetMediaTypeAllowedAtRootData, GetMediaTypeAllowedAtRootResponse, PostMediaTypeAvailableCompositionsData, PostMediaTypeAvailableCompositionsResponse, GetMediaTypeConfigurationResponse, PostMediaTypeFolderData, PostMediaTypeFolderResponse, GetMediaTypeFolderByIdData, GetMediaTypeFolderByIdResponse, DeleteMediaTypeFolderByIdData, DeleteMediaTypeFolderByIdResponse, PutMediaTypeFolderByIdData, PutMediaTypeFolderByIdResponse, PostMediaTypeImportData, PostMediaTypeImportResponse, GetTreeMediaTypeAncestorsData, GetTreeMediaTypeAncestorsResponse, GetTreeMediaTypeChildrenData, GetTreeMediaTypeChildrenResponse, GetTreeMediaTypeRootData, GetTreeMediaTypeRootResponse, GetFilterMemberData, GetFilterMemberResponse, GetItemMemberData, GetItemMemberResponse, GetItemMemberSearchData, GetItemMemberSearchResponse, PostMemberData, PostMemberResponse, GetMemberByIdData, GetMemberByIdResponse, DeleteMemberByIdData, DeleteMemberByIdResponse, PutMemberByIdData, PutMemberByIdResponse, GetMemberByIdReferencedByData, GetMemberByIdReferencedByResponse, GetMemberByIdReferencedDescendantsData, GetMemberByIdReferencedDescendantsResponse, PutMemberByIdValidateData, PutMemberByIdValidateResponse, GetMemberAreReferencedData, GetMemberAreReferencedResponse, GetMemberConfigurationResponse, PostMemberValidateData, PostMemberValidateResponse, GetItemMemberGroupData, GetItemMemberGroupResponse, GetMemberGroupData, GetMemberGroupResponse, PostMemberGroupData, PostMemberGroupResponse, GetMemberGroupByIdData, GetMemberGroupByIdResponse, DeleteMemberGroupByIdData, DeleteMemberGroupByIdResponse, PutMemberGroupByIdData, PutMemberGroupByIdResponse, GetTreeMemberGroupRootData, GetTreeMemberGroupRootResponse, GetItemMemberTypeData, GetItemMemberTypeResponse, GetItemMemberTypeSearchData, GetItemMemberTypeSearchResponse, PostMemberTypeData, PostMemberTypeResponse, GetMemberTypeByIdData, GetMemberTypeByIdResponse, DeleteMemberTypeByIdData, DeleteMemberTypeByIdResponse, PutMemberTypeByIdData, PutMemberTypeByIdResponse, GetMemberTypeByIdCompositionReferencesData, GetMemberTypeByIdCompositionReferencesResponse, PostMemberTypeByIdCopyData, PostMemberTypeByIdCopyResponse, PostMemberTypeAvailableCompositionsData, PostMemberTypeAvailableCompositionsResponse, GetMemberTypeConfigurationResponse, GetTreeMemberTypeRootData, GetTreeMemberTypeRootResponse, PostModelsBuilderBuildResponse, GetModelsBuilderDashboardResponse, GetModelsBuilderStatusResponse, GetObjectTypesData, GetObjectTypesResponse, GetOembedQueryData, GetOembedQueryResponse, PostPackageByNameRunMigrationData, PostPackageByNameRunMigrationResponse, GetPackageConfigurationResponse, GetPackageCreatedData, GetPackageCreatedResponse, PostPackageCreatedData, PostPackageCreatedResponse, GetPackageCreatedByIdData, GetPackageCreatedByIdResponse, DeletePackageCreatedByIdData, DeletePackageCreatedByIdResponse, PutPackageCreatedByIdData, PutPackageCreatedByIdResponse, GetPackageCreatedByIdDownloadData, GetPackageCreatedByIdDownloadResponse, GetPackageMigrationStatusData, GetPackageMigrationStatusResponse, GetItemPartialViewData, GetItemPartialViewResponse, PostPartialViewData, PostPartialViewResponse, GetPartialViewByPathData, GetPartialViewByPathResponse, DeletePartialViewByPathData, DeletePartialViewByPathResponse, PutPartialViewByPathData, PutPartialViewByPathResponse, PutPartialViewByPathRenameData, PutPartialViewByPathRenameResponse, PostPartialViewFolderData, PostPartialViewFolderResponse, GetPartialViewFolderByPathData, GetPartialViewFolderByPathResponse, DeletePartialViewFolderByPathData, DeletePartialViewFolderByPathResponse, GetPartialViewSnippetData, GetPartialViewSnippetResponse, GetPartialViewSnippetByIdData, GetPartialViewSnippetByIdResponse, GetTreePartialViewAncestorsData, GetTreePartialViewAncestorsResponse, GetTreePartialViewChildrenData, GetTreePartialViewChildrenResponse, GetTreePartialViewRootData, GetTreePartialViewRootResponse, DeletePreviewResponse, PostPreviewResponse, GetProfilingStatusResponse, PutProfilingStatusData, PutProfilingStatusResponse, GetPropertyTypeIsUsedData, GetPropertyTypeIsUsedResponse, PostPublishedCacheRebuildResponse, GetPublishedCacheRebuildStatusResponse, PostPublishedCacheReloadResponse, GetRedirectManagementData, GetRedirectManagementResponse, GetRedirectManagementByIdData, GetRedirectManagementByIdResponse, DeleteRedirectManagementByIdData, DeleteRedirectManagementByIdResponse, GetRedirectManagementStatusResponse, PostRedirectManagementStatusData, PostRedirectManagementStatusResponse, GetRelationByRelationTypeIdData, GetRelationByRelationTypeIdResponse, GetItemRelationTypeData, GetItemRelationTypeResponse, GetRelationTypeData, GetRelationTypeResponse, GetRelationTypeByIdData, GetRelationTypeByIdResponse, GetItemScriptData, GetItemScriptResponse, PostScriptData, PostScriptResponse, GetScriptByPathData, GetScriptByPathResponse, DeleteScriptByPathData, DeleteScriptByPathResponse, PutScriptByPathData, PutScriptByPathResponse, PutScriptByPathRenameData, PutScriptByPathRenameResponse, PostScriptFolderData, PostScriptFolderResponse, GetScriptFolderByPathData, GetScriptFolderByPathResponse, DeleteScriptFolderByPathData, DeleteScriptFolderByPathResponse, GetTreeScriptAncestorsData, GetTreeScriptAncestorsResponse, GetTreeScriptChildrenData, GetTreeScriptChildrenResponse, GetTreeScriptRootData, GetTreeScriptRootResponse, GetSearcherData, GetSearcherResponse, GetSearcherBySearcherNameQueryData, GetSearcherBySearcherNameQueryResponse, GetSecurityConfigurationResponse, PostSecurityForgotPasswordData, PostSecurityForgotPasswordResponse, PostSecurityForgotPasswordResetData, PostSecurityForgotPasswordResetResponse, PostSecurityForgotPasswordVerifyData, PostSecurityForgotPasswordVerifyResponse, GetSegmentData, GetSegmentResponse, GetServerConfigurationResponse, GetServerInformationResponse, GetServerStatusResponse, GetServerTroubleshootingResponse, GetServerUpgradeCheckResponse, GetItemStaticFileData, GetItemStaticFileResponse, GetTreeStaticFileAncestorsData, GetTreeStaticFileAncestorsResponse, GetTreeStaticFileChildrenData, GetTreeStaticFileChildrenResponse, GetTreeStaticFileRootData, GetTreeStaticFileRootResponse, GetItemStylesheetData, GetItemStylesheetResponse, PostStylesheetData, PostStylesheetResponse, GetStylesheetByPathData, GetStylesheetByPathResponse, DeleteStylesheetByPathData, DeleteStylesheetByPathResponse, PutStylesheetByPathData, PutStylesheetByPathResponse, PutStylesheetByPathRenameData, PutStylesheetByPathRenameResponse, PostStylesheetFolderData, PostStylesheetFolderResponse, GetStylesheetFolderByPathData, GetStylesheetFolderByPathResponse, DeleteStylesheetFolderByPathData, DeleteStylesheetFolderByPathResponse, GetTreeStylesheetAncestorsData, GetTreeStylesheetAncestorsResponse, GetTreeStylesheetChildrenData, GetTreeStylesheetChildrenResponse, GetTreeStylesheetRootData, GetTreeStylesheetRootResponse, GetTagData, GetTagResponse, GetTelemetryData, GetTelemetryResponse, GetTelemetryLevelResponse, PostTelemetryLevelData, PostTelemetryLevelResponse, GetItemTemplateData, GetItemTemplateResponse, GetItemTemplateSearchData, GetItemTemplateSearchResponse, PostTemplateData, PostTemplateResponse, GetTemplateByIdData, GetTemplateByIdResponse, DeleteTemplateByIdData, DeleteTemplateByIdResponse, PutTemplateByIdData, PutTemplateByIdResponse, GetTemplateConfigurationResponse, PostTemplateQueryExecuteData, PostTemplateQueryExecuteResponse, GetTemplateQuerySettingsResponse, GetTreeTemplateAncestorsData, GetTreeTemplateAncestorsResponse, GetTreeTemplateChildrenData, GetTreeTemplateChildrenResponse, GetTreeTemplateRootData, GetTreeTemplateRootResponse, PostTemporaryFileData, PostTemporaryFileResponse, GetTemporaryFileByIdData, GetTemporaryFileByIdResponse, DeleteTemporaryFileByIdData, DeleteTemporaryFileByIdResponse, GetTemporaryFileConfigurationResponse, PostUpgradeAuthorizeResponse, GetUpgradeSettingsResponse, GetFilterUserData, GetFilterUserResponse, GetItemUserData, GetItemUserResponse, PostUserData, PostUserResponse, DeleteUserData, DeleteUserResponse, GetUserData, GetUserResponse, GetUserByIdData, GetUserByIdResponse, DeleteUserByIdData, DeleteUserByIdResponse, PutUserByIdData, PutUserByIdResponse, GetUserById2FaData, GetUserById2FaResponse, DeleteUserById2FaByProviderNameData, DeleteUserById2FaByProviderNameResponse, GetUserByIdCalculateStartNodesData, GetUserByIdCalculateStartNodesResponse, PostUserByIdChangePasswordData, PostUserByIdChangePasswordResponse, PostUserByIdClientCredentialsData, PostUserByIdClientCredentialsResponse, GetUserByIdClientCredentialsData, GetUserByIdClientCredentialsResponse, DeleteUserByIdClientCredentialsByClientIdData, DeleteUserByIdClientCredentialsByClientIdResponse, PostUserByIdResetPasswordData, PostUserByIdResetPasswordResponse, DeleteUserAvatarByIdData, DeleteUserAvatarByIdResponse, PostUserAvatarByIdData, PostUserAvatarByIdResponse, GetUserConfigurationResponse, GetUserCurrentResponse, GetUserCurrent2FaResponse, DeleteUserCurrent2FaByProviderNameData, DeleteUserCurrent2FaByProviderNameResponse, PostUserCurrent2FaByProviderNameData, PostUserCurrent2FaByProviderNameResponse, GetUserCurrent2FaByProviderNameData, GetUserCurrent2FaByProviderNameResponse, PostUserCurrentAvatarData, PostUserCurrentAvatarResponse, PostUserCurrentChangePasswordData, PostUserCurrentChangePasswordResponse, GetUserCurrentConfigurationResponse, GetUserCurrentLoginProvidersResponse, GetUserCurrentPermissionsData, GetUserCurrentPermissionsResponse, GetUserCurrentPermissionsDocumentData, GetUserCurrentPermissionsDocumentResponse, GetUserCurrentPermissionsMediaData, GetUserCurrentPermissionsMediaResponse, PostUserDisableData, PostUserDisableResponse, PostUserEnableData, PostUserEnableResponse, PostUserInviteData, PostUserInviteResponse, PostUserInviteCreatePasswordData, PostUserInviteCreatePasswordResponse, PostUserInviteResendData, PostUserInviteResendResponse, PostUserInviteVerifyData, PostUserInviteVerifyResponse, PostUserSetUserGroupsData, PostUserSetUserGroupsResponse, PostUserUnlockData, PostUserUnlockResponse, PostUserDataData, PostUserDataResponse, GetUserDataData, GetUserDataResponse, PutUserDataData, PutUserDataResponse, GetUserDataByIdData, GetUserDataByIdResponse, GetFilterUserGroupData, GetFilterUserGroupResponse, GetItemUserGroupData, GetItemUserGroupResponse, DeleteUserGroupData, DeleteUserGroupResponse, PostUserGroupData, PostUserGroupResponse, GetUserGroupData, GetUserGroupResponse, GetUserGroupByIdData, GetUserGroupByIdResponse, DeleteUserGroupByIdData, DeleteUserGroupByIdResponse, PutUserGroupByIdData, PutUserGroupByIdResponse, DeleteUserGroupByIdUsersData, DeleteUserGroupByIdUsersResponse, PostUserGroupByIdUsersData, PostUserGroupByIdUsersResponse, GetItemWebhookData, GetItemWebhookResponse, GetWebhookData, GetWebhookResponse, PostWebhookData, PostWebhookResponse, GetWebhookByIdData, GetWebhookByIdResponse, DeleteWebhookByIdData, DeleteWebhookByIdResponse, PutWebhookByIdData, PutWebhookByIdResponse, GetWebhookByIdLogsData, GetWebhookByIdLogsResponse, GetWebhookEventsData, GetWebhookEventsResponse, GetWebhookLogsData, GetWebhookLogsResponse } from './types.gen';
export class CultureService {
/**
@@ -1491,6 +1491,7 @@ export class DocumentService {
/**
* @param data The data for the request.
* @param data.query
+ * @param data.trashed
* @param data.skip
* @param data.take
* @param data.parentId
@@ -1504,6 +1505,7 @@ export class DocumentService {
url: '/umbraco/management/api/v1/item/document/search',
query: {
query: data.query,
+ trashed: data.trashed,
skip: data.skip,
take: data.take,
parentId: data.parentId,
@@ -2504,6 +2506,7 @@ export class DocumentTypeService {
/**
* @param data The data for the request.
* @param data.query
+ * @param data.isElement
* @param data.skip
* @param data.take
* @returns unknown OK
@@ -2515,6 +2518,7 @@ export class DocumentTypeService {
url: '/umbraco/management/api/v1/item/document-type/search',
query: {
query: data.query,
+ isElement: data.isElement,
skip: data.skip,
take: data.take
},
@@ -3498,6 +3502,7 @@ export class MediaService {
/**
* @param data The data for the request.
* @param data.query
+ * @param data.trashed
* @param data.skip
* @param data.take
* @param data.parentId
@@ -3511,6 +3516,7 @@ export class MediaService {
url: '/umbraco/management/api/v1/item/media/search',
query: {
query: data.query,
+ trashed: data.trashed,
skip: data.skip,
take: data.take,
parentId: data.parentId,
@@ -4823,6 +4829,58 @@ export class MemberService {
});
}
+ /**
+ * @param data The data for the request.
+ * @param data.id
+ * @param data.skip
+ * @param data.take
+ * @returns unknown OK
+ * @throws ApiError
+ */
+ public static getMemberByIdReferencedBy(data: GetMemberByIdReferencedByData): CancelablePromise {
+ return __request(OpenAPI, {
+ method: 'GET',
+ url: '/umbraco/management/api/v1/member/{id}/referenced-by',
+ path: {
+ id: data.id
+ },
+ query: {
+ skip: data.skip,
+ take: data.take
+ },
+ errors: {
+ 401: 'The resource is protected and requires an authentication token',
+ 403: 'The authenticated user does not have access to this resource'
+ }
+ });
+ }
+
+ /**
+ * @param data The data for the request.
+ * @param data.id
+ * @param data.skip
+ * @param data.take
+ * @returns unknown OK
+ * @throws ApiError
+ */
+ public static getMemberByIdReferencedDescendants(data: GetMemberByIdReferencedDescendantsData): CancelablePromise {
+ return __request(OpenAPI, {
+ method: 'GET',
+ url: '/umbraco/management/api/v1/member/{id}/referenced-descendants',
+ path: {
+ id: data.id
+ },
+ query: {
+ skip: data.skip,
+ take: data.take
+ },
+ errors: {
+ 401: 'The resource is protected and requires an authentication token',
+ 403: 'The authenticated user does not have access to this resource'
+ }
+ });
+ }
+
/**
* @param data The data for the request.
* @param data.id
@@ -4849,6 +4907,30 @@ export class MemberService {
});
}
+ /**
+ * @param data The data for the request.
+ * @param data.id
+ * @param data.skip
+ * @param data.take
+ * @returns unknown OK
+ * @throws ApiError
+ */
+ public static getMemberAreReferenced(data: GetMemberAreReferencedData = {}): CancelablePromise {
+ return __request(OpenAPI, {
+ method: 'GET',
+ url: '/umbraco/management/api/v1/member/are-referenced',
+ query: {
+ id: data.id,
+ skip: data.skip,
+ take: data.take
+ },
+ errors: {
+ 401: 'The resource is protected and requires an authentication token',
+ 403: 'The authenticated user does not have access to this resource'
+ }
+ });
+ }
+
/**
* @returns unknown OK
* @throws ApiError
diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts
index 5e831e2da3..a1a97aa80d 100644
--- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts
+++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts
@@ -694,6 +694,7 @@ export type DocumentReferenceResponseModel = {
name?: (string) | null;
published?: (boolean) | null;
documentType: (TrackedReferenceDocumentTypeModel);
+ variants: Array<(DocumentVariantItemResponseModel)>;
};
export type DocumentResponseModel = {
@@ -1406,6 +1407,13 @@ export enum MemberKindModel {
API = 'Api'
}
+export type MemberReferenceResponseModel = {
+ $type: string;
+ id: string;
+ name?: (string) | null;
+ memberType: (TrackedReferenceMemberTypeModel);
+};
+
export type MemberResponseModel = {
values: Array<(MemberValueResponseModel)>;
variants: Array<(MemberVariantResponseModel)>;
@@ -1751,7 +1759,7 @@ export type PagedIndexResponseModel = {
export type PagedIReferenceResponseModel = {
total: number;
- items: Array<(DefaultReferenceResponseModel | DocumentReferenceResponseModel | MediaReferenceResponseModel)>;
+ items: Array<(DefaultReferenceResponseModel | DocumentReferenceResponseModel | MediaReferenceResponseModel | MemberReferenceResponseModel)>;
};
export type PagedLanguageResponseModel = {
@@ -2407,6 +2415,12 @@ export type TrackedReferenceMediaTypeModel = {
name?: (string) | null;
};
+export type TrackedReferenceMemberTypeModel = {
+ icon?: (string) | null;
+ alias?: (string) | null;
+ name?: (string) | null;
+};
+
export type UnknownTypePermissionPresentationModel = {
$type: string;
verbs: Array<(string)>;
@@ -3357,6 +3371,7 @@ export type GetItemDocumentSearchData = {
query?: string;
skip?: number;
take?: number;
+ trashed?: boolean;
};
export type GetItemDocumentSearchResponse = ((PagedModelDocumentItemResponseModel));
@@ -3640,6 +3655,7 @@ export type GetItemDocumentTypeData = {
export type GetItemDocumentTypeResponse = (Array<(DocumentTypeItemResponseModel)>);
export type GetItemDocumentTypeSearchData = {
+ isElement?: boolean;
query?: string;
skip?: number;
take?: number;
@@ -3927,6 +3943,7 @@ export type GetItemMediaSearchData = {
query?: string;
skip?: number;
take?: number;
+ trashed?: boolean;
};
export type GetItemMediaSearchResponse = ((PagedModelMediaItemResponseModel));
@@ -4308,6 +4325,22 @@ export type PutMemberByIdData = {
export type PutMemberByIdResponse = (string);
+export type GetMemberByIdReferencedByData = {
+ id: string;
+ skip?: number;
+ take?: number;
+};
+
+export type GetMemberByIdReferencedByResponse = ((PagedIReferenceResponseModel));
+
+export type GetMemberByIdReferencedDescendantsData = {
+ id: string;
+ skip?: number;
+ take?: number;
+};
+
+export type GetMemberByIdReferencedDescendantsResponse = ((PagedReferenceByIdModel));
+
export type PutMemberByIdValidateData = {
id: string;
requestBody?: (UpdateMemberRequestModel);
@@ -4315,6 +4348,14 @@ export type PutMemberByIdValidateData = {
export type PutMemberByIdValidateResponse = (string);
+export type GetMemberAreReferencedData = {
+ id?: Array<(string)>;
+ skip?: number;
+ take?: number;
+};
+
+export type GetMemberAreReferencedResponse = ((PagedReferenceByIdModel));
+
export type GetMemberConfigurationResponse = ((MemberConfigurationResponseModel));
export type PostMemberValidateData = {
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/tracked-reference.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/tracked-reference.data.ts
index bbd02fb59b..1137b79c47 100644
--- a/src/Umbraco.Web.UI.Client/src/mocks/data/tracked-reference.data.ts
+++ b/src/Umbraco.Web.UI.Client/src/mocks/data/tracked-reference.data.ts
@@ -2,10 +2,11 @@ import type {
DefaultReferenceResponseModel,
DocumentReferenceResponseModel,
MediaReferenceResponseModel,
+ MemberReferenceResponseModel,
} from '@umbraco-cms/backoffice/external/backend-api';
export const items: Array<
- DefaultReferenceResponseModel | DocumentReferenceResponseModel | MediaReferenceResponseModel
+ DefaultReferenceResponseModel | DocumentReferenceResponseModel | MediaReferenceResponseModel | MemberReferenceResponseModel
> = [
{
$type: 'DocumentReferenceResponseModel',
@@ -17,6 +18,7 @@ export const items: Array<
icon: 'icon-document',
name: 'Simple Document Type',
},
+ variants: []
} satisfies DocumentReferenceResponseModel,
{
$type: 'DocumentReferenceResponseModel',
@@ -28,6 +30,7 @@ export const items: Array<
icon: 'icon-settings',
name: 'Image Block',
},
+ variants: []
} satisfies DocumentReferenceResponseModel,
{
$type: 'MediaReferenceResponseModel',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/info-app/global-components/workspace-info-app-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/info-app/global-components/workspace-info-app-layout.element.ts
index 3b6388299e..83a10560ff 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/info-app/global-components/workspace-info-app-layout.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/info-app/global-components/workspace-info-app-layout.element.ts
@@ -10,7 +10,9 @@ export class UmbWorkspaceInfoAppLayoutElement extends UmbLitElement {
return html`
-
+
+
+
`;
}
@@ -20,6 +22,10 @@ export class UmbWorkspaceInfoAppLayoutElement extends UmbLitElement {
uui-box {
--uui-box-default-padding: 0;
}
+
+ #container {
+ padding-left: var(--uui-size-space-4)
+ }
`,
];
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.element.ts
index 5e73b4c2e9..e1c2d80d7f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.element.ts
@@ -6,6 +6,7 @@ import {
type UmbReferenceModel,
isDocumentReference,
isMediaReference,
+ isMemberReference,
isDefaultReference,
} from '@umbraco-cms/backoffice/relations';
@@ -61,6 +62,9 @@ export class UmbDocumentReferenceTableElement extends UmbLitElement {
if (isMediaReference(item)) {
return item.mediaType.icon ?? 'icon-picture';
}
+ if (isMemberReference(item)) {
+ return item.memberType.icon ?? 'icon-user';
+ }
if (isDefaultReference(item)) {
return item.icon ?? 'icon-document';
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts
index f1c4effd40..ec4f69d43c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts
@@ -14,7 +14,7 @@ export const manifests: Array = [
{
type: 'entityAction',
alias: 'Umb.EntityAction.Media.Delete',
- name: 'Delete Media Entity Action ',
+ name: 'Delete Media Entity Action',
kind: 'deleteWithRelation',
forEntityTypes: [UMB_MEDIA_ENTITY_TYPE],
meta: {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/info-app/media-references-workspace-info-app.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/info-app/media-references-workspace-info-app.element.ts
index b1f46e6fd9..5a6151a8c4 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/info-app/media-references-workspace-info-app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/info-app/media-references-workspace-info-app.element.ts
@@ -59,10 +59,6 @@ export class UmbMediaReferencesWorkspaceInfoAppElement extends UmbLitElement {
);
}
- protected override firstUpdated(): void {
- this.#getReferences();
- }
-
async #getReferences() {
if (!this.#mediaUnique) {
throw new Error('Media unique is required');
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts
index c2e40ebfe7..cc342219ab 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts
@@ -4,6 +4,7 @@ export { UMB_MEMBER_VARIANT_CONTEXT } from './property-dataset-context/member-pr
export * from './collection/constants.js';
export * from './entity-actions/constants.js';
export * from './item/constants.js';
+export * from './reference/constants.js';
export * from './repository/constants.js';
export * from './search/constants.js';
export * from './workspace/constants.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/manifests.ts
index 933d3a563b..56072ee35b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity-actions/manifests.ts
@@ -2,18 +2,20 @@ import { UMB_MEMBER_ITEM_REPOSITORY_ALIAS } from '../item/constants.js';
import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js';
import { UMB_MEMBER_DETAIL_REPOSITORY_ALIAS } from '../repository/detail/manifests.js';
import { manifests as createManifests } from './create/manifests.js';
+import { UMB_MEMBER_REFERENCE_REPOSITORY_ALIAS } from '../reference/constants.js';
export const manifests: Array = [
{
type: 'entityAction',
- kind: 'delete',
alias: 'Umb.EntityAction.Member.Delete',
name: 'Delete Member Entity Action',
+ kind: 'deleteWithRelation',
forEntityTypes: [UMB_MEMBER_ENTITY_TYPE],
meta: {
- detailRepositoryAlias: UMB_MEMBER_DETAIL_REPOSITORY_ALIAS,
itemRepositoryAlias: UMB_MEMBER_ITEM_REPOSITORY_ALIAS,
+ detailRepositoryAlias: UMB_MEMBER_DETAIL_REPOSITORY_ALIAS,
+ referenceRepositoryAlias: UMB_MEMBER_REFERENCE_REPOSITORY_ALIAS,
},
},
...createManifests,
-];
+];
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/types.ts
index 660b7d84fc..2a105e08b4 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/types.ts
@@ -11,10 +11,19 @@ export interface UmbMemberItemModel {
icon: string;
collection: UmbReferenceByUnique | null;
};
- variants: Array;
+ variants: Array;
kind: UmbMemberKindType;
}
+export interface UmbMemberItemVariantModel {
+ name: string;
+ culture: string | null;
+}
+
+/**
+ * @deprecated Deprecated in favor of UmbMemberItemVariantModel. Will be removed in v17.0.0
+ * @interface UmbMemberVariantItemModel
+ */
export interface UmbMemberVariantItemModel {
name: string;
culture: string | null;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts
index 470f6503b3..7814ae8c8a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts
@@ -5,6 +5,7 @@ import { manifests as memberPickerModalManifests } from './components/member-pic
import { manifests as menuItemManifests } from './menu-item/manifests.js';
import { manifests as pickerManifests } from './picker/manifests.js';
import { manifests as propertyEditorManifests } from './property-editor/manifests.js';
+import { manifests as referenceManifests } from './reference/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
import { manifests as searchManifests } from './search/manifests.js';
import { manifests as workspaceManifests } from './workspace/manifests.js';
@@ -19,6 +20,7 @@ export const manifests: Array =
...menuItemManifests,
...pickerManifests,
...propertyEditorManifests,
+ ...referenceManifests,
...repositoryManifests,
...searchManifests,
...workspaceManifests,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/constants.ts
new file mode 100644
index 0000000000..41a409dec1
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/constants.ts
@@ -0,0 +1 @@
+export * from './repository/constants.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/index.ts
new file mode 100644
index 0000000000..3d76f338dd
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/index.ts
@@ -0,0 +1 @@
+export * from './repository/index.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/manifests.ts
new file mode 100644
index 0000000000..7ebbb37e12
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/manifests.ts
@@ -0,0 +1,18 @@
+import { UMB_MEMBER_WORKSPACE_ALIAS } from '../../workspace/constants.js';
+import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace';
+
+export const manifests: Array = [
+ {
+ type: 'workspaceInfoApp',
+ name: 'Member References Workspace Info App',
+ alias: 'Umb.WorkspaceInfoApp.Member.References',
+ element: () => import('./member-references-workspace-info-app.element.js'),
+ weight: 90,
+ conditions: [
+ {
+ alias: UMB_WORKSPACE_CONDITION_ALIAS,
+ match: UMB_MEMBER_WORKSPACE_ALIAS,
+ },
+ ],
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/member-references-workspace-info-app.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/member-references-workspace-info-app.element.ts
new file mode 100644
index 0000000000..23828e7026
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/info-app/member-references-workspace-info-app.element.ts
@@ -0,0 +1,161 @@
+import { UmbMemberReferenceRepository } from '../repository/index.js';
+import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../workspace/constants.js';
+import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import type { UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations';
+import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui';
+import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
+
+@customElement('umb-member-references-workspace-info-app')
+export class UmbMemberReferencesWorkspaceInfoAppElement extends UmbLitElement {
+ #itemsPerPage = 10;
+
+ #referenceRepository;
+
+ @state()
+ private _currentPage = 1;
+
+ @state()
+ private _total = 0;
+
+ @state()
+ private _items?: Array = [];
+
+ @state()
+ private _loading = true;
+
+ #workspaceContext?: typeof UMB_MEMBER_WORKSPACE_CONTEXT.TYPE;
+ #memberUnique?: UmbEntityUnique;
+
+ constructor() {
+ super();
+ this.#referenceRepository = new UmbMemberReferenceRepository(this);
+
+ this.consumeContext(UMB_MEMBER_WORKSPACE_CONTEXT, (context) => {
+ this.#workspaceContext = context;
+ this.#observeMemberUnique();
+ });
+ }
+
+ #observeMemberUnique() {
+ this.observe(
+ this.#workspaceContext?.unique,
+ (unique) => {
+ if (!unique) {
+ this.#memberUnique = undefined;
+ this._items = [];
+ return;
+ }
+
+ if (this.#memberUnique === unique) {
+ return;
+ }
+
+ this.#memberUnique = unique;
+ this.#getReferences();
+ },
+ 'umbReferencesDocumentUniqueObserver',
+ );
+ }
+
+ async #getReferences() {
+ if (!this.#memberUnique) {
+ throw new Error('Member unique is required');
+ }
+
+ this._loading = true;
+
+ const { data } = await this.#referenceRepository.requestReferencedBy(
+ this.#memberUnique,
+ (this._currentPage - 1) * this.#itemsPerPage,
+ this.#itemsPerPage,
+ );
+
+ if (!data) return;
+
+ this._total = data.total;
+ this._items = data.items;
+
+ this._loading = false;
+ }
+
+ #onPageChange(event: UUIPaginationEvent) {
+ if (this._currentPage === event.target.current) return;
+ this._currentPage = event.target.current;
+
+ this.#getReferences();
+ }
+
+ override render() {
+ if (!this._items?.length) return nothing;
+ return html`
+
+ ${when(
+ this._loading,
+ () => html``,
+ () => html`${this.#renderItems()} ${this.#renderPagination()}`,
+ )}
+
+ `;
+ }
+
+ #renderItems() {
+ if (!this._items) return;
+ return html`
+
+ ${repeat(
+ this._items,
+ (item) => item.unique,
+ (item) => html``,
+ )}
+
+ `;
+ }
+
+ #renderPagination() {
+ if (!this._total) return nothing;
+
+ const totalPages = Math.ceil(this._total / this.#itemsPerPage);
+
+ if (totalPages <= 1) return nothing;
+
+ return html`
+
+ `;
+ }
+
+ static override styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ display: contents;
+ }
+
+ uui-table-cell {
+ color: var(--uui-color-text-alt);
+ }
+
+ uui-pagination {
+ flex: 1;
+ display: inline-block;
+ }
+
+ .pagination {
+ display: flex;
+ justify-content: center;
+ margin-top: var(--uui-size-space-4);
+ }
+ `,
+ ];
+}
+
+export default UmbMemberReferencesWorkspaceInfoAppElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-member-references-workspace-info-app': UmbMemberReferencesWorkspaceInfoAppElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/manifests.ts
new file mode 100644
index 0000000000..cad6350ec8
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/manifests.ts
@@ -0,0 +1,4 @@
+import { manifests as repositoryManifests } from './repository/manifests.js';
+import { manifests as infoAppManifests } from './info-app/manifests.js';
+
+export const manifests: Array = [...repositoryManifests, ...infoAppManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/constants.ts
new file mode 100644
index 0000000000..b715312e79
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/constants.ts
@@ -0,0 +1 @@
+export const UMB_MEMBER_REFERENCE_REPOSITORY_ALIAS = 'Umb.Repository.Member.Reference';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/index.ts
new file mode 100644
index 0000000000..25fce74586
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/index.ts
@@ -0,0 +1 @@
+export * from './member-reference.repository.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/manifests.ts
new file mode 100644
index 0000000000..745fc200fc
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/manifests.ts
@@ -0,0 +1,19 @@
+import { UMB_MEMBER_REFERENCE_REPOSITORY_ALIAS } from './constants.js';
+import { UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS } from '@umbraco-cms/backoffice/repository';
+
+export const manifests: Array = [
+ {
+ type: 'repository',
+ alias: UMB_MEMBER_REFERENCE_REPOSITORY_ALIAS,
+ name: 'Member Reference Repository',
+ api: () => import('./member-reference.repository.js'),
+ },
+ {
+ type: 'dataSourceDataMapping',
+ alias: 'Umb.DataSourceDataMapping.ManagementApi.MemberReferenceResponse',
+ name: 'Member Reference Response Management Api Data Mapping',
+ api: () => import('./member-reference-response.management-api.mapping.js'),
+ forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS,
+ forDataModel: 'MemberReferenceResponseModel',
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference-response.management-api.mapping.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference-response.management-api.mapping.ts
new file mode 100644
index 0000000000..e6418503e8
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference-response.management-api.mapping.ts
@@ -0,0 +1,32 @@
+import { UMB_MEMBER_ENTITY_TYPE } from '../../entity.js';
+import type { UmbMemberReferenceModel } from './types.js';
+import type { MemberReferenceResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbDataSourceDataMapping } from '@umbraco-cms/backoffice/repository';
+
+export class UmbMemberReferenceResponseManagementApiDataMapping
+ extends UmbControllerBase
+ implements UmbDataSourceDataMapping
+{
+ async map(data: MemberReferenceResponseModel): Promise {
+ return {
+ entityType: UMB_MEMBER_ENTITY_TYPE,
+ memberType: {
+ alias: data.memberType.alias,
+ icon: data.memberType.icon,
+ name: data.memberType.name,
+ },
+ name: data.name,
+ // TODO: this is a hardcoded array until the server can return the correct variants array
+ variants: [
+ {
+ culture: null,
+ name: data.name ?? '',
+ },
+ ],
+ unique: data.id,
+ };
+ }
+}
+
+export { UmbMemberReferenceResponseManagementApiDataMapping as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.repository.ts
new file mode 100644
index 0000000000..4db055d64f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.repository.ts
@@ -0,0 +1,36 @@
+import { UmbMemberReferenceServerDataSource } from './member-reference.server.data.js';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbEntityReferenceRepository } from '@umbraco-cms/backoffice/relations';
+import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
+import type { UmbRepositoryResponse, UmbPagedModel } from '@umbraco-cms/backoffice/repository';
+
+export class UmbMemberReferenceRepository extends UmbControllerBase implements UmbEntityReferenceRepository {
+ #referenceSource: UmbMemberReferenceServerDataSource;
+
+ constructor(host: UmbControllerHost) {
+ super(host);
+ this.#referenceSource = new UmbMemberReferenceServerDataSource(this);
+ }
+
+ async requestReferencedBy(unique: string, skip = 0, take = 20) {
+ if (!unique) throw new Error(`unique is required`);
+ return this.#referenceSource.getReferencedBy(unique, skip, take);
+ }
+
+ async requestDescendantsWithReferences(unique: string, skip = 0, take = 20) {
+ if (!unique) throw new Error(`unique is required`);
+ return this.#referenceSource.getReferencedDescendants(unique, skip, take);
+ }
+
+ async requestAreReferenced(
+ uniques: Array,
+ skip?: number,
+ take?: number,
+ ): Promise>> {
+ if (!uniques || uniques.length === 0) throw new Error(`uniques is required`);
+ return this.#referenceSource.getAreReferenced(uniques, skip, take);
+ }
+}
+
+export default UmbMemberReferenceRepository;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.server.data.ts
new file mode 100644
index 0000000000..3ad6b90a6b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/member-reference.server.data.ts
@@ -0,0 +1,121 @@
+import { UMB_MEMBER_ENTITY_TYPE } from '../../entity.js';
+import { MemberService } from '@umbraco-cms/backoffice/external/backend-api';
+import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
+import type { UmbEntityReferenceDataSource, UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations';
+import type { UmbPagedModel, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
+
+/**
+ * @class UmbMemberReferenceServerDataSource
+ * @implements {UmbEntityReferenceDataSource}
+ */
+export class UmbMemberReferenceServerDataSource extends UmbControllerBase implements UmbEntityReferenceDataSource {
+ #dataMapper = new UmbManagementApiDataMapper(this);
+
+ /**
+ * Fetches the item for the given unique from the server
+ * @param {string} unique - The unique identifier of the item to fetch
+ * @param {number} skip - The number of items to skip
+ * @param {number} take - The number of items to take
+ * @returns {Promise>>} - Items that are referenced by the given unique
+ * @memberof UmbMemberReferenceServerDataSource
+ */
+ async getReferencedBy(
+ unique: string,
+ skip: number = 0,
+ take: number = 20,
+ ): Promise>> {
+ const { data, error } = await tryExecuteAndNotify(
+ this,
+ MemberService.getMemberByIdReferencedBy({ id: unique, skip, take }),
+ );
+
+ if (data) {
+ const promises = data.items.map(async (item) => {
+ return this.#dataMapper.map({
+ forDataModel: item.$type,
+ data: item,
+ fallback: async () => {
+ return {
+ ...item,
+ unique: item.id,
+ entityType: 'unknown',
+ };
+ },
+ });
+ });
+
+ const items = await Promise.all(promises);
+
+ return { data: { items, total: data.total } };
+ }
+
+ return { data, error };
+ }
+
+ /**
+ * Checks if the items are referenced by other items
+ * @param {Array} uniques - The unique identifiers of the items to fetch
+ * @param {number} skip - The number of items to skip
+ * @param {number} take - The number of items to take
+ * @returns {Promise>>} - Items that are referenced by other items
+ * @memberof UmbMemberReferenceServerDataSource
+ */
+ async getAreReferenced(
+ uniques: Array,
+ skip: number = 0,
+ take: number = 20,
+ ): Promise>> {
+ const { data, error } = await tryExecuteAndNotify(
+ this,
+ MemberService.getMemberAreReferenced({ id: uniques, skip, take }),
+ );
+
+ if (data) {
+ const items: Array = data.items.map((item) => {
+ return {
+ unique: item.id,
+ entityType: UMB_MEMBER_ENTITY_TYPE,
+ };
+ });
+
+ return { data: { items, total: data.total } };
+ }
+
+ return { data, error };
+ }
+
+ /**
+ * Returns any descendants of the given unique that is referenced by other items
+ * @param {string} unique - The unique identifier of the item to fetch descendants for
+ * @param {number} skip - The number of items to skip
+ * @param {number} take - The number of items to take
+ * @returns {Promise>>} - Any descendants of the given unique that is referenced by other items
+ * @memberof UmbMemberReferenceServerDataSource
+ */
+ async getReferencedDescendants(
+ unique: string,
+ skip: number = 0,
+ take: number = 20,
+ ): Promise>> {
+ const { data, error } = await tryExecuteAndNotify(
+ this,
+ MemberService.getMemberByIdReferencedDescendants({ id: unique, skip, take }),
+ );
+
+ if (data) {
+ const items: Array = data.items.map((item) => {
+ return {
+ unique: item.id,
+ entityType: UMB_MEMBER_ENTITY_TYPE,
+ };
+ });
+
+ return { data: { items, total: data.total } };
+ }
+
+ return { data, error };
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/types.ts
new file mode 100644
index 0000000000..bc62433db5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/reference/repository/types.ts
@@ -0,0 +1,14 @@
+import type { UmbMemberItemVariantModel } from '../../item/types.js';
+import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
+import type { TrackedReferenceMemberTypeModel } from '@umbraco-cms/backoffice/external/backend-api';
+
+export interface UmbMemberReferenceModel extends UmbEntityModel {
+ /**
+ * @deprecated use name on the variant array instead
+ * @type {(string | null)}
+ * @memberof UmbMemberReferenceModel
+ */
+ name?: string | null;
+ memberType: TrackedReferenceMemberTypeModel;
+ variants: Array;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts
index 090f63cee1..4f6e625a1c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts
@@ -8,7 +8,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/workspace';
import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace';
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
-import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type';
+import { UMB_MEMBER_TYPE_ENTITY_TYPE, UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type';
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section';
import { UMB_SETTINGS_SECTION_ALIAS } from '@umbraco-cms/backoffice/settings';
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
@@ -51,7 +51,7 @@ export class UmbMemberWorkspaceViewMemberInfoElement extends UmbLitElement imple
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
.addAdditionalPath('member-type')
.onSetup(() => {
- return { data: { entityType: 'member-type', preset: {} } };
+ return { data: { entityType: UMB_MEMBER_TYPE_ENTITY_TYPE, preset: {} } };
})
.observeRouteBuilder((routeBuilder) => {
this._editMemberTypePath = routeBuilder({});
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts
index de613acd6f..b8a2ccb8cc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts
@@ -198,6 +198,10 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement
+
+
+
+
`;
}
@@ -269,6 +273,9 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement
#left-column {
/* Is there a way to make the wrapped right column grow only when wrapped? */
flex: 9999 1 500px;
+ display: flex;
+ flex-direction: column;
+ gap: var(--uui-size-space-4);
}
#right-column {
flex: 1 1 350px;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relations/reference/types.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relations/reference/types.ts
index 599ee7559b..2567a3ece5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/relations/relations/reference/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relations/reference/types.ts
@@ -4,6 +4,7 @@ import type {
DefaultReferenceResponseModel,
DocumentReferenceResponseModel,
MediaReferenceResponseModel,
+ MemberReferenceResponseModel,
} from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbDataSourceResponse, UmbPagedModel, UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository';
@@ -13,7 +14,8 @@ export interface UmbReferenceItemModel extends UmbEntityModel {}
export type UmbReferenceModel =
| DefaultReferenceResponseModel
| DocumentReferenceResponseModel
- | MediaReferenceResponseModel;
+ | MediaReferenceResponseModel
+ | MemberReferenceResponseModel;
export interface UmbEntityReferenceRepository extends UmbApi {
requestReferencedBy(
diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relations/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relations/utils.ts
index 6d1fab486c..cfe15b7fa7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/relations/relations/utils.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relations/utils.ts
@@ -3,6 +3,7 @@ import type {
DefaultReferenceResponseModel,
DocumentReferenceResponseModel,
MediaReferenceResponseModel,
+ MemberReferenceResponseModel,
} from '@umbraco-cms/backoffice/external/backend-api';
/**
@@ -21,6 +22,14 @@ export function isMediaReference(item: UmbReferenceModel): item is MediaReferenc
return typeof (item as MediaReferenceResponseModel).mediaType !== 'undefined';
}
+/**
+ *
+ * @param item
+ */
+export function isMemberReference(item: UmbReferenceModel): item is MemberReferenceResponseModel {
+ return typeof (item as MemberReferenceResponseModel).memberType !== 'undefined';
+}
+
/**
*
* @param item
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs
index def5d3cafc..610bb87c2f 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs
@@ -225,20 +225,22 @@ public class RelationRepositoryTest : UmbracoIntegrationTest
RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias);
var relatedContentRelType =
RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedDocumentAlias);
+ var relatedMemberRelType =
+ RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMemberAlias);
- parents = repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 0, 11, out totalRecords, new[] { relatedContentRelType.Id, relatedMediaRelType.Id }).ToList();
+ parents = repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 0, 11, out totalRecords, [relatedContentRelType.Id, relatedMediaRelType.Id, relatedMemberRelType.Id]).ToList();
Assert.AreEqual(6, totalRecords);
Assert.AreEqual(6, parents.Count);
- parents = repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 1, 11, out totalRecords, new[] { relatedContentRelType.Id, relatedMediaRelType.Id }).ToList();
+ parents = repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 1, 11, out totalRecords, [relatedContentRelType.Id, relatedMediaRelType.Id, relatedMemberRelType.Id]).ToList();
Assert.AreEqual(6, totalRecords);
Assert.AreEqual(0, parents.Count);
- parents = repository.GetPagedParentEntitiesByChildId(createdContent[0].Id, 0, 6, out totalRecords, new[] { relatedContentRelType.Id, relatedMediaRelType.Id }).ToList();
+ parents = repository.GetPagedParentEntitiesByChildId(createdContent[0].Id, 0, 6, out totalRecords, [relatedContentRelType.Id, relatedMediaRelType.Id, relatedMemberRelType.Id]).ToList();
Assert.AreEqual(3, totalRecords);
Assert.AreEqual(3, parents.Count);
- parents = repository.GetPagedParentEntitiesByChildId(createdContent[0].Id, 1, 6, out totalRecords, new[] { relatedContentRelType.Id, relatedMediaRelType.Id }).ToList();
+ parents = repository.GetPagedParentEntitiesByChildId(createdContent[0].Id, 1, 6, out totalRecords, [relatedContentRelType.Id, relatedMediaRelType.Id, relatedMemberRelType.Id]).ToList();
Assert.AreEqual(3, totalRecords);
Assert.AreEqual(0, parents.Count);
}
@@ -281,15 +283,15 @@ public class RelationRepositoryTest : UmbracoIntegrationTest
var repository = CreateRepository(ScopeProvider, out _);
// Get parent entities for child id
- var parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 6, out var totalRecords)
+ var parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 9, out var totalRecords)
.ToList();
- Assert.AreEqual(6, totalRecords);
- Assert.AreEqual(6, parents.Count);
+ Assert.AreEqual(9, totalRecords);
+ Assert.AreEqual(9, parents.Count);
// Add the next page
- parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 1, 6, out totalRecords));
- Assert.AreEqual(6, totalRecords);
- Assert.AreEqual(6, parents.Count);
+ parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 1, 9, out totalRecords));
+ Assert.AreEqual(9, totalRecords);
+ Assert.AreEqual(9, parents.Count);
var contentEntities = parents.OfType().ToList();
var mediaEntities = parents.OfType().ToList();
@@ -297,7 +299,7 @@ public class RelationRepositoryTest : UmbracoIntegrationTest
Assert.AreEqual(3, contentEntities.Count);
Assert.AreEqual(3, mediaEntities.Count);
- Assert.AreEqual(0, memberEntities.Count);
+ Assert.AreEqual(3, memberEntities.Count);
// only of a certain type
parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Media.GetGuid()));
@@ -307,20 +309,22 @@ public class RelationRepositoryTest : UmbracoIntegrationTest
Assert.AreEqual(3, totalRecords);
parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Member.GetGuid()));
- Assert.AreEqual(0, totalRecords);
+ Assert.AreEqual(3, totalRecords);
// Test getting relations of specified relation types
var relatedMediaRelType =
RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias);
var relatedContentRelType =
RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedDocumentAlias);
+ var relatedMemberRelType =
+ RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMemberAlias);
- parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 6, out totalRecords, new[] { relatedContentRelType.Id, relatedMediaRelType.Id }).ToList();
- Assert.AreEqual(3, totalRecords);
- Assert.AreEqual(3, parents.Count);
+ parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 6, out totalRecords, [relatedContentRelType.Id, relatedMediaRelType.Id, relatedMemberRelType.Id]).ToList();
+ Assert.AreEqual(6, totalRecords);
+ Assert.AreEqual(6, parents.Count);
- parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 1, 6, out totalRecords, new[] { relatedContentRelType.Id, relatedMediaRelType.Id }).ToList();
- Assert.AreEqual(3, totalRecords);
+ parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 1, 6, out totalRecords, [relatedContentRelType.Id, relatedMediaRelType.Id, relatedMemberRelType.Id]).ToList();
+ Assert.AreEqual(6, totalRecords);
Assert.AreEqual(0, parents.Count);
}
}
@@ -368,6 +372,8 @@ public class RelationRepositoryTest : UmbracoIntegrationTest
RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias);
var relatedContentRelType =
RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedDocumentAlias);
+ var relatedMemberRelType =
+ RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMemberAlias);
// Relate content to media
foreach (var content in createdContent)
@@ -387,6 +393,15 @@ public class RelationRepositoryTest : UmbracoIntegrationTest
}
}
+ // Relate content to member
+ foreach (var content in createdContent)
+ {
+ foreach (var member in createdMembers)
+ {
+ RelationService.Relate(content.Id, member.Id, relatedMemberRelType);
+ }
+ }
+
// Relate members to media
foreach (var member in createdMembers)
{
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationTypeRepositoryTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationTypeRepositoryTest.cs
index 2fbf06bb6c..009a5efccd 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationTypeRepositoryTest.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationTypeRepositoryTest.cs
@@ -100,7 +100,7 @@ public class RelationTypeRepositoryTest : UmbracoIntegrationTest
var repository = CreateRepository(provider);
// Act
- var relationType = repository.Get(8) as IRelationTypeWithIsDependency;
+ var relationType = repository.Get(9) as IRelationTypeWithIsDependency;
// Assert
Assert.That(relationType, Is.Not.Null);
@@ -130,7 +130,7 @@ public class RelationTypeRepositoryTest : UmbracoIntegrationTest
Assert.That(relationTypes, Is.Not.Null);
Assert.That(relationTypes.Any(), Is.True);
Assert.That(relationTypes.Any(x => x == null), Is.False);
- Assert.That(relationTypes.Count(), Is.EqualTo(8));
+ Assert.That(relationTypes.Count(), Is.EqualTo(9));
}
}
@@ -165,7 +165,7 @@ public class RelationTypeRepositoryTest : UmbracoIntegrationTest
// Act
var exists = repository.Exists(3);
- var doesntExist = repository.Exists(9);
+ var doesntExist = repository.Exists(99);
// Assert
Assert.That(exists, Is.True);
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RelationServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RelationServiceTests.cs
index 06c39098ee..935915740b 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RelationServiceTests.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/RelationServiceTests.cs
@@ -26,6 +26,10 @@ public class RelationServiceTests : UmbracoIntegrationTest
private IMediaService MediaService => GetRequiredService();
+ private IMemberTypeService MemberTypeService => GetRequiredService();
+
+ private IMemberService MemberService => GetRequiredService();
+
private IRelationService RelationService => GetRequiredService();
[Test]
@@ -115,6 +119,39 @@ public class RelationServiceTests : UmbracoIntegrationTest
Assert.AreEqual(6, entities.Count);
}
+ [Test]
+ public void Return_List_Of_Content_Items_Where_Member_Item_Referenced()
+ {
+ var memberType = MemberTypeBuilder.CreateSimpleMemberType("testMemberType", "Test Member Type");
+ MemberTypeService.Save(memberType);
+ var member = MemberBuilder.CreateSimpleMember(memberType, "Test Member", "test@test.com", "xxxxxxxx", "testMember");
+ MemberService.Save(member);
+
+ var ct = ContentTypeBuilder.CreateTextPageContentType("richTextTest");
+ ct.AllowedTemplates = Enumerable.Empty();
+ ContentTypeService.Save(ct);
+
+ void CreateContentWithMemberRefs()
+ {
+ var content = ContentBuilder.CreateTextpageContent(ct, "my content 2", -1);
+
+ // 'bodyText' is a property with a RTE property editor which we knows automatically tracks relations
+ content.Properties["bodyText"].SetValue(@"");
+ ContentService.Save(content);
+ }
+
+ for (var i = 0; i < 6; i++)
+ {
+ CreateContentWithMemberRefs(); // create 6 content items referencing the same member
+ }
+
+ var relations = RelationService.GetByChildId(member.Id, Constants.Conventions.RelationTypes.RelatedMemberAlias).ToList();
+ Assert.AreEqual(6, relations.Count);
+
+ var entities = RelationService.GetParentEntitiesFromRelations(relations).ToList();
+ Assert.AreEqual(6, entities.Count);
+ }
+
[Test]
public void Can_Create_RelationType_Without_Name()
{
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs
index f992aa57b1..3b063ee9b0 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/TrackRelationsTests.cs
@@ -23,6 +23,10 @@ public class TrackRelationsTests : UmbracoIntegrationTestWithContent
private IMediaService MediaService => GetRequiredService();
+ private IMemberTypeService MemberTypeService => GetRequiredService();
+
+ private IMemberService MemberService => GetRequiredService();
+
private IRelationService RelationService => GetRequiredService();
// protected override void CustomTestSetup(IUmbracoBuilder builder)
@@ -42,6 +46,11 @@ public class TrackRelationsTests : UmbracoIntegrationTestWithContent
MediaService.Save(m1);
MediaService.Save(m2);
+ var memberType = MemberTypeBuilder.CreateSimpleMemberType("testMemberType", "Test Member Type");
+ MemberTypeService.Save(memberType);
+ var member = MemberBuilder.CreateSimpleMember(memberType, "Test Member", "test@test.com", "xxxxxxxx", "testMember");
+ MemberService.Save(member);
+
var template = TemplateBuilder.CreateTextPageTemplate();
FileService.SaveTemplate(template);
@@ -62,17 +71,24 @@ public class TrackRelationsTests : UmbracoIntegrationTestWithContent
hello
+
+
+
+
");
ContentService.Save(c2);
var relations = RelationService.GetByParentId(c2.Id).ToList();
- Assert.AreEqual(3, relations.Count);
+ Assert.AreEqual(4, relations.Count);
Assert.AreEqual(Constants.Conventions.RelationTypes.RelatedMediaAlias, relations[0].RelationType.Alias);
Assert.AreEqual(m1.Id, relations[0].ChildId);
Assert.AreEqual(Constants.Conventions.RelationTypes.RelatedMediaAlias, relations[1].RelationType.Alias);
Assert.AreEqual(m2.Id, relations[1].ChildId);
Assert.AreEqual(Constants.Conventions.RelationTypes.RelatedDocumentAlias, relations[2].RelationType.Alias);
Assert.AreEqual(c1.Id, relations[2].ChildId);
+ Assert.AreEqual(Constants.Conventions.RelationTypes.RelatedMemberAlias, relations[3].RelationType.Alias);
+ Assert.AreEqual(member.Id, relations[3].ChildId);
+
}
}