diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js index 2c2007dd91b0..05594115e1d2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js @@ -34,6 +34,15 @@ angular.module('umbraco.mocks'). return [200, nodes, null]; } + function returnUrlsbyUdis(status, data, headers) { + + if (!mocksUtils.checkAuth()) { + return [401, null, null]; + } + + return [200, {}, null]; + } + function returnEntitybyIdsPost(method, url, data, headers) { if (!mocksUtils.checkAuth()) { @@ -73,6 +82,10 @@ angular.module('umbraco.mocks'). .whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetByIds')) .respond(returnEntitybyIdsPost); + $httpBackend + .whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetUrlsByUdis')) + .respond(returnUrlsbyUdis); + $httpBackend .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Entity/GetAncestors')) .respond(returnEntitybyIds); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index 0b060da34bed..44be85b8fdd9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -127,6 +127,21 @@ function entityResource($q, $http, umbRequestHelper) { 'Failed to retrieve url for id:' + id); }, + getUrlsByUdis: function(udis, culture) { + var query = "culture=" + (culture || ""); + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "entityApiBaseUrl", + "GetUrlsByUdis", + query), + { + udis: udis + }), + 'Failed to retrieve url map for udis ' + udis); + }, + getUrlByUdi: function (udi, culture) { if (!udi) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index d8c7b3e76a62..7c8c1e64fbd7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -413,8 +413,13 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso var missingIds = _.difference(valueIds, renderModelIds); if (missingIds.length > 0) { - return entityResource.getByIds(missingIds, entityType).then(function (data) { + var requests = [ + entityResource.getByIds(missingIds, entityType), + entityResource.getUrlsByUdis(missingIds) + ]; + + return $q.all(requests).then(function ([data, urlMap]) { _.each(valueIds, function (id, i) { var entity = _.find(data, function (d) { @@ -422,7 +427,12 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso }); if (entity) { - addSelectedItem(entity); + + entity.url = entity.trashed + ? vm.labels.general_recycleBin + : urlMap[id]; + + addSelectedItem(entity); } }); @@ -469,26 +479,6 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso } - function setEntityUrl(entity) { - - // get url for content and media items - if (entityType !== "Member") { - entityResource.getUrl(entity.id, entityType).then(function (data) { - // update url - $scope.renderModel.forEach(function (item) { - if (item.id === entity.id) { - if (entity.trashed) { - item.url = vm.labels.general_recycleBin; - } else { - item.url = data; - } - } - }); - }); - } - - } - function addSelectedItem(item) { // set icon @@ -523,8 +513,6 @@ function contentPickerController($scope, $q, $routeParams, $location, entityReso "published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true // only content supports published/unpublished content so we set everything else to published so the UI looks correct }); - - setEntityUrl(item); } function setSortingState(items) { diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index b6bef3fd9651..0b6273e79da8 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -235,6 +235,50 @@ public HttpResponseMessage GetUrl(Udi udi, string culture = "*") return GetUrl(intId.Result, entityType, culture); } + /// + /// Get entity URLs by UDIs + /// + /// + /// A list of UDIs to lookup items by + /// + /// The culture to fetch the URL for + /// Dictionary mapping Udi -> Url + /// + /// We allow for POST because there could be quite a lot of Ids. + /// + [HttpGet] + [HttpPost] + public IDictionary GetUrlsByUdis([FromJsonPath] Udi[] udis, string culture = null) + { + if (udis == null || udis.Length == 0) + { + return new Dictionary(); + } + + // TODO: PMJ 2021-09-27 - Should GetUrl(Udi) exist as an extension method on UrlProvider/IUrlProvider (in v9) + string MediaOrDocumentUrl(Udi udi) + { + if (udi is not GuidUdi guidUdi) + { + return null; + } + + return guidUdi.EntityType switch + { + Constants.UdiEntityType.Document => UmbracoContext.UrlProvider.GetUrl(guidUdi.Guid, culture: culture ?? ClientCulture()), + // NOTE: If culture is passed here we get an empty string rather than a media item URL WAT + Constants.UdiEntityType.Media => UmbracoContext.UrlProvider.GetMediaUrl(guidUdi.Guid, culture: null), + _ => null + }; + } + + return udis + .Select(udi => new { + Udi = udi, + Url = MediaOrDocumentUrl(udi) + }).ToDictionary(x => x.Udi, x => x.Url); + } + /// /// Gets the URL of an entity ///