diff --git a/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs b/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs index 8d2dacfe56..9e82213aa5 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs @@ -109,6 +109,23 @@ namespace Umbraco.Core.Services return new ContentTypeAvailableCompositionsResults(ancestors, result); } + /// + /// Returns the list of content types the composition is used in + /// + /// + /// + /// + /// + internal static IEnumerable GetWhereCompositionIsUsedInContentTypes(this IContentTypeService ctService, + IContentTypeComposition source, + IContentTypeComposition[] allContentTypes) + { + + var sourceId = source != null ? source.Id : 0; + + // find which content types are using this composition + return allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == sourceId)).ToArray(); + } private static IContentTypeComposition[] GetAncestors(IContentTypeComposition ctype, IContentTypeComposition[] allContentTypes) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js index 3d12b4ff7d..75d26c7fac 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js @@ -348,9 +348,10 @@ } }; - + //select which resource methods to use, eg document Type or Media Type versions var availableContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getAvailableCompositeContentTypes : mediaTypeResource.getAvailableCompositeContentTypes; - var countContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getCount : mediaTypeResource.getCount; + var whereUsedContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getWhereCompositionIsUsedInContentTypes : mediaTypeResource.getWhereCompositionIsUsedInContentTypes; + var countContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getCount : mediaTypeResource.getCount; //get the currently assigned property type aliases - ensure we pass these to the server side filer var propAliasesExisting = _.filter(_.flatten(_.map(scope.model.groups, function(g) { @@ -363,7 +364,14 @@ $q.all([ //get available composite types availableContentTypeResource(scope.model.id, [], propAliasesExisting).then(function (result) { - setupAvailableContentTypesModel(result); + setupAvailableContentTypesModel(result); + }), + //get where used document types + whereUsedContentTypeResource(scope.model.id).then(function (whereUsed) { + //pass to the dialog model the content type eg documentType or mediaType + scope.compositionsDialogModel.section = scope.contentType; + //pass the list of 'where used' document types + scope.compositionsDialogModel.whereCompositionUsed = whereUsed; }), //get content type count countContentTypeResource().then(function(result) { diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js index 8bfcdfcc5a..f31550781a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js @@ -38,7 +38,37 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { query), 'Failed to retrieve data for content type id ' + contentTypeId); }, - + /** + * @ngdoc method + * @name umbraco.resources.contentTypeResource#getWhereCompositionIsUsedInContentTypes + * @methodOf umbraco.resources.contentTypeResource + * + * @description + * Returns a list of content types which use a specific composition with a given id + * + * ##usage + *
+         * contentTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
+         *    .then(function(contentTypeList) {
+         *        console.log(contentTypeList);
+         *    });
+         * 
+ * @param {Int} contentTypeId id of the composition content type to retrieve the list of the content types where it has been used + * @returns {Promise} resourcePromise object. + * + */ + getWhereCompositionIsUsedInContentTypes: function (contentTypeId) { + var query = { + contentTypeId: contentTypeId + }; + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "contentTypeApiBaseUrl", + "GetWhereCompositionIsUsedInContentTypes"), + query), + 'Failed to retrieve data for content type id ' + contentTypeId); + }, /** * @ngdoc method diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js index 090d6a1ee9..572b2ba3fd 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/mediatype.resource.js @@ -38,7 +38,38 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { query), 'Failed to retrieve data for content type id ' + contentTypeId); }, + /** + * @ngdoc method + * @name umbraco.resources.mediaTypeResource#getWhereCompositionIsUsedInContentTypes + * @methodOf umbraco.resources.mediaTypeResource + * + * @description + * Returns a list of media types which use a specific composition with a given id + * + * ##usage + *
+         * mediaTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
+         *    .then(function(mediaTypeList) {
+         *        console.log(mediaTypeList);
+         *    });
+         * 
+ * @param {Int} contentTypeId id of the composition content type to retrieve the list of the media types where it has been used + * @returns {Promise} resourcePromise object. + * + */ + getWhereCompositionIsUsedInContentTypes: function (contentTypeId) { + var query = { + contentTypeId: contentTypeId + }; + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "mediaTypeApiBaseUrl", + "GetWhereCompositionIsUsedInContentTypes"), + query), + 'Failed to retrieve data for content type id ' + contentTypeId); + }, /** * @ngdoc method * @name umbraco.resources.mediaTypeResource#getAllowedTypes diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.controller.js index 7a908a7260..7e768336a6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.controller.js @@ -1,17 +1,23 @@ (function() { "use strict"; - function CompositionsOverlay($scope) { + function CompositionsOverlay($scope,$location) { var vm = this; vm.isSelected = isSelected; + vm.openContentType = openContentType; function isSelected(alias) { if($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) { return true; } } + function openContentType(contentType, section) { + + var url = (section === "documentType" ? "/settings/documenttypes/edit/" : "/settings/mediaTypes/edit/") + contentType.id; + $location.path(url); + } } angular.module("umbraco").controller("Umbraco.Overlays.CompositionsOverlay", CompositionsOverlay); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.html index 6759da0fb4..f2d8902f9d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/compositions/compositions.html @@ -22,11 +22,16 @@ position="center"> - + - +
+
+

+ +
- \ No newline at end of file + diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index ab33d9af1b..86d8d41192 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -1521,6 +1521,9 @@ To manage your website, simply open the Umbraco back office and start adding con Allow this property value to be displayed on the member profile page tab has no sort order + + Where is this composition used? + This composition is currently used in the composition of the following content types: diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 252d63b530..1748e210ee 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -1646,6 +1646,9 @@ To manage your website, simply open the Umbraco back office and start adding con Allow this property value to be displayed on the member profile page tab has no sort order + + Where is this composition used? + This composition is currently used in the composition of the following content types: diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index bd881f7fcf..69cc785f15 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -111,6 +111,22 @@ namespace Umbraco.Web.Editors }); return Request.CreateResponse(result); } + /// + /// Returns where a particular composition has been used + /// This has been wrapped in a dto instead of simple parameters to support having multiple parameters in post request body + /// + /// + /// + [HttpPost] + public HttpResponseMessage GetWhereCompositionIsUsedInContentTypes(GetAvailableCompositionsFilter filter) + { + var result = PerformGetWhereCompositionIsUsedInContentTypes(filter.ContentTypeId, UmbracoObjectTypes.DocumentType) + .Select(x => new + { + contentType = x + }); + return Request.CreateResponse(result); + } [UmbracoTreeAuthorize( Constants.Trees.DocumentTypes, Constants.Trees.Content, diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 35ae95a069..a009fad6e7 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -113,7 +113,66 @@ namespace Umbraco.Web.Editors .ToList(); } + /// + /// Returns a list of content types where a particular composition content type is used + /// + /// Type of content Type, eg documentType or mediaType + /// Id of composition content type + /// + protected IEnumerable PerformGetWhereCompositionIsUsedInContentTypes(int contentTypeId, + UmbracoObjectTypes type) + { + IContentTypeComposition source = null; + //below is all ported from the old doc type editor and comes with the same weaknesses /insanity / magic + + IContentTypeComposition[] allContentTypes; + + switch (type) + { + case UmbracoObjectTypes.DocumentType: + if (contentTypeId > 0) + { + source = Services.ContentTypeService.GetContentType(contentTypeId); + if (source == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + } + allContentTypes = Services.ContentTypeService.GetAllContentTypes().Cast().ToArray(); + break; + + case UmbracoObjectTypes.MediaType: + if (contentTypeId > 0) + { + source = Services.ContentTypeService.GetMediaType(contentTypeId); + if (source == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + } + allContentTypes = Services.ContentTypeService.GetAllMediaTypes().Cast().ToArray(); + break; + + case UmbracoObjectTypes.MemberType: + if (contentTypeId > 0) + { + source = Services.MemberTypeService.Get(contentTypeId); + if (source == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); + } + allContentTypes = Services.MemberTypeService.GetAll().Cast().ToArray(); + break; + + default: + throw new ArgumentOutOfRangeException("The entity type was not a content type"); + } + + var contentTypesWhereCompositionIsUsed = Services.ContentTypeService.GetWhereCompositionIsUsedInContentTypes(source, allContentTypes); + return contentTypesWhereCompositionIsUsed + .Select(x => Mapper.Map(x)) + .Select(x => + { + //translate the name + x.Name = TranslateItem(x.Name); + + return x; + }) + .ToList(); + } protected string TranslateItem(string text) { if (text == null) diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index a98a2183b2..6dd2646204 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -109,7 +109,22 @@ namespace Umbraco.Web.Editors }); return Request.CreateResponse(result); } - + /// + /// Returns where a particular composition has been used + /// This has been wrapped in a dto instead of simple parameters to support having multiple parameters in post request body + /// + /// + /// + [HttpPost] + public HttpResponseMessage GetWhereCompositionIsUsedInContentTypes(GetAvailableCompositionsFilter filter) + { + var result = PerformGetWhereCompositionIsUsedInContentTypes(filter.ContentTypeId, UmbracoObjectTypes.MediaType) + .Select(x => new + { + contentType = x + }); + return Request.CreateResponse(result); + } public MediaTypeDisplay GetEmpty(int parentId) { var ct = new MediaType(parentId) {Icon = "icon-picture"};