From 0eceb3c7fcb6b36c03ebaec9d594946fb21657b7 Mon Sep 17 00:00:00 2001 From: Marc Goodson Date: Wed, 6 Jun 2018 21:35:10 +0100 Subject: [PATCH] U4-11369 - Add list of content types where a composition content type is used to compositions dialog (#2668) --- .../Services/ContentTypeServiceExtensions.cs | 19 +++++- .../components/umbgroupsbuilder.directive.js | 14 ++++- .../common/resources/contenttype.resource.js | 32 +++++++++- .../common/resources/mediatype.resource.js | 31 ++++++++++ .../compositions/compositions.controller.js | 8 ++- .../compositions/compositions.html | 13 ++-- src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 3 + .../umbraco/config/lang/en_us.xml | 3 + .../Editors/ContentTypeController.cs | 22 ++++++- .../Editors/ContentTypeControllerBase.cs | 61 ++++++++++++++++++- .../Editors/MediaTypeController.cs | 17 +++++- 11 files changed, 208 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs b/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs index ed04edc6bf..8403db7b62 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) { @@ -162,4 +179,4 @@ namespace Umbraco.Core.Services } } -} \ No newline at end of file +} 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 c0be05addf..63cddbf1bf 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 e0f9495298..2d3af2c4de 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -1652,6 +1652,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 a6c0774582..5f453075bd 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -1644,6 +1644,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 8581e28d6d..a93c4b91ce 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -133,6 +133,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, @@ -311,8 +327,8 @@ namespace Umbraco.Web.Editors { basic.Name = localizedTextService.UmbracoDictionaryTranslate(basic.Name); basic.Description = localizedTextService.UmbracoDictionaryTranslate(basic.Description); - } - + } + //map the blueprints var blueprints = Services.ContentService.GetBlueprintsForContentTypes(types.Select(x => x.Id).ToArray()).ToArray(); foreach (var basic in basics) @@ -322,7 +338,7 @@ namespace Umbraco.Web.Editors { basic.Blueprints[blueprint.Id] = blueprint.Name; } - } + } return basics; } diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index 0e699b591a..20dc316c49 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -133,7 +133,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) @@ -479,4 +538,4 @@ namespace Umbraco.Web.Editors } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index fbd2641e08..a258c987f2 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -127,7 +127,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"};